Mesird

Get crash logs on mobile device

Every iOS developer knows that we can get crash information while running application via Xcode, including simulator and mobile device. Basically this would help us to debug under most conditions, however sometimes crashes are not discovered by us, like testers. Thus, we need to fetch these crash logs from their devices.

There will be several steps to get crash log.

First of all, connect the target device to your Mac, sync via iTunes.

Then, open directory ~/Library/Logs/CrashReporter/MobileDevice/YourMobileName/Retired, and you will see files named like BundleName-Time.crash. These files are generated by mobile when the application crashed, this would help us to find out what’s going on.

Quite easy, isn’t it? Well, let’s see what’s in it. A crash log would looks like this(a crash report demo):

Incident Identifier: 80F61CF6-CECC-4E9D-A85E-03F68BBBBC73
CrashReporter Key:   383daadfbd4ac97cf2e53531fc349858fb09ae3c
Hardware Model:      iPhone6,2
Process:             MyAppName [6485]
Path:                /private/var/containers/Bundle/Application/9DB38223-0B3F-4F9E-AAFA-BD025B7C2602/MyAppName.app/MyAppName
Identifier:          com.myCompany.MyAppName
Version:             1 (5.2.12)
Code Type:           ARM-64 (Native)
Parent Process:      launchd [1]

Date/Time:           2016-06-14 14:23:25.25 +0800
Launch Time:         2016-06-14 14:23:23.23 +0800
OS Version:          iOS 9.3.2 (13F69)
Report Version:      105

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Triggered by Thread:  0

Filtered syslog:
None found

Last Exception Backtrace:
(0x181c9edb0 0x181303f80 0x181c9ec80 0x182624154 0x1005461f8 0x181ca4a60 0x181b9c488 0x1857ba294 0x1857b9e38 0x1857bb030 0x185362ae8 0x1857a1d38 0x18579bed8 0x1856c79fc 0x18536683c 0x1853665ec 0x185756658 0x100556ff0 0x181ca2a1c 0x181ba0c5c 0x186dfcc40 0x186dfc844 0x100107044 0x1872d3a50 0x187540b84 0x1002c50e4 0x1002c39bc 0x100165184 0x10016471c 0x100329508 0x1004d5d24 0x1004f82e8 0x1816e94bc 0x1816e947c 0x1816eeb84 0x181c54d50 0x181c52bb8 0x181b7cc50 0x183464088 0x186e66088 0x1002d887c 0x18171a8b8)

