android addr2line使用

本文详细介绍了如何使用addr2line工具将NE异常的地址转换为具体的代码文件和行号,包括所需步骤及具体命令行操作,适用于解决Android系统中遇到的异常定位问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般碰到NE的异常需要通过addr2line把异常地址转成code文件和行号。

1.进入到prebuilts/gcc/linux-x86/arm/cit-arm-linux-androideabi-4.8目录,

2.把libunwind.so从\out\target\product\XXX\symbols下面去找到该库文件,并把该so拷贝到cit-arm-linux-androideabi-4.8目录。注意:这个so一定要是出问题的版本的so,即使是同个项目不同软件,都不能代替。

 3. 执行如下命令addr2line -e libunwind.so 0000e3ac

 

则可以把

// #00 pc 0000e3ac /system/lib/libunwind.so 
// #01 pc 000109f7 /system/lib/libunwind.so (_Uelf32_memory_read+178) 
// #02 pc 0000d803 /system/lib/libunwind.so 
// #03 pc 000030db /system/lib/libunwind.so (unw_map_local_create+42) 
// #04 pc 00009ca9 /system/lib/libbacktrace.so (_ZN14UnwindMapLocal5BuildEv+4) 
// #05 pc 00009d8f /system/lib/libbacktrace.so (_ZN12BacktraceMap6CreateEib+138) 
// #06 pc 0033b721 /system/lib/libart.so (_ZN3art10ThreadList4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEb+164) 
// #07 pc 0033b61f /system/lib/libart.so (_ZN3art10ThreadList14DumpForSigQuitERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE+574) 
// #08 pc 00320a8d /system/lib/libart.so (_ZN3art7Runtime14DumpForSigQuitERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE+228) 
// #09 pc 003252f7 /system/lib/libart.so (_ZN3art13SignalCatcher13HandleSigQuitEv+1394) 
// #10 pc 00324465 /system/lib/libart.so (_ZN3art13SignalCatcher3RunEPv+336) 
// #11 pc 00047fa3 /system/lib/libc.so (_ZL15__pthread_startPv+22) 
// #12 pc 00019a0d /system/lib/libc.so (__start_thread+6) 

 

用addr2line后得出:

/proc/self/cwd/external/libunwind/src/arm/Ginit.c:199 
/proc/self/cwd/external/libunwind/src/elfxx.c:75 
/proc/self/cwd/external/libunwind/src/elfxx.h:106 
/proc/self/cwd/external/libunwind/src/mi/Lmap.c:70 (discriminator 1) 
/proc/self/cwd/system/core/libbacktrace/UnwindMap.cpp:127 
/proc/self/cwd/system/core/libbacktrace/UnwindMap.cpp:157 
/proc/self/cwd/art/runtime/thread_list.cc:195 (discriminator 4) 
/proc/self/cwd/art/runtime/thread_list.cc:144 
/proc/self/cwd/art/runtime/runtime.cc:1411 
/proc/self/cwd/art/runtime/signal_catcher.cc:144 
/proc/self/cwd/art/runtime/signal_catcher.cc:215 
/proc/self/cwd/bionic/libc/bionic/pthread_create.cpp:198 (discriminator 1) 
/proc/self/cwd/bionic/libc/bionic/clone.cpp:41 (discriminator 1) 

