崩溃报告结构如下,每个部分都包含可帮助定位崩溃位置的信息:
1. Header
描述崩溃发生的环境,包含设备、系统、时间、版本等信息。如:
Incident Identifier: 6156848E-344E-4D9E-84E0-87AFD0D0AE7B
CrashReporter Key: 76f2fb60060d6a7f814973377cbdc866fffd521f
Hardware Model: iPhone8,1
Process: TouchCanvas [1052]
Path: /private/var/containers/Bundle/Application/51346174-37EF-4F60-B72D-8DE5F01035F5/TouchCanvas.app/TouchCanvas
Identifier: com.example.apple-samplecode.TouchCanvas
Version: 1 (3.0)
Code Type: ARM-64 (Native)
Role: Foreground
Parent Process: launchd [1]
Coalition: com.example.apple-samplecode.TouchCanvas [1806]Date/Time: 2020-03-27 18:06:51.4969 -0700
Launch Time: 2020-03-27 18:06:31.7593 -0700
OS Version: iPhone OS 13.3.1 (17D50)
2. Exception information
异常信息。描述进程如何终止,但可能无法完全解释程序终止的原因。如:
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000102afb3d0
Exception Type
:Mach 异常名称 (对应的 BSD 终止信号)Exception Codes
:异常处理器特定信息,一个或多个 64 位十六进制数。通常此字段不存在,因为操作系统通过其他字段将信息呈现为人类可读的信息。Exception Subtype
:异常子类型Exception Message
:异常描述信息Exception Note
:异常附加信息。- 若包含
EXC_CORPSE_NOTIFY
,则崩溃并非源自硬件缺陷,原因可能是 操作系统 或 进程调用 abort() 函数 导致进程终止。 - 若包含
SIMULATED
,则进程没有崩溃,但操作系统可能随后请求终止进程。 - 若包含
NON-FATAL CONDITION
(这不是崩溃),则进程不会终止,因为创建崩溃报告的问题并不致命
- 若包含
Termination Reason
:终止原因,系统组件在遇到致命错误时会终止进程,并在该字段中记录信息。可在此字段中找到例如:无效代码签名、缺少依赖库、访问不带目的的字符串的隐私敏感信息 等消息。Triggered by Thread or Crashed Thread
:引发异常的线程
3. Diagnostic messages
操作系统有时会包含额外的诊断信息,这些信息使用多种格式,具体取决于崩溃的原因,并不是每个崩溃报告都包含。如:
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: dispatch_sync called on queue already owned by current thread
Application Specific Information
:进程终止前发生的框架错误消息
Termination Description
:由于看门狗违规而导致终止,会包含该字段,描述看门狗触发原因的信息。如:
Termination Description: SPRINGBOARD, scene-create watchdog transgression: application<com.example.MyCoolApp>:667exhausted real (wall clock) time allowance of 19.97 seconds
4. Backtraces
崩溃进程的每个线程都被捕获为回溯,记录进程终止时线程上运行的代码。
由语言异常引起的崩溃包含一个额外的回溯,即位于第一个线程之前的 Last Exception Backtrace
。
每个回溯的第一行列出了线程的编号和名称。之后的每一行代表回溯中的一个堆栈帧,堆栈帧的每一列都包含崩溃时执行的代码信息。如:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 TouchCanvas 0x0000000102afb3d0 CanvasView.updateEstimatedPropertiesForTouches(_:) + 62416 (CanvasView.swift:231)
1 TouchCanvas 0x0000000102afb3d0 CanvasView.updateEstimatedPropertiesForTouches(_:) + 62416 (CanvasView.swift:231)
2 TouchCanvas 0x0000000102af7d10 ViewController.touchesMoved(_:with:) + 48400 (<compiler-generated>:0)
3 TouchCanvas 0x0000000102af80b8 @objc ViewController.touchesMoved(_:with:) + 49336 (<compiler-generated>:0)
4 UIKitCore 0x00000001ba9d8da4 forwardTouchMethod + 328
5 UIKitCore 0x00000001ba9d8e40 -[UIResponder touchesMoved:withEvent:] + 60
6 UIKitCore 0x00000001ba9d8da4 forwardTouchMethod + 328
7 UIKitCore 0x00000001ba9d8e40 -[UIResponder touchesMoved:withEvent:] + 60
8 UIKitCore 0x00000001ba9e6ea4 -[UIWindow _sendTouchesForEvent:] + 1896
9 UIKitCore 0x00000001ba9e8390 -[UIWindow sendEvent:] + 3352
10 UIKitCore 0x00000001ba9c4a9c -[UIApplication sendEvent:] + 344
11 UIKitCore 0x00000001baa3cc20 __dispatchPreprocessedEventFromEventQueue + 5880
12 UIKitCore 0x00000001baa3f17c __handleEventQueueInternal + 4924
13 UIKitCore 0x00000001baa37ff0 __handleHIDEventFetcherDrain + 108
14 CoreFoundation 0x00000001b68a4a00 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24
15 CoreFoundation 0x00000001b68a4958 __CFRunLoopDoSource0 + 80
16 CoreFoundation 0x00000001b68a40f0 __CFRunLoopDoSources0 + 180
17 CoreFoundation 0x00000001b689f23c __CFRunLoopRun + 1080
18 CoreFoundation 0x00000001b689eadc CFRunLoopRunSpecific + 464
19 GraphicsServices 0x00000001c083f328 GSEventRunModal + 104
20 UIKitCore 0x00000001ba9ac63c UIApplicationMain + 1936
21 TouchCanvas 0x0000000102af16dc main + 22236 (AppDelegate.swift:12)
22 libdyld.dylib 0x00000001b6728360 start + 4Thread 1:
0 libsystem_pthread.dylib 0x00000001b6645758 start_wqthread + 0Thread 2:
0 libsystem_pthread.dylib 0x00000001b6645758 start_wqthread + 0
...
-
第一列:堆栈帧号,堆栈帧按调用顺序排列,其中0帧是执行停止时正在执行的函数,1帧则是调用0帧的函数,以此类推。
-
第二列:正在执行函数的二进制文件名称
-
第三列:正在执行的机器指令的地址。对于非崩堆栈,这是控制权返回到该堆栈帧后执行的第一条机器指令的地址
-
第四列:在完全符号化的崩溃报告中,正在执行的函数名称。
-
后面的
+数字
:是从函数入口点到函数中当前指令的字节偏移量。 -
(文件名.后缀:数字):文件名和行号。某些情况下跟原始源代码不对应:
- 如果源文件名是
<compiler-generated>
,则编译器为该框架创建代码,并且该代码不在您的源文件中。如果这是崩溃线程的顶部帧,需要查看前面几个堆栈帧获得线索。 - 如果源文件的行号是0,意味着回溯不会映射到原始代码中的特定代码行。因为编译器优化了代码(如:内敛),且崩溃时执行的代码与原始代码中的确切行不对应。此时框架的函数名仍然只是个线索。
- 如果源文件名是
5. Thread state
线程状态部分列出了程序终止时崩溃线程的 CPU 寄存器及其值。如:
Thread 0 crashed with ARM Thread State (64-bit):x0: 0x0000000000000001 x1: 0x0000000000000000 x2: 0x0000000000000000 x3: 0x000000000000000fx4: 0x00000000000001c2 x5: 0x000000010327f6c0 x6: 0x000000010327f724 x7: 0x0000000000000120x8: 0x0000000000000001 x9: 0x0000000000000001 x10: 0x0000000000000001 x11: 0x0000000000000000x12: 0x00000001038612b0 x13: 0x000005a102b075a7 x14: 0x0000000000000100 x15: 0x0000010000000000x16: 0x00000001c3e6c630 x17: 0x00000001bae4bbf8 x18: 0x0000000000000000 x19: 0x0000000282c14280x20: 0x00000001fe64a3e0 x21: 0x4000000281f1df10 x22: 0x0000000000000001 x23: 0x0000000000000000x24: 0x0000000000000000 x25: 0x0000000282c14280 x26: 0x0000000103203140 x27: 0x00000001bacf4b7cx28: 0x00000001fe5ded08 fp: 0x000000016d311310 lr: 0x0000000102afb3d0sp: 0x000000016d311200 pc: 0x0000000102afb3d0 cpsr: 0x60000000esr: 0xf2000001 Address size fault
了解线程状态是个高级主题,需要了解程序二进制接口(ABI),可参阅 Writing ARM64 code for Apple platforms
寄存器为内存访问引起的崩溃提供额外信息,详情可参阅 Understand the crashed thread’s registers
6. Binary images
二进制图像,崩溃报告的二进制图片部分列出了终止时进程中加载的所有代码(如:应用程序可执行文件和系统框架)。二进制图像部分中的每一行代表一个二进制图像, 如:
Binary Images:
0x102aec000 - 0x102b03fff TouchCanvas arm64 <fe7745ae12db30fa886c8baa1980437a> /var/containers/Bundle/Application/51346174-37EF-4F60-B72D-8DE5F01035F5/TouchCanvas.app/TouchCanvas
...
- 第一列:进程内二进制图像的地址范围,第一个地址是二进制文件的加载地址。
- 第二列:二进制名称
- 第三列:操作系统加载到进程中的二进制映像的 CPU 架构
- 第四列:唯一标识二进制图像的 UUID,跟 dSYM 文件对应
- 第四列:磁盘上二进制文件的路径。(MacOS使用占位符替换用户可识别的路径组件以保护隐私)
参考:
Examining the fields in a crash report