iOS 項目打包成功后為 xcarchive 后綴的文件, 里面不但包含了 app 運行所需要的二進制文件和資源文件,還含有項目中編程時具體文件的信息。App 運行時,內(nèi)存中僅僅加載了二進制文件,出現(xiàn)異常時,只能反映出 16 進制的內(nèi)存地址,還需要通過 dSYM 文件映射為對應(yīng)的具體文件信息,編程人員才能定位問題,進行更正。具體是個什么過程呢?
打開 xcarchive 文件,可以找到 app 后綴的文件,其中包含了 ipa 包的全部信息。

查看包內(nèi)容,能夠看到里面有 app 運行所需要的圖片,nib 文件和 bundle 資源文件,除此之外,最重要的是 Unix 可執(zhí)行文件。
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 執(zhí)行文件,能夠看到其為 Mach-O 文件,支持 arm_v7 和 arm64 兩種 CPU 指令集。Mach-O 文件格式中用來存儲和處理調(diào)試信息的標準格式為 DWARF (DebuggingWith Arbitrary Record Formats) 。
采用 sublime 打開 .app.dSYM 文件:

能看出 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
不同架構(gòu)下的 UUID 用于區(qū)分不同的 dSYM 匹配文件。
使用Xcode 自帶的 dwarfdump命令,對 .app.dSYM 進行信息提取:
1 獲取函數(shù)文件 info 信息:
dwarfdump -p -debug-info /Users/zhudongdong/Desktop/dsym/MTAppProduction.app.dSYM/Contents/Resources/DWARF/MTAppProduction > info-e.txt
2 獲取函數(shù)行號 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 方法結(jié)束地址: 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 對應(yīng)的行號 ,比如 0x00000000001f35c0 對應(yīng) 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 崩潰時的調(diào)用棧:
Thread 0 Crashed...
想要解析崩潰日志,依據(jù)以上信息,只需要兩步即可完成:
1 根據(jù) 3 中的映射地址,能夠在 dSYM 文件中找到對應(yīng)的函數(shù);
2 根據(jù)崩潰的具體地址,在對應(yīng)的函數(shù)中找到具體的行數(shù);
以上是解析日志信息的整體流程,具體的地址計算,都是固定的程序化,已經(jīng)有人專門做好了解析的工具:dSYMTools 。
參考:
1 https://davidlii.cn/2018/07/11/dsym.html
2 http://www.itdecent.cn/p/fc67f95eee41
3 http://www.itdecent.cn/p/d79d5377dccf