Global Trace Buffer (reverse chronological seconds):
0.424518     libsystem_trace.dylib     0x000000018191c9cc dyld_image_header_containing_address(0x144f8e891) failed
0.908955     CFNetwork                 0x0000000182281a80 TCP Conn 0x144d93d80 SSL Handshake DONE
0.941332     CFNetwork                 0x0000000182281990 TCP Conn 0x144d93d80 starting SSL negotiation
0.941448     CFNetwork                 0x0000000182323f18 TCP Conn 0x144d77ac0 complete. fd: 14, err: 0
0.941738     CFNetwork                 0x0000000182323f18 TCP Conn 0x144d93d80 complete. fd: 10, err: 0
0.941917     CFNetwork                 0x0000000182325444 TCP Conn 0x144d77ac0 event 1. err: 0
0.942189     CFNetwork                 0x0000000182325444 TCP Conn 0x144d93d80 event 1. err: 0
0.953446     CFNetwork                 0x0000000182323f18 TCP Conn 0x144d55bb0 complete. fd: 5, err: 0
0.953773     CFNetwork                 0x0000000182325444 TCP Conn 0x144d55bb0 event 1. err: 0
0.957419     CFNetwork                 0x000000018232551c TCP Conn 0x144d93d80 started
0.961604     CFNetwork                 0x0000000182281a80 TCP Conn 0x144f07400 SSL Handshake DONE
1.029544     CFNetwork                 0x0000000182281990 TCP Conn 0x144f07400 starting SSL negotiation
1.037481     CFNetwork                 0x0000000182323f18 TCP Conn 0x144f07400 complete. fd: 7, err: 0
1.037481     CFNetwork                 0x000000018232551c TCP Conn 0x144d77ac0 started
1.043621     CFNetwork                 0x000000018232551c TCP Conn 0x144d55bb0 started
1.050324     CFNetwork                 0x0000000182325444 TCP Conn 0x144f07400 event 1. err: 0
1.076020     libsystem_trace.dylib     0x000000018191c9cc dyld_image_header_containing_address(0x144d7b291) failed
1.089100     libsystem_trace.dylib     0x000000018191c9cc dyld_image_header_containing_address(0x144d8e351) failed
1.132366     CFNetwork                 0x000000018232551c TCP Conn 0x144f07400 started
1.145189     CFNetwork                 0x000000018237fe5c Creating default cookie storage with default identifier
1.145189     CFNetwork                 0x000000018237fe28 Faulting in CFHTTPCookieStorage singleton
1.145189     CFNetwork                 0x00000001823d1e50 Faulting in NSHTTPCookieStorage singleton



Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib        0x000000018183811c 0x18181c000 + 114972
1   libsystem_pthread.dylib       0x0000000181904ef8 0x181900000 + 20216
2   libsystem_c.dylib             0x00000001817a9dac 0x181748000 + 400812
3   libc++abi.dylib               0x00000001812dd3f4 0x1812dc000 + 5108
4   libc++abi.dylib               0x00000001812f9e98 0x1812dc000 + 122520
5   libobjc.A.dylib               0x0000000181304248 0x1812fc000 + 33352
6   libc++abi.dylib               0x00000001812f6f44 0x1812dc000 + 110404
7   libc++abi.dylib               0x00000001812f685c 0x1812dc000 + 108636
8   libobjc.A.dylib               0x0000000181304094 0x1812fc000 + 32916
9   CoreFoundation                0x0000000181c9ec80 0x181b74000 + 1223808
10  Foundation                    0x0000000182624154 0x182580000 + 672084
11  MyAppName                     0x00000001005461f8 0x100024000 + 5382648
12  CoreFoundation                0x0000000181ca4a60 0x181b74000 + 1247840
13  CoreFoundation                0x0000000181b9c488 0x181b74000 + 165000
14  JavaScriptCore                0x00000001857ba294 0x18531c000 + 4842132
15  JavaScriptCore                0x00000001857b9e38 0x18531c000 + 4841016
16  JavaScriptCore                0x00000001857bb030 0x18531c000 + 4845616
17  JavaScriptCore                0x0000000185362ae8 0x18531c000 + 289512
18  JavaScriptCore                0x00000001857a1d38 0x18531c000 + 4742456
19  JavaScriptCore                0x000000018579bed8 0x18531c000 + 4718296
20  JavaScriptCore                0x00000001856c79fc 0x18531c000 + 3848700
21  JavaScriptCore                0x000000018536683c 0x18531c000 + 305212
22  JavaScriptCore                0x00000001853665ec 0x18531c000 + 304620
23  JavaScriptCore                0x0000000185756658 0x18531c000 + 4433496
24  MyAppName                     0x0000000100556ff0 0x100024000 + 5451760
25  CoreFoundation                0x0000000181ca2a1c 0x181b74000 + 1239580
26  CoreFoundation                0x0000000181ba0c5c 0x181b74000 + 183388
27  UIKit                         0x0000000186dfcc40 0x186de8000 + 85056
28  UIKit                         0x0000000186dfc844 0x186de8000 + 84036
29  MyAppName                     0x0000000100107044 0x100024000 + 929860
30  UIKit                         0x00000001872d3a50 0x186de8000 + 5159504
31  UIKit                         0x0000000187540b84 0x186de8000 + 7703428
32  MyAppName                     0x00000001002c50e4 0x100024000 + 2756836
33  MyAppName                     0x00000001002c39bc 0x100024000 + 2750908
34  MyAppName                     0x0000000100165184 0x100024000 + 1315204
35  MyAppName                     0x000000010016471c 0x100024000 + 1312540
36  MyAppName                     0x0000000100329508 0x100024000 + 3167496
37  MyAppName                     0x00000001004d5d24 0x100024000 + 4922660
38  MyAppName                     0x00000001004f82e8 0x100024000 + 5063400
39  libdispatch.dylib             0x00000001816e94bc 0x1816e8000 + 5308
40  libdispatch.dylib             0x00000001816e947c 0x1816e8000 + 5244
41  libdispatch.dylib             0x00000001816eeb84 0x1816e8000 + 27524
42  CoreFoundation                0x0000000181c54d50 0x181b74000 + 920912
43  CoreFoundation                0x0000000181c52bb8 0x181b74000 + 912312
44  CoreFoundation                0x0000000181b7cc50 0x181b74000 + 35920
45  GraphicsServices              0x0000000183464088 0x183458000 + 49288
46  UIKit                         0x0000000186e66088 0x186de8000 + 516232
48  libdyld.dylib                 0x000000018171a8b8 0x181718000 + 10424
47  MyAppName                     0x00000001002d887c 0x100024000 + 2836604
...

