iOS崩溃调用栈不同十六进制地址含义及问题源码行号定位方法
崩溃调用栈地址含义与iOS平台源码定位方法
参考崩溃栈原文
==8587==ERROR: AddressSanitizer: heap-use-after-free on address 0x611000112680 at pc 0x000124c4c2e5 bp 0x700003c58130 sp 0x700003c58128 READ of size 8 at 0x611000112680 thread T32 #0 0x124c4c2e4 in fun1(param1,param2, param3)+0xac4 (TestApp:x86_64+0x122eba2e4) #1 0x124c4d88a in fun2(param1)+0x29a (TestApp:x86_64+0x122ebb88a)
加粗标注的十六进制地址含义
0x124c4c2e4:进程虚拟内存中的运行时绝对指令地址,对应#0栈帧的代码执行位置,是App开启ASLR(地址空间布局随机化)后加载到内存的实际访问地址,和崩溃头部记录的pc寄存器值差1字节,属于x86_64架构下调用指令压栈返回地址的正常偏移。0xac4:函数内偏移,即触发崩溃的指令距离fun1函数入口内存地址的字节偏移为0xac4。0x122eba2e4:二进制镜像固定偏移,是该指令相对于TestApp可执行文件原始基址的偏移,不受ASLR随机加载影响,是符号化解析时的稳定参考值。
iOS平台定位精确源码行号的方法
iOS平台无法直接使用Linux的addr2line工具,需使用Xcode内置的atos命令完成地址到源码行号的转换,操作流程如下:
- 前置校验:准备和崩溃安装包完全匹配的三个产物:崩溃日志、对应版本的TestApp可执行文件、对应版本的dSYM符号文件。使用
dwarfdump --uuid命令校验三者UUID完全一致,否则解析结果无效。 - 计算加载基址:运行时加载基址 = 栈帧运行时绝对地址 - 对应二进制固定偏移,以本次#0栈帧为例,加载基址为
0x124c4c2e4 - 0x122eba2e4 = 0x2062000。 - 执行解析命令:
atos命令基础格式如下
atos -arch <CPU架构> -o <dSYM包内DWARF文件路径> -l <运行时加载基址> <待解析的栈帧绝对地址>
针对本次x86_64架构的模拟器崩溃,实际执行命令参考:
atos -arch x86_64 -o TestApp.app.dSYM/Contents/Resources/DWARF/TestApp -l 0x2062000 0x124c4c2e4
命令执行后会直接输出对应代码的文件名、所属函数、精确行号。如果是真机arm64/arm64e架构的崩溃,仅需将-arch参数替换为对应真机架构即可。
补充:如果崩溃触发时设备已连接Xcode,且Xcode本地存有对应版本的App二进制和dSYM文件,Xcode会自动完成符号化,无需手动执行命令。
内容的提问来源于stack exchange,提问作者Law Kumar
相关产品推荐
相关产品推荐

