一次崩溃的堆栈
如题,在分析这个crash时,顶层调用栈显示libdispatch.dylib::unknown,无法进一步定位crash的原因。
现象原因
这种现象多半是出问题的机器系统库过于老旧,和解dmp所在机器的系统库版本不一致,导致解dmp时无法匹配该系统库
解决方法
-
捞取log后,全局搜索os_version, 找到出问题的macOS系统版本,本例中是10.14.4
-
自行到搜索引擎下载对应版本macOS镜像的dmg文件
-
下载下来后,按如下图的路径找到系统库的dylib文件:
-
把dylib拷出来,用lldb -c xxx.dmp重新加载dmp文件,然后target symbol add xxx.dylib,即可加载刚下载的dylib文件。然后重新bt就可以找到系统库的符号,如下图,是crash在系统api:dispatch_block_cancel
-
或者用atos命令也可以找到符号,这个命令是把指定的地址转换为符号,需要知道两个地址,模块加载的基地址和实际的地址:
用lldb加载dmp后,image list可以查看所有已加载的模块列表,找到需要的模块,0x00007fff5b3db000就是基地址:
bt后跟在frame #x:后面的0x00007fff5b3e16fe是实际的地址,然后运行:
atos -o path/to/dylib -arch x86_64 -l 0x00007fff5b3db000 0x00007fff5b3e16fe,也可以得到函数名:
备注,用mindump_stackwalker解出来的结果,如果最后面显示某个模块是No symbol,同样可以佐证这个模块没有被成功加载:
附:
-
有时候发现用target symbol add自己另外下载的dylib后,再bt仍然没有函数名,需要用atos手动转,转出来的是正确的,猜测可能lldb已经加载了错误的dylib,如果没有把这个错误的卸载掉,那正确的可能不会生效,暂时没有找到解法,目前先用atos手动转
-
macOS常见模块所在的路径:
系统库(以libsystem开头的)或c++库按下面路径查找:
framework相关的库:
如图:在Extensions或Frameworks目录下,注意kext文件可以右键--显示包内容
IOHIDLib在这里:
近期看了一些高版本(macOS 11.x, 12.x)的crash,发现在下载的系统镜像中已经无法找到dylib文件,猜测是苹果把这些二进制文件又做了一层压缩,所以现在如果还想解系统符号,估计只能装个和崩溃现场一模一样的系统了。