安卓平台valgrind交叉编译

背景

通过上次的文章valgrind跨平台调试及其问题分析,为同事们在大部分平台下进行内存问题分析提供了帮助。但是也遇到了阻塞情况:android 平台,无法交叉编译通过。大家对于编译这件事,似乎天然有一种排斥,本能的拒绝,很少会去研究。只会淡淡的说一句"艺华,按照你的文档操作,我编译不过啊"。

呃...(内心无语)

短暂无语后,只能说:我来看看吧。

这次遇到的问题,个人感觉还是挺麻烦的。虽然最终的解决是解决掉了,但也是换了一个思路,投机取巧。本文我会将两者思路都进行描述,针对第一种方式,有知道原因的朋友,还请告知,十分感谢。若您急需答案,可以直接看方法二。

思路一

虽然该思路最终没有将问题解决,但是过程中的一些分析思路,还是希望能和大家分享。

该项目的host环境是android系统,并且客户提供的交叉编译工具链是ndk23。valgrind 的版本为3.22.0

经过上篇文章,交叉编译的流程可以简单为:

  1. export 环境变量
  2. 执行configure,检测主机系统的特性,设置编译选项,确认安装路径,生成Makefile。
  3. 执行make -j8 编译。

其中export环境变量较为简单,一般host提供交叉编译工具链时,都会进行指导。

但是其中configure的设置,可能存在一些困难:

  • --host参数设置,一般情况下,填为目标架构-操作系统,按此理解我们就应该填aarch64-android。但是我们会遇到下面的异常:
bash 复制代码
yihua@ubuntu:~/valgrind-3.22.0$ ./configure --host=aarch64-android
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for aarch64-android-strip... no
checking for strip... strip
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking whether to enable maintainer-specific portions of Makefiles... no
checking whether ln -s works... yes
checking for style of include used by make... GNU
checking for aarch64-android-gcc... /home/yihua/toolchain/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang
......
checking for perl... /usr/bin/perl
checking for gdb... /usr/bin/gdb
checking dependency style of /home/yihua/toolchain/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android30-clang... gcc3
checking for diff -u... yes
checking for a supported version of gcc... ok (clang-12.0.8)
checking build system type... x86_64-pc-linux-gnu
checking host system type... aarch64-unknown-android
checking for a supported CPU... ok (aarch64)
checking for a 64-bit only build... no
checking for a 32-bit only build... no
checking for a supported OS... no (android)
configure: error: Valgrind is operating system specific. Sorry.
yihua@ubuntu:~/valgrind-3.22.0$

如提示所示,并不支持android系统,但是官网明确表示工具支持安卓系统。

那接下来如何操作呢?

我们可以尝试看看工程中的README说明文档。如下:

bash 复制代码
yihua@ubuntu:~/valgrind-3.22.0$ ls README*
README          README.android           README_DEVELOPERS            README.freebsd  README_MISSING_SYSCALL_OR_IOCTL  README.s390
README.aarch64  README.android_emulator  README_DEVELOPERS_processes  README.mips     README_PACKAGERS                 README.solaris
yihua@ubuntu:~/valgrind-3.22.0$

可知文件README.android指导了如何进行android系统的编译。最终执行以下命令:

bash 复制代码
./configure --prefix=/data/local/Inst --host=aarch64-unknown-linux --target=aarch64-unknown-linux 

编译过程中遇到的问题

configure将准备工作安排好后,则进行编译。由于工具链的不同,也遇到了一些问题。

问题一:__builtin_longjmp is not supported for the current target;

因为valgrind 中会用到非局部跳转函数setjmplongjmp函数,但是clang并不支持这两个函数的实现,因此报了这样的错误。

这种错误的解决方式,只有在工程中手写函数实现。可参考Build arm64 target valgrind with simplified bionic setjmp.S。由于该解决思路较早,与当前的valgrind版本不匹配,修改方式略有差异。但是其核心思想:实现setjmplongjmp。大家可以抄作业:我修改了以下文件。

C 复制代码
coregrind/Makefile.am
coregrind/Makefile.in
coregrind/m_gdbserver/setjmp.S
include/pub_tool_libcsetjmp.h

资源下载可能需要收费,若有需要可私信我,我发你

再重新执行configure,编译

问题二:typedef redefinition with different types ('struct Elf32_Nhdr' vs 'struct elf32_note')

这个问题是因为结构体重复定义导致的。因为ndk23的工具链中已经有该结构的定义,因此该文件不再需要,注释掉即可。

问题三:ld: error: unable to find library -lgcc