This is really a mess right? But don’t worry, we will figure it out step by step.

There are several values at the beginning, they are:

Process Information

Basic Information

Exception

Thread Backtrace

All threads’ status and the backtrace at the crash moment are shown below. The thread which crash occurred on is marked with text Thread i Crashed, following by a list contains stack backtrace.

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libsystem_kernel.dylib        0x000000018183811c 0x18181c000 + 114972
1   libsystem_pthread.dylib       0x0000000181904ef8 0x181900000 + 20216
2   libsystem_c.dylib             0x00000001817a9dac
...

Common Crashes

  1. Watchdog timeout
    There is a description usually after exception information

     Application Specific Information:
     com.xxx.yyy   failed to resume in time
    

    This means your application spent too much time on launching, perhaps there’re some network requests on main thread. This only happens in production environment, it’s ignored in development environment.

  2. User force quit
    Force quit does not mean kill background application, it’s when main thread is blocked and application has no response, user long-press power button and press home button to kill current application.
    Notice that, device won’t generate crash log if application finished by user when it’s in background.
  3. Low memory termination
    When device does not have enough memory, and application memory usage does not decrease, this crash would occur.
  4. Crash due to bugs
    Crash created by program bug.

Common Exception Types

  1. EXC_BAD_ACCESS - application read the forbidden memory
    SIGSEGV : visit invalid address due to instance overrelease
    SIGABRT : quit application because of an abort signal, normally it’s a Foundation lib protection mechanism
    SEGV : invalid address, like empty pointer, uninitialized pointer, stack overflow
    SIGBUS : read valid address but bus error
    SIGILL : execute forbidden commands or have no privilege to execute
  2. EXC_BAD_INSTRUCTION - thread execute forbidden commands
  3. EXC_ARITHMETIC - divided by zero

Common Exception Codes

  1. 0xbaaaaaad - generally, this is not a crash, it’s just a system runtime status triggered by user’s unexpected operations.
  2. 0xbad22222 - activated from background too frequently
  3. 0x8badf00d - launching or resuming duration lasts too long
  4. 0xc00010ff - a large number of calculation for CPU and GPU, application termination due to device overheating
  5. 0xdead10cc - application still consume resources while it’s in background
  6. 0xdeadfa11 - force quit by user

Above are almost all elements in this file, however it’s still difficult for us to find out which line of code directly makes our application crashed. The most useful information I can get right now is the exception information, because I can see what kind of exception is thrown by our application.

Well, but I don’t know what code triggered this exception, so there must be a way to translate these backtrace, which is called Symbolization. but if you want, there’s still some tools can help you, like Xcode, Crashlytics, Flurry and so on.

In the rest of this passage, I’ll introduce how to use Xcode to symbolize the backtrace.

Xcode - Devices

Xcode offers an approach to fetch crash log from a iOS device and symbolize the crash information. With a translated crash report, it would be pretty easy to find out the error code.

Let’s start it.

To get the crash log on a specified device, you still need to connect your device to Mac, sync with iTunes. Then start Xcode if you finish synchronization, open Window -> Devices (or press ⇧ + ⌘ + 2) you’ll see the name of device that you just connected to your Mac is shown on left side of the window (if you cannot see it, just wait util sync finished), then click it.

