1 介绍

valgrind 是一套 Linux 下,开放源代码的动态调试工具集合,能够检测内存管理错误、线程 BUG 等,valgrind 由内核(core)以及基于内核的其他调试工具组成。内核类似于一个框架(framework),它模拟了一个 CPU 环境,并提供服务给其他工具;而其他工具则类似于插件 (plug-in),利用内核提供的服务完成各种特定的内存调试任务。

valgrind 包括的工具如下:

  1. Memcheck是一个内存错误检测器。 它可以帮助您使程序,尤其是那些用C和C ++编写的程序更加正确。
  2. Cachegrind是缓存和分支预测分析器。 它可以帮助您使程序运行得更快。
  3. Callgrind是一个生成缓存分析器的调用图。 它与Cachegrind有一些重叠,但也收集了Cachegrind没有的一些信息。
  4. Helgrind是一个线程错误检测器。 它可以帮助您使多线程程序更正确。
  5. DRD也是线程错误检测器。 它与Helgrind类似,但使用不同的分析技术,因此可能会发现不同的问题。
  6. Massif是一个堆分析器。 它可以帮助您使程序使用更少的内存。
  7. DHAT是一种不同类型的堆分析器。 它可以帮助您了解块寿命,块利用率和布局效率低下的问题。
  8. SGcheck是一种实验工具,可以检测堆栈和全局数组的溢出。 它的功能与Memcheck的功能互补:SGcheck发现Memcheck无法解决的问题,反之亦然。
  9. BBV是一个实验性的SimPoint基本块矢量生成器。 它对进行计算机体系结构研究和开发的人很有用。

2 交叉编译(arm-oe-linux-gnueabi)

2.1 前期准备

务必注意看自己的平台是否支持,我的设备通过检查是armv7l,是支持的。

uname -a
Linux mdm9607-perf 3.18.20 #36 PREEMPT Thu Jan 27 17:18:04 CST 2022 armv7l GNU/Linux

详情看官方介绍:Valgrind: Supported Platforms

Valgrind supports the following platforms:

  • x86/Linux: up to and including SSSE3, but not higher – no SSE4, AVX, AVX2. This target is in maintenance mode now…
  • AMD64/Linux: up to and including AVX2. This is the primary development target and tends to be well supported.
  • PPC32/Linux, PPC64/Linux, PPC64LE/Linux: up to and including Power8.
  • S390X/Linux: supported.
  • ARM/Linux: supported since ARMv7.
  • ARM64/Linux: supported for ARMv8.
  • MIPS32/Linux, MIPS64/Linux: supported.
  • X86/FreeBSD, AMD64/FreeBSD: supported since FreeBSD 11.3.
  • X86/Solaris, AMD64/Solaris, X86/illumos, AMD64/illumos: supported since Solaris 11.
  • X86/Darwin (10.5 to 10.13), AMD64/Darwin (10.5 to 10.13): supported.
  • ARM/Android, ARM64/Android, MIPS32/Android, X86/Android: supported.

On Linux, you must be running kernel 3.0 or later, and glibc 2.5.X or later.

On Mac OS X you must be running 10.9.x or later.

For details of which distributions the current release (valgrind-3.20.0) builds and runs its regression tests on, see the release notes.

下载