由图可知,在编译memcheck工具时,需要链接libgcc.a静态库,但是ndk23工具链中并没有该库。我们可以尝试在Makefile 中去除该依赖

问题四:32位工具编译失败

在问题一中,我添加了setjmplongjmp的实现,但那仅针对于64bit版本。因此在编译32bit 软件时,会出现该问题。因为我的host主机是64bit,因此我就没有添加32bit 的 setjmplongjmp。而是修改Makefile,不编译32bit版本。

后续编译其它工具也会出现类似错误,但是此时memcheck已经编译成功。于是我则修改上层Makefile,不编译其它工具。

最终编译成功。

但是在目标机调试时会出现断言错误,输出如下:

bash 复制代码
/bin/valgrind --tool=memcheck --leak-check=full  --track-origins=yes ./main                                                        <
==22523== Memcheck, a memory error detector
==22523== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==22523== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==22523== Command: ./main
==22523==
WARNING: linker: Warning: "/home/yihua/valgrind-3.22.0/Inst/libexec/valgrind/vgpreload_core-arm64-linux.so" has unsupported flags DT_FLAGS_1=0x421 (ignoring unsupported flags)
WARNING: linker: Warning: "/home/yihua/valgrind-3.22.0/Inst/libexec/valgrind/vgpreload_memcheck-arm64-linux.so" has unsupported flags DT_FLAGS_1=0x421 (ignoring unsupported flags)

valgrind: m_redir.c:796 (void vgPlain_redir_add_ifunc_target(Addr, Addr)): Assertion 'old' failed.

host stacktrace:
==22523==    at 0x580DC810: show_sched_status_wrk (m_libcassert.c:407)
==22523==    by 0x580DCB7B: report_and_quit (m_libcassert.c:478)
==22523==    by 0x580DCB57: vgPlain_assert_fail (m_libcassert.c:544)
==22523==    by 0x580F5CAB: vgPlain_redir_add_ifunc_target (m_redir.c:796)
==22523==    by 0x581687A7: do_client_request (scheduler.c:2072)
==22523==    by 0x581687A7: vgPlain_scheduler (scheduler.c:1542)
==22523==    by 0x5817BEDF: thread_wrapper (syswrap-linux.c:102)
==22523==    by 0x5817BEDF: run_a_thread_NORETURN (syswrap-linux.c:155)
==22523==    by 0xFFFFFFFFFFFFFFFF: ???

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable (lwpid 22523)
==22523==    at 0x5B72448: _vgnU_ifunc_wrapper (vg_preloaded.c:147)
client stack range: [0x1FFEFFA000 0x1FFF000FFF] client SP: 0x1FFEFFD320
valgrind stack range: [0x10090B4000 0x10091B3FFF] top usage: 12304 of 1048576


Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.

If that doesn't help, please report this bug to: www.valgrind.org

In the bug report, send all the above text, the valgrind
version, and what OS and version you are using.  Thanks.

很可惜因为时间的原因,就放弃了。如果有知道原因的小伙伴,还请不吝赐教,十分感谢。

思路二

在十分困惑的时候,我在想这个版本的交叉编译工具链会出现这些问题呢?因为在之前编译arm-linux平台都是很顺利的。

能直观感受到的是,android 交叉编译用的是clang,其它linux工具链用的是gcc。于是参考clang 与 GCC 的区别文章,其中有一个见解:

于是我就想改为gcc去编译valgrind。于是乎找了一个早期版本的ndk14。android-ndk-r14b-linux-x86_64.zip

再参考valgrind跨平台调试及其问题分析,发现异常顺利,并没有报错。并且调试也是一次成功。

困扰一段时间的问题,终于解决了。完结,撒花~~~

总结

本文主要讲述了在Android平台使用ndk23交叉编译工具链编译valgrind时遇到的问题及解决方法。主要问题包括不支持Android系统、结构体重复定义、无法找到libgcc.a库以及32位工具编译失败等。作者首先尝试通过修改configure参数和解决依赖问题来解决问题,但在目标机调试时仍然遇到断言错误。随后,作者尝试使用gcc编译而非clang,并找到了一个早期版本的ndk14,最终成功编译并调试了valgrind。

有时换一个思路,也许会让你柳暗花明又一村,拥有意外收获。

相关推荐
雨白4 小时前
Jetpack系列(二):Lifecycle与LiveData结合,打造响应式UI
android·android jetpack
kk爱闹6 小时前
【挑战14天学完python和pytorch】- day01
android·pytorch·python
每次的天空7 小时前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭8 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日9 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安9 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑9 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟13 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡14 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi0014 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体