使用GDB映射Android崩溃栈地址至代码行遇异常问题咨询
崩溃地址与符号不匹配问题分析
问题背景
崩溃栈信息
#01 pc 00025b85 /system_ext/lib/libsn100nfc_nci_jni.so (android::nfaDeviceManagementCallback(unsigned char, tNFA_DM_CBACK_DATA*)+792) (BuildId: 49a45aec53f191b56d0e9b3249ebe94d)
本地SO文件信息
$ file libsn100nfc_nci_jni.so libsn100nfc_nci_jni.so: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[md5/uuid]=56ba6d380faffef52b19484b178b44b0, with debug_info, not stripped
GDB查询异常结果
$ gdb libsn100nfc_nci_jni.so Reading symbols from libsn100nfc_nci_jni.so... (gdb) info symbol 0x00025b85 xmlSoL + 53 in section .rodata (gdb) info line *0x00025b85
函数地址查询结果
(gdb) info address android::nfaDeviceManagementCallback Symbol "android::nfaDeviceManagementCallback(unsigned char, tNFA_DM_CBACK_DATA*)" is a function at address 0x2d294.
疑问
- 为何崩溃地址处于
.rodata段? - 函数地址为
0x2d294,但崩溃栈显示的地址0x00025b85却小于函数地址,这是怎么回事?
问题分析与解答
核心原因:SO版本不匹配
崩溃栈中的SO和你本地用于调试的SOBuildID完全不同,这意味着两者是不同版本的库文件,编译后的内存布局、符号偏移存在本质差异,导致地址解析完全错误。
1. 崩溃地址落在.rodata段的解释
不同版本的SO,代码段(.text)、只读数据段(.rodata)的地址范围和内容布局完全不同。你用本地SO去解析另一版本SO的崩溃地址,自然会映射到错误的段上,出现“崩溃地址在.rodata”的异常结果。
2. 崩溃地址小于函数地址的解释
崩溃栈中的+792表示崩溃点是android::nfaDeviceManagementCallback函数起始地址偏移792字节的位置,对应版本SO中该函数的起始地址应为0x25b85 - 792 = 0x25849,而你本地SO中该函数的起始地址是0x2d294,这是两个版本SO编译后函数布局差异导致的,并非崩溃地址真的小于函数起始地址。
解决方法
- 必须获取与崩溃栈中BuildID(
49a45aec53f191b56d0e9b3249ebe94d)完全匹配的SO文件,再用GDB解析地址才能得到正确的符号信息。 - 如果无法直接获取对应版本SO,可以尝试从对应固件包中提取,或者联系厂商获取匹配的符号文件。
内容的提问来源于stack exchange,提问作者lucky1928
相关产品推荐
相关产品推荐

