Valgrind/Massif 交叉编译与部署指南
概述
在 Ubuntu 22.04 x86_64 主机上,使用 Rockchip aarch64 交叉编译工具链编译 Valgrind 3.22.0 (含 Massif 堆分析工具),并部署到 ARM64 开发板的完整步骤。
环境信息
编译主机 (Ubuntu 22.04)
- 系统: Ubuntu 22.04 x86_64, Kernel 6.8.0
- 交叉编译器: aarch64-rockchip-linux-gnu-gcc 9.3.0 (Buildroot)
- 工具链路径:
/opt/zlg/m3568-sdk-v1.0.0-ga/gcc-buildroot-9.3.0-2020.03-x86_64_aarch64-rockchip-linux-gnu/
目标 ARM 板 (Rockchip RK3568 M3568)
- 系统: Linux 4.19.193 aarch64
- glibc: 2.29
- 无 gcc/valgrind (最小化嵌入式系统)
步骤一:安装编译依赖
在 Ubuntu 主机上安装 autotools 等构建工具:
bash
sudo apt-get update
sudo apt-get install -y automake autoconf libtool make wget
步骤二:下载 Valgrind 源码
bash
cd /tmp
wget https://sourceware.org/pub/valgrind/valgrind-3.22.0.tar.bz2
tar xjf valgrind-3.22.0.tar.bz2
步骤三:配置交叉编译环境
关键点 : 交叉编译器需要 libisl.so.15,必须设置 LD_LIBRARY_PATH。
bash
# 设置交叉编译器环境变量
export CROSS_COMPILE=/opt/zlg/m3568-sdk-v1.0.0-ga/gcc-buildroot-9.3.0-2020.03-x86_64_aarch64-rockchip-linux-gnu/bin/aarch64-rockchip-linux-gnu-
# 关键: 设置 LD_LIBRARY_PATH,否则 cc1 会报 libisl.so.15 找不到
export LD_LIBRARY_PATH=/opt/zlg/m3568-sdk-v1.0.0-ga/gcc-buildroot-9.3.0-2020.03-x86_64_aarch64-rockchip-linux-gnu/lib:$LD_LIBRARY_PATH
验证编译器是否可用:
bash
echo 'int main(){return 0;}' > /tmp/test.c
${CROSS_COMPILE}gcc /tmp/test.c -o /tmp/test
file /tmp/test
# 应输出: ELF 64-bit LSB executable, ARM aarch64
步骤四:配置 Valgrind
bash
cd /tmp/valgrind-3.22.0
./configure \
--host=aarch64-rockchip-linux-gnu \
--prefix=/opt/massif \
CC="${CROSS_COMPILE}gcc" \
CXX="${CROSS_COMPILE}g++" \
AR="${CROSS_COMPILE}ar" \
LD="${CROSS_COMPILE}ld" \
RANLIB="${CROSS_COMPILE}ranlib" \
STRIP="${CROSS_COMPILE}strip" \
--enable-only64bit
configure 成功后应看到:
Primary build target: ARM64_LINUX
Version: 3.22.0
步骤五:编译
bash
make -j$(nproc)
步骤六:安装到临时目录
bash
make install DESTDIR=/tmp/valgrind-install
步骤七:精简安装包 (可选但推荐)
strip 二进制文件并删除开发文件,从 210M 精简到 23M:
bash
STRIP=${CROSS_COMPILE}strip
# Strip ELF 二进制文件
for f in /tmp/valgrind-install/opt/massif/bin/*; do
file "$f" | grep -q "ELF" && $STRIP "$f"
done
for f in /tmp/valgrind-install/opt/massif/libexec/valgrind/*; do
file "$f" | grep -q "ELF" && $STRIP "$f"
done
# 删除运行时不需要的文件
rm -rf /tmp/valgrind-install/opt/massif/include
rm -rf /tmp/valgrind-install/opt/massif/lib/pkgconfig
rm -rf /tmp/valgrind-install/opt/massif/share/doc
rm -rf /tmp/valgrind-install/opt/massif/share/man
rm -f /tmp/valgrind-install/opt/massif/lib/valgrind/*.a
步骤八:部署到 ARM 板
bash
# 在 ARM 板上创建目录
ssh root@<ARM_IP> "mkdir -p /opt/massif"
# 拷贝文件
scp -r /tmp/valgrind-install/opt/massif/* root@<ARM_IP>:/opt/massif/
# 添加到 PATH (写入 /etc/profile 持久化)
ssh root@<ARM_IP> 'echo "export PATH=/opt/massif/bin:\$PATH" >> /etc/profile'
步骤九:验证
bash
ssh root@<ARM_IP> "
export PATH=/opt/massif/bin:\$PATH
valgrind --version
# 应输出: valgrind-3.22.0
"
使用方法
基本 Massif 堆分析
bash
# 运行 massif 分析程序的堆内存使用
valgrind --tool=massif --massif-out-file=/tmp/massif.out ./your_program
# 查看分析结果
ms_print /tmp/massif.out
常用 Massif 参数
bash
# 设置快照间隔 (默认基于指令数)
valgrind --tool=massif --time-unit=ms ./your_program
# 跟踪栈内存 (默认只跟踪堆)
valgrind --tool=massif --stacks=yes ./your_program
# 设置分析粒度
valgrind --tool=massif --detailed-freq=1 ./your_program
# 设置堆分析深度
valgrind --tool=massif --depth=10 ./your_program
# 监控特定分配函数
valgrind --tool=massif --alloc-fn=my_alloc ./your_program
其他可用工具
由于安装的是完整 Valgrind,以下工具也可使用:
- memcheck : 内存错误检测 (
valgrind --tool=memcheck ./program) - cachegrind : 缓存分析 (
valgrind --tool=cachegrind ./program) - callgrind : 调用图分析 (
valgrind --tool=callgrind ./program) - helgrind : 线程错误检测 (
valgrind --tool=helgrind ./program) - drd : 线程错误检测 (
valgrind --tool=drd ./program) - dhat : 动态堆分析 (
valgrind --tool=dhat ./program)
移植到其他 ARM 板
前提条件
目标板需满足:
- 架构: aarch64 (ARM 64-bit)
- glibc: >= 2.29
- 内核: >= 4.19
快速移植步骤
bash
# 1. 在当前 ARM 板上打包
ssh root@<SOURCE_ARM_IP> "cd /opt && tar czf /tmp/massif-aarch64.tar.gz massif/"
# 2. 拷贝到本机
scp root@<SOURCE_ARM_IP>:/tmp/massif-aarch64.tar.gz /tmp/
# 3. 拷贝到目标板
scp /tmp/massif-aarch64.tar.gz root@<TARGET_ARM_IP>:/tmp/
# 4. 在目标板上解压
ssh root@<TARGET_ARM_IP> "cd /opt && tar xzf /tmp/massif-aarch64.tar.gz"
# 5. 添加到 PATH
ssh root@<TARGET_ARM_IP> 'echo "export PATH=/opt/massif/bin:\$PATH" >> /etc/profile'
# 6. 验证
ssh root@<TARGET_ARM_IP> "export PATH=/opt/massif/bin:\$PATH && valgrind --version"
安装目录结构
/opt/massif/ (总大小约 23M)
├── bin/ (可执行文件)
│ ├── valgrind (主程序入口)
│ ├── ms_print (massif 结果格式化输出, Perl脚本)
│ ├── vgdb (valgrind GDB 连接器)
│ ├── callgrind_annotate (callgrind 结果分析)
│ ├── callgrind_control (callgrind 控制)
│ ├── cg_annotate (cachegrind 结果分析)
│ ├── cg_diff (cachegrind 结果对比)
│ ├── cg_merge (cachegrind 结果合并)
│ ├── valgrind-di-server (调试信息服务)
│ └── valgrind-listener (远程监听)
├── lib/
│ └── valgrind/ (suppression 文件等)
│ ├── default.supp
│ └── *.supp
├── libexec/
│ └── valgrind/ (工具核心文件)
│ ├── massif-arm64-linux (massif 工具核心, 静态链接)
│ ├── vgpreload_massif-arm64-linux.so
│ ├── memcheck-arm64-linux
│ ├── vgpreload_memcheck-arm64-linux.so
│ ├── cachegrind-arm64-linux
│ ├── callgrind-arm64-linux
│ ├── helgrind-arm64-linux
│ ├── drd-arm64-linux
│ ├── dhat-arm64-linux
│ ├── lackey-arm64-linux
│ ├── none-arm64-linux
│ ├── vgpreload_core-arm64-linux.so
│ └── *.xml (GDB 描述文件)
└── share/
└── valgrind/ (支持文件)
依赖说明
valgrind主程序: 动态链接,仅依赖libc.so.6(ARM 板系统自带)massif-arm64-linux等工具核心: 静态链接,无外部依赖ms_print: Perl 脚本,需要 ARM 板上有 Perl 解释器(大部分嵌入式系统都有)- 无需额外安装任何依赖库
故障排除
1. configure 报错 "C compiler cannot create executables"
原因: 缺少 libisl.so.15
解决: 设置 LD_LIBRARY_PATH 指向交叉编译工具链的 lib 目录
2. ARM 板上运行报 "Permission denied"
bash
chmod +x /opt/massif/bin/*
chmod +x /opt/massif/libexec/valgrind/*
3. ms_print 报错 "perl not found"
bash
# 检查 perl 路径
which perl
# 如果路径不是 /usr/bin/perl,修改 ms_print 第一行
4. valgrind 运行报 FATAL 错误
检查内核版本是否 >= 4.19,glibc 版本是否 >= 2.29