- [译]《iOS Crash Dump Analysis》-
- [译]《iOS Crash Dump Analysis》-
- [译]《iOS Crash Dump Analysis》-
- [译]《iOS Crash Dump Analysis》-
- [译]《iOS Crash Dump Analysis》-
- [译]《iOS Crash Dump Analysis》- X
- [译]《iOS Crash Dump Analysis》- 分析
- [译]《iOS Crash Dump Analysis》- P
- [译]《iOS Crash Dump Analysis》- 混
- [译]《iOS Crash Dump Analysis》- 工具
macOS 崩溃报告导览
尽管 macOS CrashReport 和 iOS CrashReport 是截然不同的程序,但 macOS 崩溃报告类似于 iOS 崩溃报告。为了避免重复,这里我们只强调与 iOS 的显着差异。
macOS 崩溃报告 Header 部分
崩溃报告以一下部分开头:
Process: SiriNCService [1045]
Path: /System/Library/CoreServices/Siri.app/
Contents/XPCServices/SiriNCService.xpc/
Contents/MacOS/SiriNCService
Identifier: com.apple.SiriNCService
Version: 146.4.5.1 (146.4.5.1)
Build Info: AssistantUIX-146004005001000~1
Code Type: X86-64 (Native)
Parent Process: ??? [1]
Responsible: Siri [863]
User ID: 501
这里我们看到了熟悉的描述故障二进制信息。崩溃的进程是 SiriNCService,负责这个进程的是 Siri。在 Siri 和 SiriNCService 之间的跨进程通信时发生了崩溃(XPC)。
通常 iOS以一个用户身份运行用户体验的系统,然而 macOS系统却暴露出系统中存在多个用户 ID 的事实。
macOS 崩溃报告 Date 和 Version 部分
接下来我们来看版本信息:
Date/Time: 2018-06-24 09:52:01.419 +0100
OS Version: Mac OS X 10.13.5 (17F77)
Report Version: 12
Anonymous UUID: 00CC683B-425F-ABF0-515A-3ED73BACDDB5
Sleep/Wake UUID: 10AE8838-17A9-4405-B03D-B680DDC84436
Anonymous UUID
将是计算机的唯一标识。 Sleep/Wake UUID
用于匹配睡眠和唤醒事件。唤醒失败是系统崩溃的常见原因(与我们讨论的应用程序崩溃相反)。可以使用电源管理命令 pmset
获取更多信息。
macOS 持续时间部分
macOS 崩溃报告显示应用程序崩溃发生的时间。
Time Awake Since Boot: 100000 seconds
Time Since Wake: 2000 seconds
我们使用它作为一个广泛的指示只因为看到的数字总是四舍五入所得到一个方便的数字。
macOS崩溃报告系统完整性部分
System Integrity Protection: enabled
默认情况下,现代 macOS 运行是 "rootless"的。这意味着即使我们以超级用户身份登录,我们也无法更改系统的二进制文件。这些都是通过固件进行保护的。可以在禁用系统完整性保护的情况下启动 macOS。如果我们只是在禁用 SIP 的情况下崩溃,那么我们需要问为什么 SIP 会关闭以及对操作系统做了哪些更改。
macOS 崩溃报告的异常部分
接下来展示异常部分。
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000018
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [0]
VM Regions Near 0x18:
-->
__TEXT 0000000100238000-0000000100247000
[ 60K] r-x/rwx SM=COW
/System/Library/CoreServices/Siri.app/
Contents/XPCServices/SiriNCService.xpc/Contents/MacOS/
SiriNCService
Application Specific Information:
objc_msgSend() selector name: didUnlockScreen:
这与 iOS 类似。但是,我们应该注意,如果我们在模拟器上重现 iOS 崩溃,那么模拟器可能会以不同方式对相同的编程错误进行建模。我们可以在 x86 硬件上获得与 ARM 对应的异常。
考虑以下代码,设置为旧版的手动引用计数(MRC)而不是自动引用计数(ARC)。
void use_sema() {
dispatch_semaphore_t aSemaphore =
dispatch_semaphore_create(1);
dispatch_semaphore_wait(aSemaphore, DISPATCH_TIME_FOREVER);
dispatch_release(aSemaphore);
}
代码会导致崩溃,因为在等待时会手动释放信号量。
当它在 ARM 硬件上的 iOS 模拟器上运行时,会发生崩溃
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001814076b8
Termination Signal: Trace/BPT trap: 5
Termination Reason: Namespace SIGNAL, Code 0x5
Terminating Process: exc handler [0]
Triggered by Thread: 0
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: Semaphore object deallocated while
in use
Abort Cause 1
当它在 iOS 模拟器上运行时,我们会附带调试器
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
模拟器使用错误的汇编指令来触发崩溃。
此外,如果我们编写一个运行相同代码的 macOS 应用程序,我们就会崩溃:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_INSTRUCTION (SIGILL)
Exception Codes: 0x0000000000000001, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Illegal instruction: 4
Termination Reason: Namespace SIGNAL, Code 0x4
Terminating Process: exc handler [0]
Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH:
Semaphore object deallocated while in use
这就带来一个信息,当通过模拟器或等效的 macOS 代码在 x8 6硬件上再现 iOS ARM 崩溃时,由于运行时环境有所不同,表现也会稍有不同。
幸运的是,在两个崩溃报告中都很明显的表明了信号量被释放了。
macOS 崩溃报告线程部分
接下来是线程部分。这部分类似于iOS。
接下来用示例说明 macOS 崩溃报告中的线程部分:
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib
0x00007fff69feae9d objc_msgSend + 29
1 com.apple.CoreFoundation 0x00007fff42e19f2c
__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
2 com.apple.CoreFoundation 0x00007fff42e19eaf
___CFXRegistrationPost_block_invoke + 63
3 com.apple.CoreFoundation 0x00007fff42e228cc
__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
4 com.apple.CoreFoundation 0x00007fff42e052a3
__CFRunLoopDoBlocks + 275
5 com.apple.CoreFoundation 0x00007fff42e0492e
__CFRunLoopRun + 1278
6 com.apple.CoreFoundation 0x00007fff42e041a3
CFRunLoopRunSpecific + 483
7 com.apple.HIToolbox 0x00007fff420ead96
RunCurrentEventLoopInMode + 286
8 com.apple.HIToolbox 0x00007fff420eab06
ReceiveNextEventCommon + 613
9 com.apple.HIToolbox 0x00007fff420ea884
_BlockUntilNextEventMatchingListInModeWithFilter + 64
10 com.apple.AppKit 0x00007fff4039ca73
_DPSNextEvent + 2085
11 com.apple.AppKit 0x00007fff40b32e34
-[NSApplication(NSEvent) _nextEventMatchingEventMask:
untilDate:inMode:dequeue:] + 3044
12 com.apple.ViewBridge 0x00007fff67859df0
-[NSViewServiceApplication nextEventMatchingMask:
untilDate:inMode:dequeue:] + 92
13 com.apple.AppKit 0x00007fff40391885
-[NSApplication run] + 764
14 com.apple.AppKit 0x00007fff40360a72
NSApplicationMain + 804
15 libxpc.dylib 0x00007fff6af6cdc7
_xpc_objc_main + 580
16 libxpc.dylib 0x00007fff6af6ba1a
xpc_main + 433
17 com.apple.ViewBridge 0x00007fff67859c15
-[NSXPCSharedListener resume] + 16
18 com.apple.ViewBridge 0x00007fff67857abe
NSViewServiceApplicationMain + 2903
19 com.apple.SiriNCService 0x00000001002396e0
main + 180
20 libdyld.dylib 0x00007fff6ac12015
start + 1
macOS 崩溃报告线程状态部分
macOS 崩溃报告显示了崩溃线程中 X86 寄存器的详细信息。
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000600000249bd0 rbx: 0x0000600000869ac0
rcx: 0x00007fe798f55320
rdx: 0x0000600000249bd0
rdi: 0x00007fe798f55320 rsi: 0x00007fff642de919
rbp: 0x00007ffeef9c6220
rsp: 0x00007ffeef9c6218
r8: 0x0000000000000000 r9: 0x21eb0d26c23ae422
r10: 0x0000000000000000
r11: 0x00007fff642de919
r12: 0x00006080001e8700 r13: 0x0000600000869ac0
r14: 0x0000600000448910
r15: 0x0000600000222e60
rip: 0x00007fff69feae9d rfl: 0x0000000000010246
cr2: 0x0000000000000018
Logical CPU: 2
Error Code: 0x00000004
Trap Number: 14
除与了 iOS 相似的信息之外,我们还获得了更多有关运行该线程的 CPU 的消息 。如果有需要我们可以在 Darwin XNU 源代码中查找对应的 trap number
。
Darwin XNU 源代码的便捷镜像由 GitHub 来托管:https://github.com/apple/darwin-xnu
这些 trap number
可以被搜索到。我们从osfmk/x86_64/idt_table.h
可以找到 Trap Number:14
表明看了一个页面错误。这个错误代码是一个位向量,用于描述在 mach 上的错误代码。@macherror
macOS 崩溃报告 Binary Images 部分
接下来,是崩溃应用程序所加载的 Binary Images。
以下是崩溃报告中前几个二进制文件的示例,为了便于演示,进行了截断:
Binary Images:
0x100238000 - 0x1ß00246fff
com.apple.SiriNCService (146.4.5.1 - 146.4.5.1)
<5730AE18-4DF0-3D47-B4F7-EAA84456A9F7>
/System/Library/CoreServices/Siri.app/Contents/
XPCServices/SiriNCService.xpc/Contents/MacOS/
SiriNCService
0x101106000 - 0x10110affb
com.apple.audio.AppleHDAHALPlugIn (281.52 - 281.52)
<23C7DDE6-A44B-3BE4-B47C-EB3045B267D9>
/System/Library/Extensions/AppleHDA.kext/Contents/
PlugIns/AppleHDAHALPlugIn.bundle/Contents/MacOS/
AppleHDAHALPlugIn
当二进制旁边出现 +
号时,则意味着它是操作系统的一部分。但是,我们看到某些第三方二进制旁边出现 +
号而系统二进制文件旁没有出现 +
号的示例,因为 +
并不是可靠的指示符(在 OS X 10.13.6上进行了最后测试)。
macOS 崩溃报告修改摘要
接下来,这一节描述了崩溃过程中的所有外部修改:
External Modification Summary:
Calls made by other processes targeting this process:
task_for_pid: 184
thread_create: 0
thread_set_state: 0
Calls made by this process:
task_for_pid: 0
thread_create: 0
thread_set_state: 0
Calls made by all processes on this machine:
task_for_pid: 72970
thread_create: 0
thread_set_state: 0
macOS 是比 iOS 更开放的平台。这就允许在某些条件下运行过程中发生了修改。我们需要知道是否发生了这种事情,因为它可以使代码中的任何设计假设无效,由于可以在过程中修改寄存器,这就有可能导致项目崩溃。
通常我们可以看到如上的快照。值得注意的是,在所有情况下,thread_set_state
值均为 0。这意味着并没有任何进程直接连接到该进程来更改寄存器状态。这种操作对于托管运行时或调试器的实现是可接受的。在这些情况之外的操作会显得奇怪,需要进一步调查。
在下面的示例中,我们看到线程状态除了200个 task_for_pid
调用之外,还一次被外部进程更改了。
External Modification Summary:
Calls made by other processes targeting this process:
task_for_pid: 201
thread_create: 0
thread_set_state: 1
Calls made by this process:
task_for_pid: 0
thread_create: 0
thread_set_state: 0
Calls made by all processes on this machine:
task_for_pid: 6184
thread_create: 0
thread_set_state: 1
这些数据通常会让我们对应用程序在崩溃之前运行的环境产生怀疑。
通常只有第一等的程序(Apple 提供的)才有权限执行上述修改。我们可以安装执行这个操作的软件。
执行访问进程修改的 API 有如下要求:
-
需要禁用系统完整性保护
-
进行修改的过程必须以 root 身份运行
-
进行修改的程序必须经过代码签名
-
程序必须被分配这些权利,将
SecTaskAccess
设置为allowed
和debug
。 -
用户必须同意在其安全设置中信任该程序
示例代码 tfpexample
演示了这一点。 @icdabgithub
macOS 崩溃报告虚拟内存部分
崩溃报告接下来是虚拟内存摘要和区域类型细分。如果我们有一个用来渲染文档页面的图形丰富的应用程序,则可以查看,例如 CoreUI 的内存消耗。尽当我们用 Xcode Instruments 中的 memory profiler 工具分析该应用程序时,虚拟内存统计信息才有意义,因为这样我们就可以了解应用程序中内存的动态使用情况,从来在错误发生时发现错误。
这是报告的虚拟内存部分的示例:
VM Region Summary:
ReadOnly portion of Libraries: Total=544.2M resident=0K(0%)
swapped_out_or_unallocated=544.2M(100%)
Writable regions: Total=157.9M written=0K(0%) resident=0K(0%)
swapped_out=0K(0%) unallocated=157.9M(100%)
VIRTUAL REGION
REGION TYPE SIZE COUNT (non-coalesced)
=========== ======= =======
Accelerate framework 128K 2
Activity Tracing 256K 2
CoreAnimation 700K 16
CoreGraphics 8K 2
CoreImage 20K 4
CoreServices 11.9M 3
CoreUI image data 764K 6
CoreUI image file 364K 8
Foundation 24K 3
IOKit 7940K 2
Image IO 144K 2
Kernel Alloc Once 8K 2
MALLOC 133.1M 36
MALLOC guard page 48K 13
Memory Tag 242 12K 2
Memory Tag 251 16K 2
OpenGL GLSL 256K 4
SQLite page cache 64K 2
STACK GUARD 56.0M 6
Stack 10.0M 8
VM_ALLOCATE 640K 8
__DATA 58.3M 514
__FONT_DATA 4K 2
__GLSLBUILTINS 2588K 2
__LINKEDIT 194.0M 26
__TEXT 350.2M 516
__UNICODE 560K 2
mapped file 78.2M 29
shared memory 2824K 11
=========== ======= =======
TOTAL 908.7M 1206
macOS崩溃报告系统配置文件部分
崩溃报告的下一部分是相关硬件的摘要:
System Profile:
Network Service: Wi-Fi, AirPort, en1
Thunderbolt Bus: iMac, Apple Inc., 26.1
Boot Volume File System Type: apfs
Memory Module: BANK 0/DIMM0, 8 GB, DDR3, 1600 MHz, 0x802C,
0x31364B544631473634485A2D314736453220
Memory Module: BANK 1/DIMM0, 8 GB, DDR3, 1600 MHz, 0x802C,
0x31364B544631473634485A2D314736453220
USB Device: USB 3.0 Bus
USB Device: BRCM20702 Hub
USB Device: Bluetooth USB Host Controller
USB Device: FaceTime HD Camera (Built-in)
USB Device: iPod
USB Device: USB Keyboard
Serial ATA Device: APPLE SSD SM0512F, 500.28 GB
Model: iMac15,1, BootROM IM151.0217.B00, 4 processors,
Intel Core i5, 3.5 GHz, 16 GB, SMC 2.22f16
Graphics: AMD Radeon R9 M290X, AMD Radeon R9 M290X, PCIe
AirPort: spairport_wireless_card_type_airport_extreme
(0x14E4, 0x142), Broadcom BCM43xx 1.0 (7.77.37.31.1a9)
Bluetooth: Version 6.0.6f2, 3 services, 27 devices,
1 incoming serial ports
有时,我们的应用程序与硬件设备进行紧密交互,如果通过基于标准的设备接口(例如 USB 接口)进行交互,则有可能会发生很多变化。考虑一下磁盘驱动。许多供应商提供磁盘驱动器,它们可能直接或独立运行。它们可以直接连接,或通过 USB 电缆连接,也可以通过 USB 集线器连接。
有时新的硬件,例如新型 MacBook Pro 会出现自己的硬件问题,因此可以看到与我们的应用程序无关的崩溃。
判断是否是硬件环境导致崩溃的关键是查看大量的崩溃报告以寻找某种规律。
作为应用程序开发人员,我们只会看到应用程序中的崩溃。但如果我们与提供崩溃的用户联系,我们可以询问是否有其他应用程序崩溃,或者是否存在任何系统稳定性问题。
另一个有趣的方面是,并非所有硬件都始终被系统主动使用。例如,当 MacBook Pro 连接到外部显示器时,将使用不同的图形RAM,并使用不同的图形卡(外部GPU与内部GPU)。如果我们的应用程序执行特殊操作,则在连接到外部显示器时,故障可能出在硬件而非我们的代码中,原因是它触发了硬件中的潜在故障。
运行系统诊断程序并查看仅针对特定的匿名 UUID 故障报告是否出现问题,是尝试并了解应用程序是否存在特定的计算机硬件问题的方法。
网友评论