iOS 崩溃日志符号化

dSYM(debugging SYMbols)又称为调试符号表,是苹果为了方便调试和定位问题而使用的一种调试方案,本质上使用的是起源于贝尔实验室的DWARF(Debugging With Attributed Record Formats)
通常,我们直接从用户导出来的崩溃日志都是未符号化或者部分符号化的,都是一堆十六进制内存地址的集合,可读性较差。未符号化或者部分符号化的崩溃日志对闪退问题的解决几乎毫无帮助,如下所示:

callStackSymbols: {
0   libsystem_kernel.dylib          0x00000001ba2ce564 mach_msg_trap + 8
.....
8   UIKitCore                       0x0000000185e206c4 0x0000000185c95000 + 1619652
9   TestApp                         0x0000000102cc0eb8 _mh_execute_header + 3821240
......
23  TestApp                         0x00000001032d832c _mh_execute_header + 10208044
....
30  libsystem_pthread.dylib         0x00000001f3cc0f50 start_wqthread + 8
}

dSYM 中存储着文件名、方法名、行号等信息,是和可执行文件的16进制函数地址一一对应的,通过分析崩溃的崩溃文件可以准确知道具体的崩溃信息。

每一个版本都有相应的UUID
每一个xxx.app.dSYM,xx.app文件都拥有相应的uuid 当然 .crash文件也有uuid,只有三者uuid一至才表明之三者可以解析出正确的日志文件

xcarchive 里面看到 dSYM 文件以及目录架构
.xcarchive
--dSYMs
|--Your.app.dSYM
|--Contents
|--Resources
|--DWARF

//查uuID对应的dsym

mdfind "com_apple_xcode_dsym_uuids == 57B2B22D-CC9A-30D8-907C-91ECC5871DEC"

查看dsym 文件uuid 的几种方式

dwarfdump --uuid TestApp.app.dSYM
xcrun dwarfdump --uuid TestApp.app.dSYM
dwarfdump --uuid /Users/username/Documents/Test/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp

导出debug_line的信息到debug_line.txt中,debug_info也可以使用类似命令导出

dwarfdump --debug-line TestApp.app.dSYM -> debug_line.txt

符号化流程

第一步:获取崩溃日志App关键行信息:

9   TestApp        0x0000000102cc0eb8 _mh_execute_header + 3821240

第二步:获取偏移量,运行时堆栈地址,运行时App起始地址

由关键行信息获取
偏移量:3821240 (16进制:3a4eb8)
运行时堆栈地址:0x0000000102cc0eb8
运行时App起始地址:0x10291c000

第三步:获取dSYM起始地址

获取符号表中的TEXT段起始地址

otool -l /Users/username/Documents/Test/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp

结果如下:
__TEXT 起始地址

Load command 3
      cmd LC_SEGMENT_64
  cmdsize 1032
  segname __TEXT
   vmaddr 0x0000000100000000
   vmsize 0x0000000004334000
  fileoff 0
 filesize 0

符号表起始地址:

  0x0000000100000000

第四步:计算崩溃地址对应dSYM符号表的地址

符号表堆栈地址 = 符号表起始地址 + 偏移量

0x1003a4eb8=  0x100000000 + 3a4eb8

第五步:获取到具体函数/行数信息

崩溃信息还原:(http://www.cocoachina.com/articles/12806)
符号表崩溃地址的解析方式
第一种:
dwarfdump 使用符号表堆栈地址可以不加 --arch=arm64:

  dwarfdump --arch=arm64 --lookup 符号表堆栈地址Test/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp
    如:
dwarfdump --arch=arm64 --lookup 0x1003a4eb8 /Users/username/Documents/Test/TestApp.app.dSYM/Contents/Resources/DWARF/TestApp
第二种使用: atos -o TestApp.app.dSYM/Contents/Resources/DWARF/TestApp -arch arm64 符号表堆栈地址
如:
    atos -o TestApp.app.dSYM/Contents/Resources/DWARF/TestApp -arch arm64 0x1003a4eb8

无符号表崩溃地址的解析方式

实际上,atos还提供了另外一种无需计算崩溃地址对应的符号表地址的方式,命令格式如下:

atos -o TestApp.app.dSYM/Contents/Resources/DWARF/TestApp -arch arm64 -l 运行时的起始地址 运行时地址

运行时堆栈地址 = 运行时起始地址 + 偏移量
0x102cc0eb8 = 0x10291c000 + 0x3a4eb8

atos -o TestApp.app.dSYM/Contents/Resources/DWARF/TestApp -arch arm64 -l 0x10291c000 0x102cc0eb8

其中-l选项指定了二进制文件在运行时的起始地址0xa2000(获取方式见Binary Images相关内容),后面跟的是崩溃发生的运行时地址0x000f0846,解析结果和使用计算得到的符号表中崩溃地址一致:

参考地址:
https://zhuanlan.zhihu.com/p/159301707
https://mp.weixin.qq.com/s/W1xzi56W9sJRrSz0v2SgDA

你可能感兴趣的:(iOS 崩溃日志符号化)