Analyze a systemd-coredump Core Dump with eu-unstrip and gdb
Use eu-unstrip and systemd-coredump to analyze a Linux core dump: coredumpctl list/info/gdb, extract the core, list module build-ids with eu-unstrip, then debug in gdb.
- #linux
- #coredump
- #debugging
- #troubleshooting
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
What systemd-coredump Does
On modern Linux distributions (Fedora, RHEL 8+, Ubuntu with systemd-coredump installed, Arch, openSUSE), the kernel’s core_pattern is wired to hand crashing processes to systemd-coredump instead of writing a core file in the working directory. When a process dies from a signal like SIGSEGV or SIGABRT, systemd captures the core, compresses it, records rich metadata in the journal, and stores the payload under /var/lib/systemd/coredump.
That is convenient for retention, but it changes the workflow. You no longer gdb ./myapp core. You go through coredumpctl, and when symbols are missing you lean on elfutils tools like eu-unstrip to figure out exactly which shared objects and build-ids were mapped into the crashed process.
Confirm the Core Pattern
Check that systemd-coredump is actually the handler:
cat /proc/sys/kernel/core_pattern
|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h
The leading pipe (|) means the kernel streams the core to that binary. If you instead see a plain path like core.%p, dumps land as files and systemd-coredump is not in play.
Listing and Inspecting Dumps
coredumpctl is the front door. List everything the system has captured:
coredumpctl list
TIME PID UID GID SIG COREFILE EXE
Wed 2026-07-15 09:14:02 UTC 4821 1000 1000 SIGSEGV present /usr/bin/myapp
Get the metadata for a specific dump, either by PID or by executable name:
coredumpctl info 4821
The info output shows the signal, the command line, the timestamp, the storage location, and a stack trace if debug symbols are already resolvable. When symbols are absent you will see a lot of ?? frames, which is the cue to identify the exact binaries and their build-ids.
Where the Core Is Stored
systemd-coredump keeps two things: structured metadata in the journal, and the compressed core payload on disk.
ls -lh /var/lib/systemd/coredump/
-rw-r-----. 1 root root 512K core.myapp.1000.<hash>.4821.<ts>.zst
Note the .zst (or .lz4) extension. You cannot feed a compressed core to gdb directly, which is why you extract it first. Retention and size limits live in /etc/systemd/coredump.conf (MaxUse, ProcessSizeMax, Storage).
Extracting the Raw Core
Pull an uncompressed core out to a normal file so the elfutils and gdb tooling can read it:
coredumpctl dump 4821 --output=/tmp/myapp.core
You now have a plain ELF core dump at /tmp/myapp.core. Everything below operates on that file.
Listing Loaded Modules with eu-unstrip
Before you chase symbols, you need the ground truth of what was actually mapped into the process and the exact build-id of each object. That is what eu-unstrip -n gives you:
eu-unstrip -n --core=/tmp/myapp.core
0x400000+0x21000 a3f1c9...b27 0x0 /usr/bin/myapp /usr/bin/myapp
0x7f2a...+0x1f0000 5d8e2f...a10 . /lib64/libc.so.6 libc.so.6
0x7f2b...+0x9000 9c14ab...ee0 . /lib64/libpthread.so.0 libpthread.so.0
Each row is: load address range, the 40-hex build-id, the debuginfo path (. means none separated, - means missing), the runtime file, and the module name. This is invaluable: the build-id is what uniquely ties a stripped binary to its matching debuginfo. If a build-id here does not match the debuginfo you have installed, gdb will silently give you wrong or missing symbols.
Step-by-Step Resolution
- Verify the handler and locate the dump:
cat /proc/sys/kernel/core_pattern
coredumpctl list
- Read the metadata and note the signal and executable:
coredumpctl info 4821
- Extract the raw core for offline analysis:
coredumpctl dump 4821 --output=/tmp/myapp.core
- Enumerate the mapped modules and their build-ids so you know exactly what to symbolize:
eu-unstrip -n --core=/tmp/myapp.core
- Match debuginfo to each build-id. On Fedora/RHEL, install symbols for the crashing package and its libraries:
sudo dnf debuginfo-install myapp glibc
- Get a fast backtrace without a full debugger using
eu-stack, which resolves frames against the same build-ids:
eu-stack --core=/tmp/myapp.core
- Open the dump in
gdbfor interactive analysis. The simplest path is to letcoredumpctllaunch gdb with the right executable already attached:
coredumpctl gdb 4821
Or point gdb at the extracted core yourself:
gdb /usr/bin/myapp /tmp/myapp.core
- Inside gdb, confirm the frames now resolve to real function names and file:line locations:
(gdb) bt
#0 0x000055... in parse_config (path=0x0) at config.c:142
#1 0x000055... in main (argc=2, argv=...) at main.c:38
If frames still show ??, the build-id from eu-unstrip did not match the installed debuginfo. See the companion guide on missing debuginfo. Automating this triage across many hosts is a good fit for a repeatable prompt from our DevOps AI prompt library.
Prevention and Best Practices
- Keep
systemd-coredumpinstalled on production Linux hosts so crashes are captured with metadata instead of lost. - Raise
ProcessSizeMaxincoredump.confif large processes are being truncated, and watchMaxUseso/var/lib/systemd/coredumpdoes not fill the disk. - Record the build-id (
eu-unstrip -n) alongside any bug report; it lets anyone fetch the exact matching debuginfo later. - Prefer
coredumpctl gdbover manual extraction when possible, since it selects the correct executable automatically. - Ship debuginfo (or configure debuginfod) on at least one triage host so you can symbolize without rebuilding.
Frequently Asked Questions
Where does systemd-coredump store core dumps? The compressed payload lives under /var/lib/systemd/coredump/ (usually .zst or .lz4), and structured metadata is written to the systemd journal, queryable with coredumpctl.
How do I get an uncompressed core file for gdb? Run coredumpctl dump <PID> --output=/tmp/app.core. systemd stores dumps compressed, so you must extract before gdb or eu-stack can read them.
What does eu-unstrip -n —core do? It prints every module mapped into the crashed process with its load address and 40-character build-id, so you can match each stripped object to its exact debuginfo before symbolizing.
Do I have to use gdb, or is there something faster? eu-stack --core=<core> from elfutils produces a symbolized backtrace quickly without an interactive session, which is ideal for scripted triage. For more low-level debugging walkthroughs, see the Linux admin guides.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.