You’ll get a view like this.

Press View Device Logs, and select All Logs. All recent crash logs of each application are shown below, choose one that you want to see, and the translated crash log displays on the right.

Sometimes you notice that there’s no difference between the crash log from Xcode and the crash log from user directory, that means Xcode cannot symbolicate this crash log backtrace. So How could this happen?

Symbolization

Symbolization is the procedure that translating stack backtrace which is shown as address format to line number of code, making the crash log more readable.


Symbolicating in LLDB

In the development environment, we can debug our program with breakpoint, see backtrace, see value of variable, execute script, etc. Sometimes we meet a crash (provided that we’ve set Global Exception Breakpoint), but Xcode locates in main.h file, thus we cannot know which line of code cause this exception on earth. There’re two ways to figure it out, one is opening debug navigator and select View Process by Thread, then you’ll see several threads below, usually our breakpoint stops on thread 1, spread thread 1 you will get a method call stack, select last one to see which method is invoked and trigger the crash. Another way is input bt command in console, it’s the same usage as former one.

A method call stack (backtrace) usually looks like this:

* thread #1: tid = 0x2466c, 0x000000010179b495 MyAppName`-[MyViewController viewDidLoad](self=0x00007fab44324e80, _cmd="viewDidLoad") + 85 at MyViewController.m:43, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1
  * frame #0: 0x000000010179b495 MyAppName`-[MyViewController viewDidLoad](self=0x00007fab44324e80, _cmd="viewDidLoad") + 85 at MyViewController.m:43
    frame #1: 0x000000010596f984 UIKit`-[UIViewController loadViewIfRequired] + 1198
    frame #2: 0x000000010597593b UIKit`-[UIViewController __viewWillAppear:] + 120
    frame #3: 0x00000001059a5750 UIKit`-[UINavigationController _startCustomTransition:] + 1203
    frame #4: 0x00000001059b5b9b UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 712
    frame #5: 0x00000001059b6d0b UIKit`-[UINavigationController __viewWillLayoutSubviews] + 57
    frame #6: 0x0000000105b65503 UIKit`-[UILayoutContainerView layoutSubviews] + 248
    frame #7: 0x000000010588f980 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703
    frame #8: 0x0000000105546c00 QuartzCore`-[CALayer layoutSublayers] + 146
    frame #9: 0x000000010553b08e QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 366
    frame #10: 0x000000010553af0c QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 24
    frame #11: 0x000000010552f3c9 QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 277
    frame #12: 0x000000010555d086 QuartzCore`CA::Transaction::commit() + 486
    frame #13: 0x000000010555d7f8 QuartzCore`CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 92
    frame #14: 0x000000010392ac37 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    frame #15: 0x000000010392aba7 CoreFoundation`__CFRunLoopDoObservers + 391
    frame #16: 0x00000001039207fb CoreFoundation`__CFRunLoopRun + 1147
    frame #17: 0x00000001039200f8 CoreFoundation`CFRunLoopRunSpecific + 488
    frame #18: 0x000000010a059ad2 GraphicsServices`GSEventRunModal + 161
    frame #19: 0x00000001057d4f09 UIKit`UIApplicationMain + 171
    frame #20: 0x0000000101a99fcf MyAppName`main(argc=1, argv=0x00007fff5e55e660) + 111 at main.m:14
    frame #21: 0x000000010939c92d libdyld.dylib`start + 1

If we only have the address of method, how do we know which line then? — The image command.

LLDB offers a command image to translate address to line number of code, here’s the usage:

image lookup --address 0x000000010179b495

and here’s what you got:

Address: MyAppName[0x00000001000fb495] (MyAppName.__TEXT.__text + 1020165)
Summary: MyAppName`-[MyViewController viewDidLoad] + 85 at MyViewController.m:43

Symbolicating with .dSYM file

references

iOS应用崩溃日志揭秘
Symbolicating Crash Logs
(Stackoverflow) iphone: Where the .dSYM file is located in crash report
iOS Crash文件的解析(一)