linux64位系统 addr2line使用

博客介绍了在64位系统中,可执行文件的符号表地址与运行时地址的差异,以及如何通过动态映射地址区间来定位代码位置。通过分析`/proc/pid/smaps`获取映射信息,并利用addr2line工具进行符号定位,解决strip过的程序无法直接定位的问题。举例展示了flutter运行时的映射地址段,强调了动态库地址解析在程序调试中的重要性。

简介

64位系统运行的可执行文件的符号表地址和实际运行时地址差异甚大。
譬如使用nm查看函数的地址为0x69207,但是运行时打印函数的地址为0x7FA3333F8207

那么我们通过backtrace,手动打印,gdb,pstack获取到函数调用栈信息时,如果可执行程序是经过strip过的,打印出来将是一堆0X7F开头的大地址(0x7FA3333F8207),使用addr2line直接进行定位,显示是??:00

原因是因为0x7FA3333F8207是动态映射的虚拟地址,该虚拟地址是通过而符号表地址(0x69207)+该代码段映射区间的地址(0x7fa33338f000)得来的。

那么我们如果要得到真正的代码位置,需要知道代码段映射地址区间,以及包含符号表信息的原始可执行程序

代码段映射地址区间

代码段映射地址区间是动态生成的,所以如果要获得真是的区间信息,必须再程序运行时通过命令
cat /proc/{pid}/smaps获取完整的映射信息。如果崩溃前没有完整的信息,那肯定就没法通过addr2line定位程序崩溃位置了。

程序运行以后,我们可以通过一下命令,获取的所有代码段映射地址区间:

cat /proc/{
   
   pid}/smaps | grep 
