iOS 的那些事儿Crash文章

iOS 用 dSYM 文件解析崩溃日志

2019-06-18  本文已影响1人  uniapp

iOS 项目打包成功后为 xcarchive 后缀的文件, 里面不但包含了 app 运行所需要的二进制文件和资源文件,还含有项目中编程时具体文件的信息。App 运行时,内存中仅仅加载了二进制文件,出现异常时,只能反映出 16 进制的内存地址,还需要通过 dSYM 文件映射为对应的具体文件信息,编程人员才能定位问题,进行更正。具体是个什么过程呢?

打开 xcarchive 文件,可以找到 app 后缀的文件,其中包含了 ipa 包的全部信息。

image.png

查看包内容,能够看到里面有 app 运行所需要的图片,nib 文件和 bundle 资源文件,除此之外,最重要的是 Unix 可执行文件。

file MTAppProduction
MTAppProduction: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64]
MTAppProduction (for architecture armv7):   Mach-O executable arm_v7
MTAppProduction (for architecture arm64):   Mach-O 64-bit executable arm64

使用 file 命令查看 Unix 执行文件,能够看到其为 Mach-O 文件,支持 arm_v7 和 arm64 两种 CPU 指令集。Mach-O 文件格式中用来存储和处理调试信息的标准格式为 DWARF (DebuggingWith Arbitrary Record Formats) 。
采用 sublime 打开 .app.dSYM 文件:

image.png

能看出 dSYM 文件实际上是一个文件夹,里面目录名为 DWARF 的文件夹中的文件,其格式为 Mach-O dSYM

file MTAppProduction.app.dSYM/Contents/Resources/DWARF/MTAppProduction

MTAppProduction (for architecture armv7):   Mach-O dSYM companion file arm_v7
MTAppProduction (for architecture arm64):   Mach-O 64-bit dSYM companion file arm64

文章开始所说的映射,就是在 MTAppProduction.app.dSYM两者间进行的。

通过 Xcode 工具能够查看 dSYM 文件的 UUID:

xcrun dwarfdump --uuid MTAppProduction.app.dSYM 
UUID: C6FF1B19-2F18-31D2-A125-2C51795EFA60 (armv7) MTAppProduction.app.dSYM/Contents/Resources/DWARF/MTAppProduction
UUID: C6E7752D-6BF6-3761-8AA8-E7E261C548C0 (arm64) MTAppProduction.app.dSYM/Contents/Resources/DWARF/MTAppProduction

不同架构下的 UUID 用于区分不同的 dSYM 匹配文件。

使用Xcode 自带的 dwarfdump命令,对 .app.dSYM 进行信息提取:
1 获取函数文件 info 信息:

dwarfdump -p -debug-info /Users/zhudongdong/Desktop/dsym/MTAppProduction.app.dSYM/Contents/Resources/DWARF/MTAppProduction > info-e.txt

2 获取函数行号 line 信息:

dwarfdump -p --debug-line /Users/zhudongdong/Desktop/dsym/MTAppProduction.app.dSYM/Contents/Resources/DWARF/MTAppProduction > line-e.txt

取 info 信息的一段进行分析:

0x0009e61a:   DW_TAG_subprogram
                DW_AT_low_pc    (0x0000000100072884)
                DW_AT_high_pc   (0x0000000100072898)
                DW_AT_frame_base    (DW_OP_reg31 WSP)
                DW_AT_object_pointer    (0x0009e63b)
                DW_AT_name  ("-[MTOpenEditController setProfitLossCell:]")
                DW_AT_decl_file ("/Users/zhudongdong/Desktop/td/mitrade-iOS2/mitrade-iOS/MTApp/UI/Positions/Controller/PositonDetail/MTOpenEditController.m")
                DW_AT_decl_line (42)
                DW_AT_prototyped    (0x01)
                DW_AT_artificial    (0x01)
                DW_AT_APPLE_optimized   (0x01)

在上段能够得到如下信息:
1 文件的起始地址: 0x0009e61a ;
2 方法名: -[MTOpenEditController setProfitLossCell:]
3 文件名称: MTOpenEditController.m
4 方法起始地址: 0x0000000100072884
5 方法结束地址: 0x0000000100072898

取 line 的一段信息如下:

