ndk addr2line工具的使用

addr2line是Android NDK中的一个调试工具,用于定位JNI代码中的错误。当应用因JNI错误闪退时,通过log获取异常信息,结合ndk编译输出找到对应的so文件。将so文件与addr2line工具放在同一目录,通过脚本输入异常地址,可以定位到源代码的具体行数,例如在native.cpp的75行。

addr2line是一个十分有用的debug工具,这个工具在ndk的安装目录下就有


在ndk \toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin目录下


可以用于帮助我们分析jni 里面的bug,下面我们故意在jni代码中留一个异常,在运行到memcpy就会发生空指针异常,应用会闪退。


运行之后,通过log我们得到如下信息

09-08 14:35:53.777 F/DEBUG   ( 6893): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
09-08 14:35:53.853 F/DEBUG   ( 6893): Build fingerprint: 'Android/sdk_google_phone_arm64/generic_arm64:7.1.1/NYC/4252396:userdebug/test-keys'
09-08 14:35:53.853 F/DEBUG   ( 6893): Revision: '0'
09-08 14:35:53.853 F/DEBUG   ( 6893): ABI: 'arm64'
09-08 14:35:53.854 F/DEBUG   ( 6893): pid: 6867, tid: 6867, name: hxiong.neondemo  >>> com.hxiong.neondemo <<<
09-08 14:35:53.854 F/DEBUG   ( 6893): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
09-08 14:35:53.855 F/DEBUG   ( 6893):     x0   0000000000000003  x1   0000000000000000  x2   0000000000000004  x3   0000007ffb9e6980
09-08 14:35:53.855 F/DEBUG   ( 6893):     x4   0000007329c01ad3  x5   0000007ffb9e7360  x6   0000007337196000  x7   fffffffffffffffd
09-08 14:35:53.855 F/DEBUG   ( 6893):     x8   0000000000000003  x9   0000007335738c79  x10  0000000000000058  x11  0101010101010101
09-08 14:35:53.855 F/DEBUG   ( 6893):     x12  000000000ccccccc  x13  000000008000002f  x14  00000073357429e8  x15  000000733574268c
09-08 14:35:53.855 F/DEBUG   ( 6893):     x16  000000733575e2c0  x17  00000073356b8368  x18  00000000ffffffff  x19  ffffffffffffffff
09-08 14:35:53.855 F/DEBUG   ( 6893):     x20  000000000000000e  x21  00000000ffffffff  x22  0000007ffb9e6b60  x23  0000000000000001
09-08 14:35:53.855 F/DEBUG   ( 6893):     x24  0000007329c01ae3  x25  0000000000000003  x26  0000000000000073  x27  0000007ffb9e70b0
09-08 14:35:53.856 F/DEBUG   ( 6893):     x28  6cd7b2dd5dd0d059  x29  0000007ffb9e67a0  x30  0000007335710f64
09-08 14:35:53.856 F/DEBUG   ( 6893):     sp   0000007ffb9e6790  pc   00000073356b83c8  pstate 0000000080000000
09-08 14:35:54.233 F/DEBUG   ( 6893): 
09-08 14:35:54.233 F/DEBUG   ( 6893): backtrace:
09-08 14:35:54.234 F/DEBUG   ( 6893):     #00 pc 000000000001b3c8  /system/lib64/libc.so (strlen+96)
09-08 14:35:54.234 F/DEBUG   ( 6893):     #01 pc 0000000000073f60  /system/lib64/libc.so (__strlen_chk+16)
09-08 14:35:54.234 F/DEBUG   ( 6893):     #02 pc 000000000005ba18  /system/lib64/libc.so (__vfprintf+6356)
09-08 14:35:54.234 F/DEBUG   ( 6893):     #03 pc 0000000000064be4  /system/lib64/libc.so (vsnprintf+228)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #04 pc 00000000000741a0  /system/lib64/libc.so (__vsnprintf_chk+64)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #05 pc 00000000000057c8  /system/lib64/liblog.so (__android_log_print+148)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #06 pc 00000000000009a4  /data/app/com.hxiong.neondemo-1/lib/arm64/libneondemo.so
09-08 14:35:54.235 F/DEBUG   ( 6893):     #07 pc 00000000000dbb10  /system/lib64/libart.so (art_quick_generic_jni_trampoline+144)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #08 pc 00000000000d27e8  /system/lib64/libart.so (art_quick_invoke_static_stub+600)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #09 pc 00000000000df230  /system/lib64/libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+252)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #10 pc 000000000028eefc  /system/lib64/libart.so (_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPKNS_7DexFile8CodeItemEPNS_11ShadowFrameEPNS_6JValueE+312)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #11 pc 0000000000287ed8  /system/lib64/libart.so (_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+592)
09-08 14:35:54.235 F/DEBUG   ( 6893):     #12 pc 0000000000555cec  /system/lib64/libart.so (MterpInvokeStatic+356)
09-08 14:35:54.236 F/DEBUG   ( 6893):     #13 pc 00000000000c5094  /system/lib64/libart.so (ExecuteMterpImpl+14612)

