Understanding of Crash Log Symbolication

Boudhayan Biswas
5 min readNov 28, 2017

--

The relationship between iOS app and crash was never good. The crash log is an evidence to that. When an application crashed, a crash report is generated and it is stored into the device. Basically, the crash report gives you a snapshot of active frames of the program for a particular point of execution. So it contains very useful pieces of information for debugging the crashes.

What does symbolication mean?

Symbolication is the process of transforming active memory address into a human readable format like method or function names. If you do not symbolicate a crash report, then it is like almost impossible to determine the exact reason behind the crash.

Role of a Compiler:

When you compile the source code, the compiler translated the human readable source code into machine code and creates a compiled binary file. It also generates debug symbols and a mapping table. If you see the mapping table, then here each debug symbol maps to the exact machine instruction in the compiled binary back to the line of source code from which it generated.

Debug Symbol File Storage:

There are two types of build, one is debug build and another one is release build. So depending upon the build setting, by default debug build stores the debug symbols inside the binary, on the other hand, release build stores the debug symbols in a dSYM file to reduce the binary size.The Debug Symbol file and application binary are tied together on a per-build-basis by the build UUID. A new UUID is generated for each build of your application and uniquely identifies that build.

A new term, Bitcode:

As a part of App Thinning process, Bitcode is all about binary optimisations. It is an intermediate representation of a compiled program. If you enable bitcode from build settings, then every time you archive the application, it generates a compiled binary containing bitcode not machine code. So when we upload the build to App Store, that time bitcode is compiled down to machine code. In our absence, The App Store does this for taking advantage of any compiler improvements.

But If we enable bitcode for an app, that means all the frameworks or other third party libraries also need to enable bitcode, otherwise crash log symbolication process will not work.

Collecting Crash Reports:

Crash Logs from Device without XCode: The App users can retrieve the crash reports and send them to you manually by email. So how an user will find crash report in a device?

  1. In Settings app, go to privacy and then open Diagnostics and usage.
  2. Find the log of the crashed app with matching format.
  3. Select the log, copy it and paste the same in the mail. Send.

Crash Logs for Production Apps: If the application is in App Store, then also crash logs can be retrieved from users who have agreed to sending diagnostic and usage information to Apple.

  1. Open XCode, go to Organizer.
  2. Select Crashes section. Crash logs can be found here.

Required files for Symbolication:

Before starting the symbolication, keep in mind that some file are necessary in order to fully symbolicate a crash log. The files are -

  1. Application binary file and dSYM file.
  2. The binary files and dSYM file for all the frameworks or third party libraries those you have added in the project.

Symbolicating Crash Reports using XCode and atos:

XCode: The symbolication is very much easy here. From XCode Window menu, open Devices and choose a Device. Then click on View Device Logs and drag you crash report onto the left column. On behalf of you, XCode will automatically symbolicate the crash file and show the results in the window.

atos: This command basically used for converting numeric addresses to their symbolic equivalents.

SYNOPSIS
atos [-o <binary-image-file>] [-p <pid> | <partial-executable-name>] [-arch architecture]
[-l <load-address>] [-s <slide>] [-printHeader] [-v] [-D] [-f <address-input-file>]
[<address> ...]

So for symbolicating with atos, we can run the below command on terminal

atos -arch <Binary Architecture> -o <Path to dSYM file>/Contents/Resources/DWARF/<binary image name> -l <load address> <address to symbolicate>

If you are an active iOS developer, then you are already aware about some of common exception types for which crashes occur. Lets dig in to those common exception types-

Bad Memory Access [EXC_BAD_ACCESS]

A major reason of receiving EXC_BAD_ACCESS exception is trying to access released objects. So basically it’s an attempt to access a memory location which is already invalid.

Abnormal Exit [SIGABRT]

This type of exception comes when you are exiting a program abnormally. These type of exceptions are mostly uncaught exceptions. Basically it tells the process to abort. You can raise these type of exceptions yourself by calling abort() or assert() method.

Trace Trap [SIGTRAP]

It does not show the origin of the crash. These type of exceptions are thrown into main thread run loop. It is mostly used for debugger watchpoints.

Illegal Instruction [SIGILL]

It is caused by an attempt to execute an illegal instruction. Illegal instruction means malformed or unknown instructions. You can face this type of exception if your code jumps to an invalid but executable memory address.

SIGFPE

It is an exception of type floating point exception or arithmetic exception. So it may come if you perform some invalid arithmetic operation like dividing an integer by zero.

SIGBUS

A bus error. It may come when you are trying to load an unaligned pointer.

SIGSEGV

This exceptions are thrown when kernel determines that the process is trying to access an invalid memory location. If you try to dereference an invalid pointer then you will face this exception.

SIGQUIT

The process was terminated at the request of another process with privileges to manage its lifetime. It does not mean that the process crashed, but it did likely misbehave in a detectable manner.

Suggestion (Keep In Mind)

Terminating an app by removing it from the multitasking tray does not generate a crash report. User has forcefully stopped the execution, so no crash report is available. This is same for the suspended app also because if an app is in suspended state, then iOS will decide the termination of that app. So in this case also no crash report will be generated.

Thanks for giving your valuable time to read this article. If you have suggestion, please feel free to comment.

--

--

Boudhayan Biswas

Swift Developer. In love with Python & Machine Learning.