Kevin Cupp

Symbolicating iOS Crash Logs

During iPhone app beta testing, and even when you have apps on the App Store, it’s often difficult to reproduce crashes reported from users. Luckily, iOS devices keep logs of each crash1 and can even tell you the exact line of code that caused the problem. Let’s take a look at a crash log for MyApp:

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Thread 0 name:  Dispatch queue:
Thread 0 Crashed:
0   libobjc.A.dylib           0x313fec98 0x313fc000 + 11416
1   MyApp                     0x00019c12 0x1000 + 101394
2   MyApp                     0x0000a1cc 0x1000 + 37324
3   MyApp                     0x0000c474 0x1000 + 46196
4   libdispatch.dylib         0x33e9d8e0 0x33e92000 + 47328
5   libdispatch.dylib         0x33e991ee 0x33e92000 + 29166
6   CoreFoundation            0x3568e934 0x35616000 + 493876
7   CoreFoundation            0x3561eebc 0x35616000 + 36540
8   CoreFoundation            0x3561edc4 0x35616000 + 36292
9   GraphicsServices          0x343cd418 0x343c9000 + 17432
10  GraphicsServices          0x343cd4c4 0x343c9000 + 17604
11  UIKit                     0x3608ad62 0x3605c000 + 191842
12  UIKit                     0x36088800 0x3605c000 + 182272
13  MyApp                     0x000024ec 0x1000 + 5356
14  MyApp                     0x000024ac 0x1000 + 5292

How are we supposed to tell anything from that? Only the hex symbols of the objects are there, so we need to symbolicate2 them. I am writing this short guide because Apple hasn’t documented this process very well, and no single article online had all the information I needed to get the job done. This post assumes a certain ability to debug your code too once you have the log symbolicated.

First, and most importantly, you need to have the .app and .dSYM file for the build that generated the crash log. This is why it’s very important to archive every build you distribute3, whether it be ad hoc or via the App Store. If you don’t have the original build, you’re out of luck.

I find it’s easiest to have everything, the .app, .dSYM, and .crash files, in the same directory. Next, we have to run a shell command called symbolicate which comes with Xcode. It’s a long path, so I recommend creating a bash/zsh alias for this, here’s mine:

alias symbolicate="/Developer/Platforms/iPhoneOS.platform/Developer/Library/\
Resources/symbolicatecrash -v"

Once that’s set in your shell, you can run the following, replacing the appropriate values of course:

symbolicate "MyApp_2011-05-10-170924-iPhone.crash" ""

Now you should see a lovely, symbolicated crash log spat out into the terminal:4

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Thread 0 name:  Dispatch queue:
Thread 0 Crashed:
0   libobjc.A.dylib        0x33b24c98 objc_msgSend + 16
1   MyApp                  0x00019c12 -[TwoLineNavBarTitleView setLine2:] 
2   MyApp                  0x0000a1cc -[ListViewController 
3   MyApp                  0x0000c474 __45-[ListViewModel 
4   libdispatch.dylib      0x33d108e0 _dispatch_call_block_and_release + 4
5   libdispatch.dylib      0x33d0c1ee _dispatch_main_queue_callback + 306
6   CoreFoundation         0x3039f934 __CFRunLoopRun + 1328
7   CoreFoundation         0x3032febc CFRunLoopRunSpecific + 224
8   CoreFoundation         0x3032fdc4 CFRunLoopRunInMode + 52
9   GraphicsServices       0x35571418 GSEventRunModal + 108
10  GraphicsServices       0x355714c4 GSEventRun + 56
11  UIKit                  0x358c7d62 -[UIApplication _run] + 398
12  UIKit                  0x358c5800 UIApplicationMain + 664
13  MyApp                  0x000024ec main (main.m:14)
14  MyApp                  0x000024ac 0x1000 + 5292

Here I can see which method was called (setLine2: in my custom view class) and that it was called from line 43 of the same class. Much more helpful. Now I can fix my over-released memory reference and call this bug squashed.

  1. How you get the logs is another story. They're stored on the user's computer after syncing with iTunes. If you have a line of communication with your users, it's usually easy for them to find the relevant logs and send them to you. iTunes Connect supposedly gathers crash logs for you but I've never seen any in there. I haven't experimented with ways of in-app crash reporting yet.
  2. Isn't that a cool word?
  3. Xcode's built-in Archive function is great for this, especially when paired with Time Machine.
  4. I typically like to use the -o tack on the symbolicate command to output the results to a file for easier reading and organization.