<think> 首先,用户的问题是:“我想获取addr2line工具的使用指南 请问addr2line工具的使用方法”。系统级指令要求我必须使用中文回答,引用中添加引用标识,生成相关问题。 回顾引用: - 引用[1]:讨论了addr2line的作用,安装步骤等。 - 引用[2]:基本命令格式和示例。 - 引用[3]:如何使用objdump和addr2line源码置。 - 引用[4]:在安卓中使用addr2line的示例。 - 引用[5]:安卓中3264工具的使用。 用户的问题是关于使用指南的,所以我需要提供一个清晰、结构化的方法指南。 回答结构: - 由于系统要求回答结构清晰,逐步解决问题,我需要组织成一个易于理解的指南。 - 必须使用中文。 - 在行内数学表达式中使用$...$,但这里可能不涉及数学,所以可能不需要。 - 独立公式用$$...$$,同样可能不适用。 - 引用段落末尾添加引用标识,如[^1]。 关键点从引用中提取: 1. **定义和用途**:addr2line工具用于将内存地址转换为源代码置,这在调试中很有用。[^1] 2. **基本命令格式**:`addr2line [-e executable] address` [^2] 3. **步骤**: - 安装工具(如果是Android/Linux)。 - 获取可执行文件(如.so文件)和调试符号文件。 - 使用命令转换地址。 4. **示例**:如`addr2line -e my_program 0x4009a8` [^2] 5. **在安卓中的使用**:使用特定路径的工具,如`aarch64-linux-android-addr2line`或`arm-linux-androideabi-addr2line` [^5] 6. **注意事项**:需要编译时带有调试信息。[^3] 步骤指南: 1. **安装addr2line工具**:在Android或Linux系统中,可能需要通过包管理器安装。 2. **准备可执行文件和符号文件**:确保有目标文件(如.so文件)和对应的调试符号文件(对于Android,在symbols目录下)。[^4], [^5] 3. **基本命令结构**: - `addr2line -e <可执行文件路径> <地址>` - 选项如`-f`显示函数名,`-C` demangled名称,`-s`只显示文件名。 4. **示例操作**: - 例如,地址0x4009a8对应程序my_program:`addr2line -e my_program 0x4009a8` - 在安卓中:`./prebuilts/clang/host/linux-x86/clang-r530567/bin/llvm-addr2line -e out/target/product/rk3576_u/symbols/vendor/lib64/hw/camera.rk30board.so 0x1a102c` [^4] 5. **处理地址**:地址可能需要计算,如基地址+偏移量(参考引用[3])。 确保回答真实可靠:基于提供的引用,不添加虚假信息。 生成相关问题:在末尾添加相关问题列表,使用§§相关问题§§格式。 完整回答结构: - 先介绍工具。 - 逐步使用方法。 - 给出示例。 - 添加引用标识。 - 最后相关问题。 相关问题想法: 1. 如何安装addr2line工具在不同系统上? 2. 在Android中如何正确配置调试符号? 3. addr2line与其他调试工具(如GDB)的区别是什么? 4. 如何解决addr2line找不到源文件的问题? 5. addr2line在崩溃日志分析中的应用实例。 </think> ### addr2line工具使用指南 addr2line是一种在调试Android或Linux程序时使用的命令行工具,它能将内存地址(如崩溃日志中的地址)转换为对应的源代码文件名、行号和函数名。这在定程序错误、崩溃分析中非常有用[^1]。以下是详细的使用方法指南,基于标准操作流程,确保编译时已生成调试符号文件(如编译时添加`-g`选项)。 #### 一、准备工作 1. **安装工具**: 在Linux或Android开发环境中,通过包管理器安装: - Ubuntu/Linux:`sudo apt-get install binutils`(包含addr2line) - Android NDK:工具通常于`NDK_PATH/toolchains`目录下,如`aarch64-linux-android-addr2line` 确保工具路径已添加到`PATH`环境变量中[^1][^5]。 2. **获取必要文件**: - **可执行文件**:需调试的程序或共享库(如`.so`文件)。 - **调试符号文件**:对于Android,通常在编译输出的`symbols`目录下(如`out/target/product/设备名/symbols/`)。 注意:如果可执行文件已包含调试信息,可直接使用;否则需单独提供符号文件[^3][^4]。 #### 二、基本命令格式 addr2line命令的核心格式为: ```bash addr2line [选项] -e <可执行文件路径> <地址> ``` - **常用选项**: - `-e`:指定可执行文件路径(必需)。 - `-f`:显示函数名称。 - `-C`:Demangle C++函数名(解码混淆名称)。 - `-s`:仅显示文件名(不包括路径)。 - `-i`:显示内联函数调用链[^2][^3]。 - **地址格式**: - 直接地址:如`0x4009a8`。 - 计算地址:如果地址是偏移量,需先计算基地址+偏移量(参考`objdump -D <文件> | grep <函数名>`获取基地址)[^3]。 #### 三、使用步骤 1. **定崩溃地址**: 从程序崩溃日志或核心转储文件中提取内存地址(如`0x1a102c`)。 2. **执行addr2line命令**: - **通用示例**: ```bash addr2line -e my_program 0x4009a8 -f -C ``` 输出示例: ``` divide(int, int) /path/to/source/file.cpp:123 ``` 这表示地址`0x4009a8`对应`file.cpp`的第123行,函数名为`divide(int, int)`[^2][^3]。 - **Android平台示例**: - **64系统**: ```bash aarch64-linux-android-addr2line -f -C -e out/target/product/rk3399_box/symbols/system/lib/hw/camera.rk30board.so 0x1a102c ``` - **32系统**: ```bash arm-linux-androideabi-addr2line -f -e out/target/product/msm8909/symbols/system/lib/libhwui.so 0x0003b319 ``` 确保使用NDK提供的工具链路径(如`prebuilts/clang/host/linux-x86/bin/llvm-addr2line`)[^4][^5]。 3. **处理复杂地址**: 如果地址是相对偏移量,先用`objdump`获取函数基地址: ```bash objdump -D test_app | grep -A20 '函数名' # 输出中包含基地址如0x4005d7 ``` 然后计算实际地址:`基地址 + 偏移量`(如`0x4005d7 + 0x1e = 0x4005f5`),再输入到addr2line[^3]。 #### 四、注意事项 - **调试符号缺失**:若输出`??:0`,表示缺少调试符号文件。需重新编译程序并添加`-g`选项生成符号信息[^1][^3]。 - **安卓特定要求**:在Android中使用前,需执行`source build/envsetup.sh`和`lunch`设置环境变量[^5]。 - **性能优化**:对于大型程序,addr2line可能较慢,可使用`-i`选项限制输出层级。 通过以上步骤,您可以高效定源代码中的问题置,加速调试过程[^1][^4]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值