1、下载 valgrind (https://www.valgrind.org/downloads/或者Index of /pub/valgrind (sourceware.org))

2、解压缩,输入指令解压

 tar -jxvf valgrind-3.20.0.tar.bz2

3、进入解压后的目录中

cd valgrind-3.20.0

2.2 环境配置

先修改 configure 脚本

将 armv7* 改为 armv7*|arm
# 否则将出现configure: error: Unsupported host architecture. Sorry错误

然后按照下面执行(根据自己的交叉编译环境修改),prefix改为自己要保存的编译后的文件目录,绝对路径。

# 配置编译环境
./configure --host=arm-oe-linux-gnueabi CC=arm-oe-linux-gnueabi-gcc CPP=arm-oe-linux-gnueabi-cpp CXX=arm-oe-linux-gnueabi-g++ AR=arm-oe-linux-gnueabi-ar LD=arm-oe-linux-gnueabi-ld --prefix=$PWD/valgrind

执行结果

                Version: 3.20.0
     Maximum build arch: arm
     Primary build arch: arm
   Secondary build arch: 
               Build OS: linux
 Link Time Optimisation: no
   Primary build target: ARM_LINUX
 Secondary build target: 
       Platform variant: vanilla
  Primary -DVGPV string: -DVGPV_arm_linux_vanilla=1
     Default supp files: ./xfree-3.supp ./xfree-4.supp glibc-2.X-drd.supp glibc-2.X-helgrind.supp glibc-2.X.supp 

然后编译

make -j4
# install也可以指定目录 make -j4 install  DESTDIR=`pwd`/valgrind 
make -j4 install

会在 --prefix 指定的目录下生成四个子目录:bin、include、lib、libexec 和 share,我们需要的 valgrind 工具就在其中的bin目录下。

valgrind
├── bin # 工具可执行文件所在目录
│   ├── callgrind_annotate
│   ├── callgrind_control
│   ├── cg_annotate
│   ├── cg_diff
│   ├── cg_merge
│   ├── ms_print
│   ├── valgrind
│   ├── valgrind-di-server
│   ├── valgrind-listener
│   └── vgdb
├── include # 头文件所在目录
│   └── valgrind
├── lib # 执行所需要的库目录
│   ├── pkgconfig
│   └── valgrind
├── libexec # 包含不由用户和shell script直接执行的二进制文件,比如某些特定库需要某些可执行文件,但是这些可执行文件不是由用户直接调用或由root调用的,则它们位于libexec中
│   └── valgrind
└── share # 文档帮助文件
    ├── doc
    └── man

3 使用

3.1 拷贝到设备并设置环境变量

动态库在valgrind/libexec/valgrind里面,所以把valgrind/libexec/valgrind中所有文件拷贝到valgrind/lib,可以把不用的删掉,比如静态库之类的,然后打包bin和lib并推送到设备就行了。

# 先拷贝到/mnt/sdidk/valgrind目录下,目录自己定
tar -czvf valgrind.tar.gz valgrind/bin/* valgrind/lib/*
adb push valgrind.tar.gz /mnt/sdisk/valgrind
cd /mnt/sdisk/valgrind && tar -zxvf valgrind.tar.gz

# 然后配置环境变量,本次有效,方便直接使用命令
export PATH="$PATH:/mnt/sdisk/valgrind/bin"
# 配置工具库变量
export VALGRIND_LIB="/mnt/sdisk/valgrind/lib/valgrind"

3.2 执行

可输入以下指令测试 valgrind 是否可以正常运行,如果出现一大堆选项解释,则表示成功

valgrind --version
valgrind-3.20.0

通过检查内存泄漏的问题使用(./sample为可执行程序名,为了使valgrind发现的错误更精确,建议在编译时加上-g参数,编译优化选项请选择O0):

valgrind -v --error-limit=no --leak-check=full --tool=memcheck ./sample

3.3 运行时遇到ld-linux.so.3问题

运行检查时发现ld-linux.so.3问题,具体如下:

==31877== Memcheck, a memory error detector
==31877== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==31877== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==31877== Command: /mnt/flash/app/monitor.exe
==31877== 

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:      index
valgrind:  in an object with soname matching:   ld-linux.so.3
valgrind:  was not found whilst processing
valgrind:  symbols from the object with soname: ld-linux.so.3
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.

原因是设备中的ld-linux.so.3是strip过的,解决办法是,从交叉编译环境中找到并替换到设备中没有strip过的ld-linux.so.3解决问题。

可以通过file命令查看库是否strip过:

file ./ql-ol-crosstool/sysroots/armv7a-vfp-neon-oe-linux-gnueabi/lib/ld-2.21.so
./ql-ol-crosstool/sysroots/armv7a-vfp-neon-oe-linux-gnueabi/lib/ld-2.21.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, with debug_info, not stripped

3.4 运行选项

(1)适用于所有Valgrind工具
–tool=< name > 最常用的选项。运行 valgrind中名为toolname的工具。默认memcheck。
-h --help 显示帮助信息。
–version 显示valgrind内核的版本,每个工具都有各自的版本。
-q --quiet 安静地运行,只打印错误信息。
-v --verbose 更详细的信息, 增加错误数统计。
–trace-children=no|yes 跟踪子线程? [no]
–track-fds=no|yes 跟踪打开的文件描述?[no]
–time-stamp=no|yes 增加时间戳到LOG信息? [no]
–log-fd=< number > 输出LOG到描述符文件 [2=stderr]
–log-file=< file > 将输出的信息写入到filename.PID的文件里,PID是运行程序的进行ID
–log-file-exactly=< file > 输出LOG信息到 file
–log-file-qualifier=< VAR > 取得环境变量的值来做为输出信息的文件名。 [none]
–log-socket=ipaddr:port 输出LOG到socket ,ipaddr:port

(2)LOG信息输出
–xml=yes 将信息以xml格式输出,只有memcheck可用
–num-callers=< number > show < numbe r> callers in stack traces [12]
–error-limit=no|yes 如果太多错误,则停止显示新错误? [yes]
–error-exitcode=< number > 如果发现错误则返回错误代码 [0=disable]
–db-attach=no|yes 当出现错误,valgrind会自动启动调试器gdb。[no]
–db-command=< command > 启动调试器的命令行选项[gdb -nw %f %p]

(3)适用于Memcheck工具的相关选项:
–leak-check=no|summary|full 要求对leak给出详细信息? [summary]
–leak-resolution=low|med|high how much bt merging in leak check [low]
–show-reachable=no|yes show reachable blocks in leak check? [no]
更详细的使用信息详见帮助文件、man手册或官网:http://valgrind.org/docs/manual/manual-core.html

(4)注意:
① valgrind不会自动的检查程序的每一行代码,只会检查运行到的代码分支,所以单元测试或功能测试用例很重要;
② 可以把valgrind看成是一个sandbox,通过valgrind运行的程序实际上是运行在valgrind的sandbox中的,所以,不要测试性能,会让你失望的,建议只做功能测试
③ 编译代码时,建议增加-g -o0选项,不要使用-o1、-o2选项

4 参考

Valgrind交叉编译(踩坑)_阿木_123的博客-CSDN博客

valgrind移植到EC20平台_valgrind 编译移植_willzhang121的博客-CSDN博客

如何移植valgrind到arm开发板_valgrind 移植_黑白黑-的博客-CSDN博客

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