背景

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

呃…(内心无语)

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

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

思路一

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

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

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

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

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

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

--host参数设置,一般情况下,填为目标架构-操作系统,按此理解我们就应该填aarch64-android。但是我们会遇到下面的异常:

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说明文档。如下:

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系统的编译。最终执行以下命令:

./configure --prefix=/data/local/Inst --host=aarch64-unknown-linux --target=aarch64-unknown-linux

编译过程中遇到的问题

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

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

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

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

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位工具编译失败

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

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

最终编译成功。

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

/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。

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

推荐文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: