Give your simulator superpowers

RocketSim: An Essential Developer Tool
as recommended by Apple

Symbolicate crash logs with Xcode

When you receive an unreadable crash report, you can symbolicate crash logs with the help of Xcode. As a developer, it’s essential to identify symbols and ensure you can fix a crash that potentially affects many of your app’s users.

Many of us will benefit from an online platform like Firebase or Datadog, which will symbolicate crash logs for us. However, there are cases in which you receive ips files extracted from the Console app after one of your colleagues encountered a crash. Before you can read those logs, you need to symbolicate the symbols. This article starts by explaining two essential file formats in this process: IPS and DSYM files.

What are ips files?

IPS files are crash reports generated by apps that store data as JSON in files with an .ips extension. This file format was first introduced in iOS 15 and macOS 12. The JSON contains two main objects:

  • IPS Metadata describing the crash on a higher level
  • Crash Report Data describing the crash in detail with threading information

If you want to know more about this file format, I encourage you to read Interpreting the JSON format of a crash report.

What are dSYM files?

A dSYM file is a Debug Symbole File (hence the name) generated by Xcode and contains all the necessary debugging information to symbolicate your crash log. In other words, you need to use a dSYM file that matches the app version of the crash report to turn a crash report into a readable format.

Exporting Crash Reports from Xcode

Before diving into symbolicating crash logs, I’d like to explain how you can benefit from a technique that helped me solve many crashes. Occasionally, a colleague calls me out, telling me our app crashed on their device. Ideally, you could find back crash reports on an online platform like Datadog. However, there are cases in which you need to ask the colleague to extract the crash report manually.

Exporting Crash Reports using Xcode

Those colleagues that got Xcode installed can follow the following steps to export Crash Reports:

  1. Open Xcode
  2. Go to the menu bar and select Window → Devices and Simulators
  3. Click on Open Recent Logs
Xcode allows you to open logs for Simulators and Devices.
Xcode allows you to open logs for Simulators and Devices.

A Finder window will open after clicking “Open Recent Logs”, showing all ips files for crash logs related to the device. Your colleague should right-click the most recent crash file for your app and select “Show in Finder” to be able to share the file with you directly.

Finding Device Crash Logs without Xcode

In case your colleague doesn’t have Xcode installed, you can ask them to follow these steps:

  1. Connect the device to your Mac
  2. Open Finder and choose Go → Go to Folder from the menu bar
  3. Enter ~/Library/Logs/CrashReporter/
  4. Open the folder identified by your device’s name
  5. Select the logs named after your app

Note that this method doesn’t always work as expected, so I always try to use Xcode if possible.

Exporting Mac app Crash Reports

For Mac apps, exporting crash reports can be done using the Console app:

  1. Open the Console app
  2. Select Crash Reports in the sidebar
  3. Export the crashes named after your app

This is how that window looks for me:

The Console app allows you to export crash reports for Mac apps.
The Console app allows you to export crash reports for Mac apps.

Your colleague needs to find a crash report in which the Process Name matches the name of your application.

How do you stay current as a Swift developer?

Let me do the hard work and join 19,144 developers that stay up to date using my weekly newsletter:

How to manually symbolicate a crash log

Back in the day, I’d start explaining how to manually symbolicate a crash log using the terminal. However, luckily enough, we’re now able to benefit from a fantastic open-source application called MacSymbolicator.

The application allows you to select a crash report on the left-hand side and dSYM files on the right. It supports old .crash file extensions and the new .ips and .txt formats. The best thing is that it will automatically scan your Mac for a matching dSYM file for the crash report.

Symbolicate a crash log manually using MacSymbolicator.
Symbolicate a crash log manually using MacSymbolicator.

For example, I’ve been able to change a RocketSim crash log from:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BREAKPOINT (SIGTRAP)
Exception Codes:       0x0000000000000001, 0x00000001026574e4

Termination Reason:    Namespace SIGNAL, Code 5 Trace/BPT trap: 5
Terminating Process:   exc handler [7689]

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   RocketSim                     	       0x1026574e4 0x102500000 + 1406180
1   RocketSim                     	       0x10265727c 0x102500000 + 1405564
2   SwiftUI                       	       0x1bbcebd50 0x1bac1b000 + 17632592
3   RocketSim                     	       0x10265671c 0x102500000 + 1402652
4   RocketSim                     	       0x102655a28 0x102500000 + 1399336

Into a more readable format:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BREAKPOINT (SIGTRAP)
Exception Codes:       0x0000000000000001, 0x00000001026574e4

Termination Reason:    Namespace SIGNAL, Code 5 Trace/BPT trap: 5
Terminating Process:   exc handler [7689]

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   RocketSim                     	       0x1026574e4 closure #1 in GridView.thinGridLines(geometry:) (in RocketSim) (GridView.swift:50) + 1406180
1   RocketSim                     	       0x10265727c closure #1 in GridView.thinGridLines(geometry:) (in RocketSim) (GridView.swift:50) + 1405564
2   SwiftUI                       	       0x1bbcebd50 0x1bac1b000 + 17632592
3   RocketSim                     	       0x10265671c GridView.thinGridLines(geometry:) (in RocketSim) (GridView.swift:65) + 1402652
4   RocketSim                     	       0x102655a28 closure #1 in GridView.body.getter (in RocketSim) (GridView.swift:27) + 1399336

The symbolicated crash report tells me I must look into the GridView.thinGridLines(geometry:) method to solve the crash.

Solving a symbolicated crash report

Now that we’ve symbolicated our crash report, it’s crucial to take a step back and consider whether you want to spend time solving the crash. Like with all tasks, you need to prioritize and determine how many users are likely affected by the same crash. Ideally, you’d solve all crashes, but in my experience, that’s never possible.

Therefore, I always open Xcode Organizer to determine whether more users are having a similar crash. This works great since Xcode will collect and symbolicate crash reports for users that opted in for sending logs:

Xcode Organizer allows you to explore symbolicated crashes for your app.
Xcode Organizer allows you to explore symbolicated crashes for your app.

In my example, I decided to instead focus on another crash that affects many more users.

An extra benefit of finding your crash inside Xcode is that you can navigate directly to the code related to the crash. This can drastically impact the time you spend finding out where and how a crash occurred.

Lastly, I recommend always looking at the code where the crash occurred. If you can fairly quickly indicate the cause of a crash, you could solve it as a quick win.

Mark the crash as resolved and add a note for your future self to ensure regressions are easier to follow up:

Mark crashes as resolved in Xcode with a note for your future self.
Mark crashes as resolved in Xcode with a note for your future self.

Conclusion

Knowing how to manually symbolicate a crash report is a crucial skill for an app developer. It allows you to increase the stability of your app and improve the user experience. Xcode provides several tools to help you solve and manage incoming crash reports.

If you like to improve your Xcode knowledge, even more, check out the Xcode category page. Feel free to contact me or tweet me on Twitter if you have any additional tips or feedback.

Thanks!

 
Antoine van der Lee

Written by

Antoine van der Lee

iOS Developer since 2010, former Staff iOS Engineer at WeTransfer and currently full-time Indie Developer & Founder at SwiftLee. Writing a new blog post every week related to Swift, iOS and Xcode. Regular speaker and workshop host.

Are you ready to

Turn your side projects into independence?

Learn my proven steps to transform your passion into profit.