Demystifying iOS Application Crash Logs
This is a blog post by Soheil Moayedi Azarpour, an independent iOS developer. You can also find him on Google+. Have you ever had the following experience as an app developer? Before you submit your app, you perform a lot of testing to make sure your app runs flawlessly. It works fine on your device, […] By Soheil Azarpour.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Demystifying iOS Application Crash Logs
50 mins
- What Is A Crash Log, and Where Do I Get One?
- What Generates a Crash Log?
- A Sample Crash Log
- Demystification with Symbolication
- Low Memory Crashes
- Exception Codes
- Swimming Time!
- Scenario 1: Bad Code for Breakfast
- Scenario 2: Button FUBAR
- Scenario 3: Another Bug On the Table
- Scenario 4: Leggo Those Licks!
- Where to Go From Here?
A Sample Crash Log
Let’s start by taking a look at a sample crash log, so that you have an idea of what to expect before tackling some real scenarios.
Without further ado, meet your new friend:
// 1: Process Information
Incident Identifier: 30E46451-53FD-4965-896A-457FC11AD05F
CrashReporter Key: 5a56599d836c4f867f6eec76afee451bf9ae5f31
Hardware Model: iPhone4,1
Process: Rage Masters [4155]
Path: /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters
Identifier: Rage Masters
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
// 2: Basic Information
Date/Time: 2012-10-17 21:39:06.967 -0400
OS Version: iOS 6.0 (10A403)
Report Version: 104
// 3: Exception
Exception Type: 00000020
Exception Codes: 0x000000008badf00d
Highlighted Thread: 0
// 4: Threads backtraces
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 libsystem_kernel.dylib 0x327f2eb4 mach_msg_trap + 20
1 libsystem_kernel.dylib 0x327f3048 mach_msg + 36
2 CoreFoundation 0x36bd4040 __CFRunLoopServiceMachPort + 124
3 CoreFoundation 0x36bd2d9e __CFRunLoopRun + 878
4 CoreFoundation 0x36b45eb8 CFRunLoopRunSpecific + 352
5 CoreFoundation 0x36b45d44 CFRunLoopRunInMode + 100
6 CFNetwork 0x32ac343e CFURLConnectionSendSynchronousRequest + 330
7 Foundation 0x346e69ba +[NSURLConnection sendSynchronousRequest:returningResponse:error:] + 242
8 Rage Masters 0x000d4046 0xd2000 + 8262
Thread 1:
0 libsystem_kernel.dylib 0x32803d98 __workq_kernreturn + 8
1 libsystem_c.dylib 0x3a987cf6 _pthread_workq_return + 14
2 libsystem_c.dylib 0x3a987a12 _pthread_wqthread + 362
3 libsystem_c.dylib 0x3a9878a0 start_wqthread + 4
// 5: Thread state
Thread 0 crashed with ARM Thread State (32-bit):
r0: 0x00000000 r1: 0x00000000 r2: 0x00000001 r3: 0x39529fc8
r4: 0xffffffff r5: 0x2fd7d301 r6: 0x2fd7d300 r7: 0x2fd7d9d0
r8: 0x2fd7d330 r9: 0x3adbf8a8 r10: 0x2fd7d308 r11: 0x00000032
ip: 0x00000025 sp: 0x2fd7d2ec lr: 0x001bdb25 pc: 0x30301838
cpsr: 0x00000010
// 6: Binary images
Binary Images:
0xd2000 - 0xd7fff +Rage Masters armv7 <f37ee6d2c7b334868972e0e9c54f7062> /var/mobile/Applications/A5635B22-F5EF-4CEB-94B6-FE158D885014/Rage Masters.app/Rage Masters
0x2fe41000 - 0x2fe61fff dyld armv7 <75594988728831d98e1f7c4c7b7ca29d> /usr/lib/dyld
0x327f2000 - 0x32808fff libsystem_kernel.dylib armv7 <f167dacec44b3a86a8eee73400ff7a83> /usr/lib/system/libsystem_kernel.dylib
0x328a8000 - 0x328bdfff libresolv.9.dylib armv7 <e79b59a3406f34d9b37f8085955115ce> /usr/lib/libresolv.9.dylib
0x32a70000 - 0x32b35fff CFNetwork armv7 <3e973794a4d13428bb974edcb2027139> /System/Library/Frameworks/CFNetwork.framework/CFNetwork
0x32b7a000 - 0x32cc3fff libicucore.A.dylib armv7 <0253932c1b9038a0849ef73c38e076ca> /usr/lib/libicucore.A.dylib
0x32cc4000 - 0x32cc5fff CoreSurface armv7 <b3f9d4e8dd803a48b88c58a0663d92a3> /System/Library/PrivateFrameworks/CoreSurface.framework/CoreSurface
0x32f65000 - 0x32f8afff OpenCL armv7 <f7706501012430fc94ed99006419fba9> /System/Library/PrivateFrameworks/OpenCL.framework/OpenCL
There is a lot of mysterious stuff in this report. :] Let’s go through it section-by-section:
(1) Process Information
This first section gives you some information about the process that crashed.
- Incident Identifier is a unique identifier for the crash report.
- CrashReporter Key is also a unique key that is mapped to the device identifier. Although it is anonymized, it gives you a very useful piece of information: if you see 100 crash logs from the same CrashReporter Key or a few CrashReporter Keys, it means that the issue might not be a widespread problem, limited to only one or a few devices.
- The Hardware Model identifies the device type. If you get a lot of crashes from the same device model, it might mean that your app is not working properly on a specific model. In the log above, the device is an iPhone 4s.
- Process is the name of the application. The number in the brackets is the process ID of the application at the time of crash.
- The next few lines should be self-explanatory.
(2) Basic Information
This section gives you some basic information about the date and time of the crash, and the version of iOS running on the device. If you have a lot of crash logs coming from iOS 6.0, it might mean that your problem is specific to iOS 6.
(3) Exception
In this section, you can see the type of exception that was thrown at the time of the crash. You also get the exception code and the thread that threw the exception. Depending on the type of crash report, you may get some extra information in this section as well.
(4) Threads backtraces
This section provides the backtrace log for all threads in the app. Backtrace is a list of all active frames at the time of the crash. It gives you a list of function calls when the crash happened. Consider the line below:
2 XYZLib 0x34648e88 0x83000 + 8740
It is basically four columns:
- The frame number – in this case, 2.
- The name of the binary – in this case, XYZLib.
- The address of the function that was called – in this case, 0x34648e88.
- The fourth column is divided into two sub-columns, a base address and an offset. Here it is 0x83000 + 8740, where the first number points to the file, and the second points to the line of code in that file.
(5) Thread state
This section gives you the values in the registers at the time of crash. You don’t usually need this section, because the backtrace has already given you the information you need to find your problem.
(6) Binary images
This section lists all the binaries that were loaded at the time of the crash.
Demystification with Symbolication
When you first look at the backtrace in a crash log, it doesn’t make sense. You’re used to working with function names and line numbers, not a cryptic location like this:
6 Rage Masters 0x0001625c 0x2a000 + 30034
The process of converting from these hexidecimal addresses in the executable code to method names and line numbers is called symbolification.
When you get crash logs off of a device through Xcode’s Organizer window, they are automatically symbolicated after a few seconds. The symbolicated version of the above line is this:
6 Rage Masters 0x0001625c -[RMAppDelegate application:didFinishLaunchingWithOptions:] (RMAppDelegate.m:35)
For Xcode to symbolicate a crash log, it needs to have access to the matching application binary that was uploaded to the App Store, and the .dSYM file that was generated when that binary was built. This must be an exact match; otherwise, the report cannot be fully symbolicated.
So, it is essential that you keep each build distributed to users. When you archive your app before submission, Xcode stores your binary. You can find all of your archived applications in the Xcode Organizer under the Archives tab.
Xcode will automatically symbolicate all crash reports that it encounters, if it has the matching .dSYM and application binary that produced the crash report. If you are switching computers or creating a new account, make sure you move over all of those binaries and put them in the right place, where Xcode can find them.
Note: You must keep both the application binary and the .dSYM file to be able to fully symbolicate crash reports. You should archive these files for every build that you submit to iTunes Connect.
The .dSYM and application binary are specifically tied together on a per-build-basis, and subsequent builds, even from the same source files, will not interoperate with files from other builds.
If you use the Build and Archive command, the files will be placed in a suitable location automatically. Otherwise, any location searchable by Spotlight (such as your home directory) is fine.
Note: You must keep both the application binary and the .dSYM file to be able to fully symbolicate crash reports. You should archive these files for every build that you submit to iTunes Connect.
The .dSYM and application binary are specifically tied together on a per-build-basis, and subsequent builds, even from the same source files, will not interoperate with files from other builds.
If you use the Build and Archive command, the files will be placed in a suitable location automatically. Otherwise, any location searchable by Spotlight (such as your home directory) is fine.