交叉编译内存分析工具 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`

部署

  1. 丢到板子上(个人习惯用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" 的形式输出所有参数。

另外还有其他放置运行库的方案

posted @ 2023-05-26 16:00  蓝天上的云℡  阅读(683)  评论(0编辑  收藏  举报