Quick answer: A crash dump is a snapshot of a process's memory at the moment it crashes. On Windows these are called minidumps (.dmp files), on Linux they are core dumps, and on macOS/iOS they are .crash or .ips files.
This guide covers capture symbolicate crash dumps player devices in detail. Your game shipped. Players are crashing. The reports say "it just closes" with no further detail. Without crash dumps and the symbols to decode them, you are debugging blind. This guide covers how to capture crash dumps from player machines across every major platform, how to symbolicate those dumps into readable stack traces, and how to automate the entire pipeline so you never lose a crash again.
What Are Crash Dumps?
A crash dump is a snapshot of your game's process state at the exact moment it crashes. It captures thread stacks, CPU register values, loaded modules, and a subset of memory. The format varies by platform:
Windows minidumps (.dmp) are the most common format in PC game development. When a game crashes, Windows can generate a minidump containing the call stack for every thread, the exception record, and the list of loaded DLLs. A typical minidump is between 50 KB and 5 MB, small enough to upload from player machines without issue.
Linux core dumps contain a full memory image of the process by default, which can be enormous. For game crash reporting you almost always want to use Breakpad or Crashpad to generate a minidump-format file instead. These are the same compact format as Windows minidumps and can be analyzed with the same tooling.
macOS and iOS .crash files are plain-text logs generated by the operating system's crash reporter. They include a partially symbolicated stack trace using any symbols available on the device, plus metadata like the OS version and exception type. Apple also produces binary .ips files starting with macOS Monterey, which contain the same data in JSON format.
Why You Need Debug Symbols
Release builds strip debug information to reduce binary size and protect intellectual property. A stripped binary turns your stack trace into a wall of hexadecimal addresses:
Thread 0 Crashed:
0 MyGame.exe 0x00007ff6a3b41c2f <unknown>
1 MyGame.exe 0x00007ff6a3b287a4 <unknown>
2 MyGame.exe 0x00007ff6a3c10d88 <unknown>
3 KERNELBASE 0x00007ffd2e1a4fd0 RaiseException
This tells you almost nothing. With the matching debug symbols, the same crash becomes:
Thread 0 Crashed:
0 MyGame.exe CombatSystem::ApplyDamage(Entity&, float) + 0x4f combat.cpp:247
1 MyGame.exe CombatSystem::ProcessHitQueue() + 0x134 combat.cpp:189
2 MyGame.exe GameWorld::Tick(float) + 0x288 world.cpp:412
3 KERNELBASE RaiseException + 0x70
Now you know exactly which function crashed and on which line. This is what symbolication does: it maps raw addresses back to function names, file paths, and line numbers using the debug information you preserved at build time.
Symbol File Formats
Each platform uses a different format for storing debug symbols:
PDB (Windows). Program Database files are generated by the MSVC and Clang-CL compilers. They contain type information, function names, line numbers, and source file paths. PDB files are typically 10 to 50 times larger than the stripped executable. They must match the exact build — a PDB from a different commit or with different compiler flags will produce incorrect or no symbolication.
dSYM (Apple). Debug Symbol bundles are macOS directory packages containing DWARF debug info. Xcode generates them automatically for Release builds when "Debug Information Format" is set to "DWARF with dSYM File." Each dSYM is identified by a UUID that must match the UUID embedded in the binary.
DWARF in ELF (Linux). On Linux, debug information is stored in DWARF format inside ELF binary sections. You can either keep an unstripped copy of the binary or use objcopy to extract the debug sections into a separate file. The build-id links the stripped binary to its debug info.
How Symbolication Works Step by Step
Symbolication is a lookup process. The crash dump contains a memory address where the crash occurred. The symbolication tool finds which module was loaded at that address, calculates the offset within the module, and looks up that offset in the symbol file to find the function name and line number.
On Windows, use WinDbg or Visual Studio. Point the debugger at your symbol server and open the minidump:
# WinDbg: set symbol path and open a minidump
.sympath srv*C:\symbols*https://your-symbol-server.example.com/symbols
.reload /f
!analyze -v
The !analyze -v command automatically symbolicates the crashing thread and provides a detailed analysis including the faulting instruction, probable cause, and full stack trace.
On macOS, use the atos command to resolve individual addresses, or symbolicatecrash to process an entire .crash file:
# Symbolicate a single address using atos
atos -arch x86_64 -o MyGame.app/Contents/MacOS/MyGame -l 0x100000000 0x10004a4c2
# Symbolicate an entire crash log
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
symbolicatecrash MyGame-2026-03-18.crash MyGame.app.dSYM > symbolicated.crash
On Linux, use gdb, llvm-symbolizer, or Breakpad's minidump_stackwalk:
# Using minidump_stackwalk with Breakpad symbols
minidump_stackwalk crash.dmp /path/to/symbols/
# Using llvm-symbolizer for a single address
llvm-symbolizer --obj=MyGame 0x4a4c2
# Using gdb with an unstripped binary and core dump
gdb ./MyGame.debug core.12345 -ex "bt full" -ex "quit"
Setting Up Symbol Servers and Archives
You must store symbols for every build that players might be running. If a player crashes on version 1.2.3 and you only have symbols for 1.2.4, the crash dump is useless. Your CI/CD pipeline should archive symbols on every release build.
On Windows, Microsoft's symstore.exe adds PDB files to a structured symbol server that debuggers can query by build ID:
# Add symbols to a local symbol store after each build
symstore add /r /f "C:\build\output\*.pdb" /s "C:\SymbolServer" /t "MyGame" /v "1.2.3"
# For Breakpad-format symbols (cross-platform)
dump_syms MyGame.exe MyGame.pdb > MyGame.sym
# Move the .sym file into the symbol directory structure
# symbols/MyGame.pdb/<BUILD_ID>/MyGame.sym
For cross-platform projects, Breakpad's symbol format is a practical choice. The dump_syms tool converts PDB, dSYM, and ELF debug info into a single text-based format that minidump_stackwalk can process on any operating system.
Automating Crash Dump Collection
Waiting for players to manually send crash dumps does not scale. You need an automated pipeline. The standard approach uses Google's Crashpad library (the successor to Breakpad), which works as follows:
1. Install the exception handler. At game startup, initialize Crashpad with your server's upload URL. It registers a system-level exception handler that intercepts fatal signals (SIGSEGV, SIGABRT) and unhandled exceptions.
2. Write the minidump on crash. When a crash occurs, the handler writes a minidump to a local staging directory. This happens in a separate process to avoid corruption from the crashed process's state.
3. Upload on next launch. The next time the game starts, Crashpad checks the staging directory and uploads any pending dumps to your server. This avoids network operations during the crash itself and handles the case where the crash killed network connectivity.
Platform-Specific Considerations
Steam. Steam automatically collects minidumps for games that crash. Developers can access them through the Steamworks partner site under "Error Reports." Steam also supports uploading symbol files so that stack traces appear pre-symbolicated in the dashboard. Use the steam_appid.txt mechanism and ensure your build process uploads PDBs to Steamworks.
Consoles (Xbox, PlayStation, Switch). Each console platform provides its own crash reporting infrastructure. Xbox provides Watson-based crash reporting through Partner Center. PlayStation uses the PlayStation Partners crash dump service. Nintendo Switch crash dumps are accessible through the Nintendo Developer Portal. In all cases, you upload your debug symbols through the platform's developer portal and crashes are symbolicated server-side.
Mobile (iOS and Android). On iOS, crashes are reported through Xcode Organizer or App Store Connect — upload your dSYMs during the archive process. On Android, the Google Play Console collects native crashes (via Crashpad under the hood) and supports symbol file uploads for NDK-based games. Unity and Unreal both provide built-in crash reporting that handles symbol upload for mobile platforms.
"The crash dump you did not collect is the crash you will never fix. Automate collection from day one, not after your first wave of one-star reviews."
How Bugnet Handles This Automatically
Bugnet's SDK integrates directly with Crashpad and platform-native crash reporters. When you ship your game with the Bugnet SDK enabled, crash dumps are captured, uploaded, and symbolicated without any additional configuration. The pipeline works like this: your CI uploads symbol files to Bugnet as part of the build step, the SDK collects dumps from player devices, and Bugnet's backend matches each dump against the correct symbol file by build ID and produces a fully symbolicated stack trace. The result appears in your dashboard grouped by crash signature, so you can see exactly which function is crashing, how many players are affected, and whether your fix actually resolved the issue.
Related Issues
If you are dealing with crashes that only reproduce on specific GPU drivers, see our guide on debugging GPU driver crashes. For Unity-specific crash analysis where Il2CPP makes symbolication more complex, check out symbolicating Il2CPP crash dumps.
Archive symbols on every build. The one you skip will be the one that crashes on 10,000 machines.