交叉编译内存分析工具 valgrind3.21.0 (aarch64-linux-gnu-gcc)
交叉编译工具
编译机器: ubuntu Server 22 LTS
编译目标: ARM64 开发板
https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/aarch64-linux-gnu/
注: 如果使用7.5以上的GCC,请到ARM官网下载:https://developer.arm.com/downloads/-/gnu-a
gcc版本(7.5)需对应板子的glibc版本【这点非常重要,具体可以查gcc对应的glibc版本】
架构(aarch64-linux-gnu)需对应操作系统和SOC核架构
源码下载地址
valgrind3.21.0 https://valgrind.org/downloads/current.html
依赖:
sudo apt install automake
sudo apt install libc6-dbg
我的编译脚本
查看 valgrind3.21.0 项目里的 README.aarch64 文件可得到编译说明,然后自己再根据它写成脚本
build_valgrind3.sh
#!/bin/sh
# lopment so far was however done by cross compiling, viz:
export GCC_PATH=/your_path_for_linaro/bin
# wrote by yucloud.cnblogs.com
export CC=${GCC_PATH}/aarch64-linux-gnu-gcc
export LD=${GCC_PATH}/aarch64-linux-gnu-ld
export AR=${GCC_PATH}/aarch64-linux-gnu-ar
./autogen.sh
./configure --prefix=`pwd`/Inst --host=aarch64-unknown-linux \
--enable-only64bit
make -j4
make -j4 install
tar -czf ../valgrind_3.21.0.yucloudbuild.tgz Inst/
echo "build and tar successful at: ../valgrind_3.21.0.yucloudbuild.tgz"
把上面的GCC_PATH改成你自己的交叉编译工具链路径即可,也就是 aarch64-linux-gnu-gcc 位于的目录路径
编译后打包生成在 ``../valgrind_3.21.0.yucloudbuild.tgz`
部署
- 丢到板子上(个人习惯用scp) 然后解压
tar -xvf valgrind_3.21.0.yucloudbuild.tgz
chmod -R +x Inst/ && cp Inst/* / -rfv
export VALGRIND_LIB=/libexec/valgrind/
然后再把带有debug信息的 ld-<版本号>.so
放入板子并chmod +x
,如果不知道怎么操作,请见下文的 [### cannot be set up 报错]
使用
运行
# valgrind --tool=memcheck --leak-check=full <目标程序执行命令_可带参数>
valgrind --tool=memcheck --leak-check=full ./test
如果这里你的程序携带了完整的调试信息,那么至此就完成了。它会告诉你你的程序内存泄漏情况。
错误解决
memcheck 报错
报错信息:
valgrind: failed to start tool 'memcheck' for platform 'arm64-linux': No such file or directory
这个需要声明运行库的变量
# vi ~/.bashrc
export VALGRIND_LIB=/libexec/valgrind/
cannot be set up 报错
这个问题是程序本身没有包含所有调试信息的原因。
要么程序完全加入调试信息(包括动静态库),要不程序编译的时候加gcc参数-g调试信息,并且也把带调试信息的libc放入板子。
报错信息:
root@plnx:/tmp# export VALGRIND_LIB=/libexec/valgrind/ && valgrind --tool=memcheck --leak-check=full /run/my_exec
root@plnx:/tmp# export VALGRIND_LIB=/libexec/valgrind/ && valgrind --tool=memcheck --leak-check=full /run/my_exec
==7643== Memcheck, a memory error detector
==7643== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==7643== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==7643== Command: /run/my_exec
==7643==
valgrind: Fatal error at startup: a function redirection
valgrind: which is mandatory for this platform-tool combination
valgrind: cannot be set up. Details of the redirection are:
valgrind:
valgrind: A must-be-redirected function
valgrind: whose name matches the pattern: strlen
valgrind: in an object with soname matching: ld-linux-aarch64.so.1
valgrind: was not found whilst processing
valgrind: symbols from the object with soname: ld-linux-aarch64.so.1
valgrind:
valgrind: Possible fixes: (1, short term): install glibc's debuginfo
valgrind: package on this machine. (2, longer term): ask the packagers
valgrind: for your Linux distribution to please in future ship a non-
valgrind: stripped ld.so (or whatever the dynamic linker .so is called)
valgrind: that exports the above-named function using the standard
valgrind: calling conventions for this platform. The package you need
valgrind: to install for fix (1) is called
valgrind:
valgrind: On Debian, Ubuntu: libc6-dbg
valgrind: On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo
valgrind:
valgrind: Note that if you are debugging a 32 bit process on a
valgrind: 64 bit system, you will need a corresponding 32 bit debuginfo
valgrind: package (e.g. libc6-dbg:i386).
valgrind:
valgrind: Cannot continue -- exiting now. Sorry.
==7643== Memcheck, a memory error detector
==7643== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==7643== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==7643== Command: /run/my_exec
==7643==
valgrind: Fatal error at startup: a function redirection
valgrind: which is mandatory for this platform-tool combination
valgrind: cannot be set up. Details of the redirection are:
valgrind:
valgrind: A must-be-redirected function
valgrind: whose name matches the pattern: strlen
valgrind: in an object with soname matching: ld-linux-aarch64.so.1
valgrind: was not found whilst processing
valgrind: symbols from the object with soname: ld-linux-aarch64.so.1
valgrind:
valgrind: Possible fixes: (1, short term): install glibc's debuginfo
valgrind: package on this machine. (2, longer term): ask the packagers
valgrind: for your Linux distribution to please in future ship a non-
valgrind: stripped ld.so (or whatever the dynamic linker .so is called)
valgrind: that exports the above-named function using the standard
valgrind: calling conventions for this platform. The package you need
valgrind: to install for fix (1) is called
valgrind:
valgrind: On Debian, Ubuntu: libc6-dbg
valgrind: On SuSE, openSuSE, Fedora, RHEL: glibc-debuginfo
valgrind:
valgrind: Note that if you are debugging a 32 bit process on a
valgrind: 64 bit system, you will need a corresponding 32 bit debuginfo
valgrind: package (e.g. libc6-dbg:i386).
valgrind:
valgrind: Cannot continue -- exiting now. Sorry.
在x86主机的arm交叉编译工具链路径搜索
$ find . -name "*ld*.so"
./aarch64-linux-gnu/libc/lib/ld-2.25.so
$ file ./aarch64-linux-gnu/libc/lib/ld-
ld-2.25.so ld-linux-aarch64.so.1
$ file ./aarch64-linux-gnu/libc/lib/ld-2.25.so
./aarch64-linux-gnu/libc/lib/ld-2.25.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=73b23c16ff9fe3eab046636cd9dd6db9d3309f27, with debug_info, not stripped
然后把它放到板子上即可
chmod +x ./tmp/ld-2.25.so
export VALGRIND_LIB=/libexec/valgrind/ && valgrind --tool=memcheck --leak-check=full /tmp/ld-2.25.so /run/my_exec
效果
export VALGRIND_LIB=/libexec/valgrind && valgrind --tool=memcheck --leak-check=full /tmp/ld-2.28.so /run/my_exec
输出信息如下:
root@plnx:/tmp# export VALGRIND_LIB=/libexec/valgrind && valgrind --tool=memcheck --leak-check=full /tmp/ld-2.28.so /run/my_exec
==27913== Memcheck, a memory error detector
==27913== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==27913== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright info
==27913== Command: /tmp/ld-2.28.so /run/my_exec
==27913==
Hell World!
***************************************************************************
==27913==
==27913== HEAP SUMMARY:
==27913== in use at exit: 0 bytes in 0 blocks
==27913== total heap usage: 33 allocs, 33 frees, 90,118 bytes allocated
==27913==
==27913== All heap blocks were freed -- no leaks are possible
==27913==
==27913== For lists of detected and suppressed errors, rerun with: -s
==27913== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
可见没有泄露!
更便捷的使用
上面的命令确实参数太长了,我们可以做成脚本:
cat run_valgrind3.sh
#!/bin/sh
# tar -xvf valgrind_3.21.0.yucloudbuild.tgz && chmod -R +x Inst/ && cp Inst/* / -rfv
# chmod +x /tmp/ld-*.so
export VALGRIND_LIB=/libexec/valgrind && valgrind --tool=memcheck --leak-check=full /tmp/ld-2.28.so $@
至于为什么放在/tmp目录,因为调试是只是临时使用,真正的产品是不能带调试信息的。
运行示例
./run_valgrind3.sh your_exec your_args0 your_args1
如果需要运行程序并检测内存泄露
- 普通运行
./my_test 1 0
- 检测内存运行
./run_valgrind3.sh /my_test 1 0
附录
附上$@
的含义
$*
所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。$@
所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
另外还有其他放置运行库的方案