crash之理論分析-iOS崩潰系列之《崩潰日志分析》

崩潰日志分析

通過崩潰日志中的重要線索能夠幫助我們迅速定位問題。

崩潰日志結構介紹

分為Header區、Exception Information區、Diagnostic Messages區、Exception Backtrace區、每個線程堆棧區、崩潰線程狀態區、二進制文件列表區。


image.png

Header

每個崩潰日志都有Header區,Header區包含了app崩潰時所處的場景,例如:
崩潰日志唯一標識、設備型號、進程號、路徑、包名、版本、指令集、前后臺、父進程、崩潰時間、程序啟動時間、iOS系統版本等。

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)
  • Incident Identifier:崩潰日志唯一id
  • CrashReporter Key:加過密的設備唯一標識,設備重裝系統時該key會被修改
  • Hardware Model:設備型號
  • Process:app名稱(CFBundle Executable值),后面的是進程號
  • Path:app在手機硬盤的路徑
  • Identifier:應用唯一標識( CFBundleIdentifier )
  • Version:app版本號(CFBundleVersion )
  • AppStoreTools:XCode編譯app bitcode和thin app的版本
  • AppVariant:一般沒啥用,格式 1:iPhone10,6:12.2
  • Code Type:CPU指令集
  • Role:一般用不著這個字段
  • Parent Process:父進程
  • Date/Time:崩潰時間
  • Launch Time:app啟動時間
  • OS Version:iOS系統版本

Exception Information
異常信息比較重要,但通常容易被忽略。通過異常信息大概能夠斷定崩潰是怎么發生的。

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x0000000102afb3d0

注意:
這兒的異常信息并不是根據OC或者C++等語言的API得來的,崩潰日志會單獨記錄OC或C++ API信息。

下面列出了異常信息中比較重要的項,崩潰日志不一定全部包含一下所有項。

  • Exception Type:異常類型,殺掉進程的Mach異常名稱,括號內代表Unix異常,Mach異常可以映射成Unix信號異常查閱崩潰類型Exception Type
  • 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:崩潰所在線程

Diagnostic Messages
診斷信息,并不是所有崩潰日志都包含這項。

當一些框架出現錯誤時,它可能在崩潰之前,往這個區域寫一些日志,舉個例子:

Application Specific Information:
BUG IN CLIENT OF LIBDISPATCH: dispatch_sync called on queue already owned by current thread

注意:
Application Specific Information有時候會被省略,因為可能涉及隱私信息泄露。

如果是被watchdog殺掉進程,則會出現這些信息。

Termination Description: SPRINGBOARD, 
    scene-create watchdog transgression: application<com.example.MyCoolApp>:667
    exhausted real (wall clock) time allowance of 19.97 seconds 

如何定位watchdog強殺

如果是內存問題,則會出現這些信息。

VM Region Info: 0 is not in any region.  Bytes before following region: 4307009536
      REGION TYPE                      START - END             [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                 0000000100b7c000-0000000100b84000 [   32K] r-x/r-x SM=COW  ...pp/MyGreatApp

如何排查內存崩潰問題

Backtraces
堆棧信息。如果崩潰是OC、C++、Swift上層語言引起的,除了堆棧信息還會有Last Exception Backtrace額外信息來幫助定位問題。
如何定位開發語言(OC、C++、Swift)異常


第一行線程名稱,注意通過xcode Crashes Organizer工具查看崩潰日志因為隱私原因是沒有展示出來的。

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 + 4
Thread 1:
0   libsystem_pthread.dylib           0x00000001b6645758 start_wqthread + 0
Thread 2:
0   libsystem_pthread.dylib           0x00000001b6645758 start_wqthread + 0
...

在線程號之后是棧幀。

  • 0:棧幀編號,棧幀都是排好序的,從后執行都先執行進程排序
  • TouchCanvas:函數所在的二進制名稱
  • 0x0000000102afb3d0:正在執行的機器碼地址
  • CanvasView.updateEstimatedPropertiesForTouche:應用函數
  • 62416:函數入口到該函數的offset
  • CanvasView.swift:231:如果有對應的dsYM文件,文件名稱和函數行號

有時候這個行號和源碼行號并不對應:

  • 編譯器動態創建的代碼 compiler-generated
  • inline函數

Thread State

這個section會列出崩潰時CPU各寄存器的值。iOS ABI 函數調用規約

Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x0000000000000001   x1: 0x0000000000000000   x2: 0x0000000000000000   x3: 0x000000000000000f
    x4: 0x00000000000001c2   x5: 0x000000010327f6c0   x6: 0x000000010327f724   x7: 0x0000000000000120
    x8: 0x0000000000000001   x9: 0x0000000000000001  x10: 0x0000000000000001  x11: 0x0000000000000000
   x12: 0x00000001038612b0  x13: 0x000005a102b075a7  x14: 0x0000000000000100  x15: 0x0000010000000000
   x16: 0x00000001c3e6c630  x17: 0x00000001bae4bbf8  x18: 0x0000000000000000  x19: 0x0000000282c14280
   x20: 0x00000001fe64a3e0  x21: 0x4000000281f1df10  x22: 0x0000000000000001  x23: 0x0000000000000000
   x24: 0x0000000000000000  x25: 0x0000000282c14280  x26: 0x0000000103203140  x27: 0x00000001bacf4b7c
   x28: 0x00000001fe5ded08   fp: 0x000000016d311310   lr: 0x0000000102afb3d0
    sp: 0x000000016d311200   pc: 0x0000000102afb3d0 cpsr: 0x60000000
   esr: 0xf2000001  Address size fault

搞明白崩潰線程寄存器狀態

Binary Images
列出所有進程加載的二進制包信息。

Binary Images:
0x102aec000 - 0x102b03fff TouchCanvas arm64  <fe7745ae12db30fa886c8baa1980437a> /var/containers/Bundle/Application/51346174-37EF-4F60-B72D-8DE5F01035F5/TouchCanvas.app/TouchCanvas
...
  • 0x102aec000 - 0x102b03fff:二進制包隨機地址
  • TouchCanvas:二進制包名
  • arm64:CPU指令集
  • fe7745ae12db30fa886c8baa1980437a:UUID
  • /var/containers/…/TouchCanvas.app/TouchCanvas:二進制包所在disk路徑

如何分析崩潰日志

如何查看當前崩潰日志是否被符號化

通過Header信息確定崩潰場景

Ask some questions

  • 崩潰只發生在app其中一個版本還是多個版本都出現過?
  • 崩潰是否只發生在特定的iOS系統中?
  • 崩潰只發生在某個特定設備下還是都有可能,iPad or iPhone?
  • 崩潰出現在主bundle還是在app extension?
  • 崩潰的包是testflight還是正式包?
  • 所有的崩潰都發生在同一個app變體(App Thinning),是否能夠重新打出這個app變體的包重現這個崩潰?Appstore connect比Ad Hoc大很多。
  • 崩潰發生在具體什么設備型號上?iPhone6、iPhone7?
  • 很多用戶都遇到了這個崩潰還是說只是特定的小部分人?
  • 崩潰時app運行了多久?

通過Exception Information來排查

  • Exception Type崩潰類型是什么?
  • 哪個線程拋出的異常?
  • 看是否有中斷原因,對應code代表什么意思?
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容