Address            Line   Column File   ISA Discriminator Flags
------------------ ------ ------ ------ --- ------------- -------------
0x00000000001f35c0     42      0      2   0             0  is_stmt
0x00000000001f35cc     45     37      2   0             0  is_stmt prologue_end
0x00000000001f3600     46      3      2   0             0  is_stmt
0x00000000001f3626      0      0      2   0             0 
0x00000000001f362a     53     27      2   0             0  is_stmt
0x00000000001f362e      0      0      2   0             0 

能够看到具体每一个 Address 对应的行号 ,比如 0x00000000001f35c0 对应 42 行。

一个典型的崩溃信息如下:

Incident Identifier: E8B419BB-9DAA-4523-A092-7A23C3ABDE38
CrashReporter Key:   82aa65447d853b4be824cac9d0399b86f9984329
Hardware Model:      iPhone10,3
Process:             WeChat [9322]
Path:                /private/var/containers/Bundle/Application/6CF1E4C4-1E68-4B3E-A8CB-BD0E78A815A9/WeChat.app/WeChat
Identifier:          com.tencent.xin
Version:             7.0.1.32 (7.0.1)
AppStoreTools:       10B63
AppVariant:          1:iPhone10,3:12
Code Type:           ARM-64 (Native)
Role:                Non UI
Parent Process:      launchd [1]
Coalition:           com.tencent.xin [2023]


Date/Time:           2019-03-13 18:52:00.6011 +0800
Launch Time:         2019-03-13 07:20:06.8636 +0800
OS Version:          iPhone OS 12.1.4 (16D57)
Baseband Version:    3.31.00
Report Version:      104

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x408c780000000008
VM Region Info: 0x408c780000000008 is not in any region.  Bytes after previous region: 4651224445287923721  
      REGION TYPE                      START - END             [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      MALLOC_NANO            0000000280000000-00000002a0000000 [512.0M] rw-/rwx SM=PRV  
--->  
      UNUSED SPACE AT END

Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [9322]
Triggered by Thread:  0

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   QBar                            0x00000001070ee8e0 0x106f84000 + 1485024
1   QBar                            0x00000001070eea0c 0x106f84000 + 1485324
2   QBar                            0x00000001070d7b90 0x106f84000 + 1391504
3   QBar                            0x00000001070cde60 0x106f84000 + 1351264
4   QBar                            0x00000001070ccb0c 0x106f84000 + 1346316
5   dyld                            0x0000000105001864 0x104fe8000 + 104548
6   dyld                            0x0000000104fea784 0x104fe8000 + 10116
7   libsystem_c.dylib               0x00000001b9213ab4 0x1b91bb000 + 363188


Binary Images:
0x100014000 - 0x103c17fff WeChat arm64  <002cc9e9f70136ae8dd415849efb2cf3> /var/containers/Bundle/Application/6CF1E4C4-1E68-4B3E-A8CB-BD0E78A815A9/WeChat.app/WeChat
0x104e08000 - 0x104e9bfff zstd arm64  <1a5604b6091b39b8abfe23d284877b97> /var/containers/Bundle/Application/6CF1E4C4-1E68-4B3E-A8CB-BD0E78A815A9/WeChat.app/Frameworks/zstd.framework/zstd

从崩溃日志中能够得到:
1 app 的 UUID : Incident Identifier: E8B419BB-9DAA-4523-A092-7A23C3ABDE38, 用于核对 dSYM 文件;
2 崩溃标记: CrashReporter Key: 82aa65447d853b4be824cac9d0399b86f9984329;
3 app 运行时的地址和 dSYM 文件映射的地址: Binary Images: 0x100014000 - 0x103c17fff;
4 崩溃的地址 0x408c780000000008;
5 崩溃时的调用栈:
Thread 0 Crashed...

想要解析崩溃日志,依据以上信息,只需要两步即可完成:

1 根据 3 中的映射地址,能够在 dSYM 文件中找到对应的函数;
2 根据崩溃的具体地址,在对应的函数中找到具体的行数;

以上是解析日志信息的整体流程,具体的地址计算,都是固定的程序化,已经有人专门做好了解析的工具:dSYMTools

参考:
1 https://davidlii.cn/2018/07/11/dsym.html
2 https://www.jianshu.com/p/fc67f95eee41
3 https://www.jianshu.com/p/d79d5377dccf

喜欢和关注都是对我的鼓励和支持~
上一篇下一篇

猜你喜欢

热点阅读