<think>好的,我现在需要详细解释用户关于如何使用`addr2line`工具的问题。用户之前询问了一个Android应用崩溃日志的分析,我之前的回复提到了使用`addr2line`来定位崩溃代码的位置。现在用户进一步询问`addr2line`的具体使用方法,需要提供一个清晰、逐步的指导。 首先,我需要确认用户对`addr2line`的了解程度。用户可能是一位开发者,遇到Native层的崩溃问题,需要定位到具体的代码行。因此,我的回答需要涵盖`addr2line`的基本用途、使用步骤、常见参数以及可能遇到的问题。 接下来,我应该先解释`addr2line`的作用:将程序计数器地址转换为源代码的文件名和行号。这对于调试崩溃日志中的内存地址非常有用,尤其是在处理Android NDK或原生库的崩溃时。 然后,分步骤说明如何使用这个工具。用户需要知道如何获取带有调试符号的库文件,因为这是`addr2line`正常工作的前提。如果库文件剥离了调试符号,`addr2line`将无法提供有用的信息。因此,我需要强调编译时保留调试符号的重要性,通常是通过在编译选项中添加`-g`。 接下来,给出具体的命令示例,例如如何针对特定的库文件和地址运行`addr2line`。同时,要说明输出结果的含义,可能包括文件名和行号,或者提示没有调试信息的情况。 还需要提到其他相关参数,比如`-f`显示函数名,`-C`用于C++符号的解码(demangle),以及`-e`指定可执行文件或库的路径。这些参数能帮助用户获得更详细的信息。 此外,用户可能在使用过程中遇到问题,比如如何获取带符号的库文件。这时需要解释在Android开发中,符号文件通常位于构建目录的`obj`或`intermediates`子目录中,或者通过NDK的`ndk-build`生成。同时,提醒用户确保使用的库文件版本与崩溃时的版本完全一致,避免因版本不一致导致地址解析错误。 最后,提供一个实际的例子,将用户之前提供的崩溃日志中的地址作为示例,展示如何应用这些步骤。这可以帮助用户更好地理解如何将理论应用到实际中,特别是在处理类似`libopencv_core.so`和`libyolov8pose.so`的崩溃时。 在整理这些信息时,要确保语言简洁明了,结构清晰,逐步引导用户完成整个过程。同时,注意使用中文,避免专业术语过于晦涩,必要时进行解释。可能还需要预见到用户的一些常见错误,如路径错误、缺少调试符号等,并在指南中给出相应的解决建议。 总结来说,我的思考过程包括: 1. 确定用户的需求和背景。 2. 解释`addr2line`的基本功能和重要性。 3. 分步骤说明使用方法,强调必要的前提条件。 4. 提供具体命令示例和参数说明。 5. 解决潜在的问题和常见错误。 6. 结合实际例子加强理解。 确保这些内容以逻辑顺序呈现,帮助用户顺利掌握`addr2line`的使用方法,从而有效调试Native层的崩溃问题。</think>--- ### **`addr2line` 工具详解** `addr2line` 是 GNU Binutils 中的一个工具,用于将程序崩溃时的 **内存地址(如堆栈中的 `pc` 地址)** 转换为对应的 **源代码文件名和行号**,帮助开发者快速定位崩溃位置。 它在调试 Android NDK 崩溃、Linux 程序崩溃或动态库(`.so`)问题时非常关键。 --- ### **使用场景** 当程序崩溃时,日志中会显示类似以下信息: ``` #01 pc 00000000000dd878 /path/to/libxxx.so (cv::Mat::copyTo+1036) ``` - **`00000000000dd878`** 是崩溃时的指令地址(`pc` 值)。 - **`libxxx.so`** 是崩溃发生的动态库。 你需要通过 `addr2line` 将地址 `00000000000dd878` 转换为具体的代码位置。 --- ### **使用步骤** #### **1. 准备带调试符号的库文件** - **关键前提**:必须使用 **编译时生成的带调试符号的库文件**(未剥离符号)。 - 编译时需添加 `-g` 选项保留调试信息(参考 Android NDK 的 `Android.mk` 或 `CMakeLists.txt`)。 - 如果使用 Release 模式构建,默认会剥离符号,此时需从构建中间目录获取未剥离的 `.so` 文件(通常位于 `obj/local/` 或 `intermediates` 目录)。 #### **2. 运行 `addr2line` 命令** **基本命令格式**: ```bash addr2line -e <带符号的库文件> <内存地址> ``` **示例**: ```bash addr2line -e libopencv_core.so 00000000000dd878 ``` - **输出结果**: - 如果成功,会显示 **源代码文件路径和行号**,例如: `/home/user/opencv/modules/core/src/matrix.cpp:123` - 如果失败,显示 `??:0`(原因通常是库文件未包含调试信息)。 #### **3. 常用参数** | 参数 | 作用 | |------|------| | `-e <文件>` | 指定目标库或可执行文件(必需) | | `-f` | 同时显示函数名(帮助确认调用栈层级) | | `-C` | 解码(demangle)C++ 符号(显示易读的函数名) | | `-a <地址>` | 直接指定要转换的地址(可省略,直接写在命令末尾) | **完整示例**: ```bash addr2line -e libyolov8pose.so -f -C 00000000000acdf8 ``` 输出可能为: ``` open_media /path/to/yolov8pose.cpp:567 ``` --- ### **常见问题解决** #### **问题1:输出 `??:0`** - **原因**:库文件不包含调试符号。 - **解决**: 1. 检查是否使用了带 `-g` 编译选项生成的库文件。 2. 确保未使用 `strip` 命令剥离符号。 3. Android 开发中,检查 NDK 构建目录下的 `obj/local/<abi>/` 是否保留未剥离的 `.so`。 #### **问题2:地址转换不准确** - **原因**:库文件版本与崩溃时的版本不一致。 - **解决**:确保 `addr2line` 使用的 `.so` 文件与崩溃时的二进制文件完全一致(编译时间、代码版本相同)。 --- ### **实际案例** 假设崩溃日志中显示: ``` #05 pc 00000000000acdf8 /data/app/.../base.apk!libyolov8pose.so (open_media+808) ``` **操作步骤**: 1. 从构建目录获取带符号的 `libyolov8pose.so`。 2. 运行命令: ```bash addr2line -e libyolov8pose.so 00000000000acdf8 ``` 3. 输出结果指向代码位置,例如: `src/video_processor.cpp:208` 表示崩溃发生在该文件的第 208 行。 --- ### **总结** - **核心作用**:将内存地址映射到源代码位置。 - **关键依赖**:带调试符号的库文件。 - **扩展工具**:结合 `ndk-stack` 可批量解析整个崩溃堆栈。 - **典型用途**:调试 Android NDK 崩溃、Linux 程序段错误(Segmentation Fault)等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值