从打印的log信息我们知道发生问题时pc寄存器的值

09-08 14:35:54.235 F/DEBUG   ( 6893):     #06 pc 00000000000009a4  /data/app/com.hxiong.neondemo-1/lib/arm64/libneondemo.so

接着,我们要拿到编译出来的so文件。


根据ndk编译时的输出信息,知道so在libs/arm64-v8a/libneondemo.so


是app\src\main\obj\local\arm64-v8a这个目录,不是app\src\main\libs\arm64-v8a



然后把so拷贝到tool_addr2line.bat 这个脚本所在的目录下。脚本内容如下:

@echo off
rem current direction
set cur_dir=%cd%

rem addr2line tool path
set add2line_path=D:\Android\sdk\ndk-bundle\toolchains\aarch64-linux-android-4.9\prebuilt\windows-x86_64\bin\aarch64-linux-android-addr2line.exe

rem debug file
set /p debug_file=请输入当前目录下debug文件名:

rem debug_file_path
set debug_file_path=%cur_dir%\%debug_file%

rem debug address
set /p debug_addr=请输入异常时PC寄存器值:

echo ----------------------- addr2line ------------------------
echo debug文件路径: %debug_file_path%  PC=%debug_addr%

if exist %debug_file_path% (
%add2line_path% -e %debug_file_path% -f %debug_addr% 
) else (
echo debug file is no exist. 
)

echo ---------------------------------------------------------
pause


运行脚本,根据提示进行输入



_ZL4neonP7_JNIEnv 这个是函数名,因为android编译时做了一些特殊处理,所以跟原来的函数名不一致。

E:\project\android_project\NeonDemo\app\src\main/jni/native.cpp:75 是发生异常对应源代码中的位置。



<think> 首先,用户的问题是:“我想获取addr2line工具使用指南 请问addr2line工具使用方法”。系统级指令要求我必须使用中文回答,引用中添加引用标识,生成相关问题。 回顾引用: - 引用[1]:讨论了addr2line的作用,安装步骤等。 - 引用[2]:基本命令格式和示例。 - 引用[3]:如何使用objdump和addr2line定位源码位置。 - 引用[4]:在安卓中使用addr2line的示例。 - 引用[5]:安卓中32位和64位工具使用。 用户的问题是关于使用指南的,所以我需要提供一个清晰、结构化的方法指南。 回答结构: - 由于系统要求回答结构清晰,逐步解决问题,我需要组织成一个易于理解的指南。 - 必须使用中文。 - 在行内数学表达式中使用$...$,但这里可能不涉及数学,所以可能不需要。 - 独立公式用$$...$$,同样可能不适用。 - 引用段落末尾添加引用标识,如[^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]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值