美文网首页
crash之理论分析-iOS崩溃系列之《崩溃日志分析》

crash之理论分析-iOS崩溃系列之《崩溃日志分析》

作者: 梁炜东 | 来源:发表于2021-07-24 12:05 被阅读0次

    崩溃日志分析

    通过崩溃日志中的重要线索能够帮助我们迅速定位问题。

    崩溃日志结构介绍

    分为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代表什么意思?

    相关文章

      网友评论

          本文标题:crash之理论分析-iOS崩溃系列之《崩溃日志分析》

          本文链接:https://www.haomeiwen.com/subject/dsommltx.html