Core Dumps und Segfaults mit gdb analysieren
AI generated
$
/etc
Linux · Troubleshooting · gdb · PHP
Core Dumps und Segfaults mit gdb analysieren
Vom kryptischen "Segmentation fault" zur konkreten Codezeile

"Segmentation fault (core dumped)" im Log ist für viele Teams das Ende der Diagnose statt der Anfang. Dabei liefert ein korrekt aktivierter Core Dump zusammen mit gdb und coredumpctl fast immer einen vollständigen Backtrace bis zur exakten Codezeile. Dieser Leitfaden zeigt, wie man Core Dumps unter Linux richtig konfiguriert, Backtraces liest und typische Ursachen wie fehlerhafte PHP-Extensions systematisch eingrenzt.

18 Min. Lesezeit gdb · coredumpctl · Backtrace · ulimit -c Linux · Troubleshooting · PHP-Extensions

1. Was ein Segfault und ein Core Dump wirklich sind

Ein Segfault (Segmentation Fault) tritt auf, wenn ein Prozess auf Speicher zugreift, für den er keine Berechtigung hat, etwa einen bereits freigegebenen Speicherbereich, einen Null-Pointer oder eine Adresse außerhalb seines zugewiesenen virtuellen Adressraums. Der Kernel erkennt diesen ungültigen Zugriff über die Memory Management Unit der CPU und beendet den Prozess mit dem Signal SIGSEGV. Anders als eine PHP-Exception oder ein sauber behandelter Fehler ist ein Segfault immer ein Anzeichen für einen Bug auf einer tieferen Ebene, meist in nativem C-Code, einer Erweiterung oder selten im Kernel selbst, da reines PHP normalerweise keine direkten Speicherzugriffsfehler dieser Art verursachen kann.

Ein Core Dump ist ein Abbild des kompletten Prozessspeichers zum Zeitpunkt des Absturzes, inklusive aller Register, des Stacks und des Heaps. Ohne diesen Core Dump bleibt nur die Fehlermeldung selbst, die außer dem Zeitpunkt und dem beteiligten Prozessnamen keine verwertbare Information über die Ursache liefert. Mit einem korrekt gesicherten Core Dump lässt sich hingegen exakt rekonstruieren, welche Funktion mit welchen Argumenten aktiv war, als der Speicherzugriff fehlschlug, was den entscheidenden Unterschied zwischen tagelangem Rätselraten und einer Diagnose in wenigen Minuten ausmacht.

2. Core Dumps aktivieren: ulimit, core_pattern und systemd

Die häufigste Ursache dafür, dass nach einem Segfault kein Core Dump existiert, ist ein auf 0 gesetztes ulimit -c. Viele Distributionen deaktivieren Core Dumps standardmäßig, um versehentliches Vollschreiben der Festplatte durch große Speicherabbilder zu verhindern. Für einen über systemd gestarteten Dienst wie PHP-FPM reicht das Setzen von ulimit -c unlimited in einer interaktiven Shell nicht aus, hier muss LimitCORE=infinity in der jeweiligen Unit-Datei gesetzt werden, analog zum bereits bekannten LimitNOFILE-Muster bei Dateideskriptor-Limits.

Zusätzlich bestimmt /proc/sys/kernel/core_pattern, wohin der Core Dump geschrieben wird. Auf modernen systemd-Systemen zeigt dieser Wert typischerweise auf ein Piping-Kommando an systemd-coredump, das die Dumps zentral in /var/lib/systemd/coredump/ speichert, komprimiert und mit Metadaten versieht. Ein manuell gesetzter, abweichender core_pattern-Wert, etwa ein einfacher relativer Pfad wie core, führt oft dazu, dass Dumps im aktuellen Arbeitsverzeichnis eines Dienstes landen, wo sie durch fehlende Schreibrechte gar nicht erst erzeugt werden, was fälschlich als "es gibt keine Core Dumps" fehlinterpretiert wird.


# Check current core dump size limit for the shell
ulimit -c

# Where does the kernel actually write core dumps?
cat /proc/sys/kernel/core_pattern

# Typical systemd-coredump integration (Debian/Ubuntu default)
# |/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %e

# Enable unlimited core dumps for a systemd-managed service
sudo mkdir -p /etc/systemd/system/php8.4-fpm.service.d
cat <<'EOF' | sudo tee /etc/systemd/system/php8.4-fpm.service.d/coredump.conf
[Service]
LimitCORE=infinity
EOF
sudo systemctl daemon-reload
sudo systemctl restart php8.4-fpm

3. coredumpctl: Core Dumps finden und verwalten

coredumpctl ist das zentrale Werkzeug auf systemd-Systemen, um vorhandene Core Dumps zu finden, ohne manuell im Dateisystem suchen zu müssen. coredumpctl list zeigt eine chronologische Übersicht aller gespeicherten Abstürze mit Prozessname, PID, Signal und Zeitstempel, während coredumpctl info php-fpm Details zu den letzten Abstürzen eines bestimmten Programms liefert, inklusive der Kommandozeile und teilweise bereits einem rudimentären Backtrace. Das erspart den ersten Schritt der manuellen Suche nach der richtigen Datei in /var/lib/systemd/coredump/, deren Dateinamen sonst mühsam nach PID und Zeitstempel durchsucht werden müssten.

Besonders praktisch ist die direkte Integration mit gdb über coredumpctl debug php-fpm, das automatisch den passenden Core Dump lädt und eine gdb-Sitzung mit korrekt gesetztem Binary-Pfad startet. Diese Kombination eliminiert einen häufigen Fehler bei der manuellen gdb-Analyse: das Laden eines Core Dumps gegen die falsche oder eine zwischenzeitlich aktualisierte Programmversion, was zu irreführenden oder unvollständigen Backtraces führt.


# List all recorded crashes, newest first
coredumpctl list

# Show details for the most recent crash of a specific binary
coredumpctl info php-fpm8.4

# Filter by PID if multiple crashes of the same binary exist
coredumpctl list php-fpm8.4 | tail -5

# Jump straight into a gdb session with the correct core and binary loaded
coredumpctl debug php-fpm8.4

4. Mit gdb einen Backtrace erstellen und lesen

Innerhalb einer gdb-Sitzung liefert der Befehl bt (Backtrace) die Aufrufkette vom Absturzpunkt zurück bis zum Programmstart, wobei jede Zeile einen sogenannten Stack Frame mit Funktionsname, Argumenten und, bei vorhandenen Debug-Symbolen, Dateiname sowie Zeilennummer zeigt. Der oberste Frame (#0) zeigt exakt die Funktion, in der der ungültige Speicherzugriff stattfand, während die darunterliegenden Frames den Aufrufkontext zeigen, also welche übergeordnete Funktion diesen Codepfad überhaupt erreicht hat. Für tiefere Analysen liefert bt full zusätzlich alle lokalen Variablen jedes Frames, was oft den entscheidenden Hinweis gibt, etwa einen erkennbar ungültigen Pointer-Wert wie 0x0 oder eine offensichtlich falsche Array-Größe.

Der Befehl info registers zeigt den Zustand aller CPU-Register zum Absturzzeitpunkt, was besonders bei Analysen auf Assembler-Ebene hilfreich ist, wenn der Fehler in einer Bibliotheksfunktion ohne verfügbaren Quellcode auftritt. Mit frame N wechselt man gezielt zu einem bestimmten Stack Frame, um dort mit print variable_name den Wert einer bestimmten Variable zum Absturzzeitpunkt zu inspizieren. Diese Kombination aus Backtrace, lokalen Variablen und Register-Zustand deckt die überwiegende Mehrheit aller Absturzursachen ab, ohne dass der Fehler erst reproduziert werden muss.


# Start gdb against a binary and its core dump
gdb /usr/sbin/php-fpm8.4 /var/lib/systemd/coredump/core.php-fpm8.4.0.abc123.12345.1234567890000.zst

# Inside the gdb prompt:
(gdb) bt
#0  0x00007f8a1c2b3456 in zend_hash_find () from /usr/lib/php/8.4/extensions/opcache.so
#1  0x00007f8a1c2a1234 in zend_execute_ex () from /usr/lib/x86_64-linux-gnu/libphp8.4.so
#2  0x00007f8a1c1a5678 in execute_ex () from /usr/lib/x86_64-linux-gnu/libphp8.4.so
#3  0x0000560a1b2c3456 in main ()

(gdb) bt full        # backtrace including all local variables per frame
(gdb) frame 1         # switch to a specific stack frame
(gdb) print *some_ptr  # inspect the dereferenced value of a suspect pointer
(gdb) info registers   # CPU register state at the moment of the crash

5. Debug-Symbole: Warum ein Backtrace ohne sie wertlos ist

Ein Backtrace ohne Debug-Symbole zeigt nur Speicheradressen und, bestenfalls, den Namen der Bibliothek, in der sich diese Adresse befindet, aber weder Funktionsnamen noch Zeilennummern. Auf Debian-basierten Systemen liefert das dbgsym-Repository die passenden Debug-Symbol-Pakete, erkennbar am Suffix -dbgsym, etwa php8.4-fpm-dbgsym. Auf RHEL-basierten Systemen übernimmt debuginfo-install dieselbe Aufgabe. Ohne diese Pakete bleibt ein Backtrace im schlimmsten Fall auf reine Hexadezimaladressen reduziert, aus denen sich ohne aufwendige manuelle Disassemblierung keine verwertbare Aussage über die Ursache ableiten lässt.

Ein häufiger Stolperstein: Debug-Symbole müssen exakt zur installierten Binary-Version passen. Ein Update von PHP oder einer Erweiterung ohne passendes Update der Debug-Symbol-Pakete führt zu einem Backtrace, der zwar Funktionsnamen zeigt, aber falsche oder gar keine Zeilennummern liefert, weil die Adressen zwischen den Versionen leicht verschoben sind. Wer regelmäßig Core Dumps analysiert, sollte deshalb Debug-Symbol-Pakete in dieselbe Update-Pipeline wie die eigentlichen Binaries aufnehmen, statt sie erst im Nachhinein bei Bedarf nachzuinstallieren.


# Debian/Ubuntu: enable the debug symbol repository once
echo "deb http://deb.debian.org/debian-debug bookworm-debug main" | \
  sudo tee /etc/apt/sources.list.d/debug.list
sudo apt-get update

# Install debug symbols matching the exact installed package version
sudo apt-get install php8.4-fpm-dbgsym

# RHEL/CentOS/Alma equivalent
sudo debuginfo-install php-fpm

# Verify gdb now resolves symbols instead of showing raw addresses
gdb -batch -ex "bt" /usr/sbin/php-fpm8.4 core.dump

6. Segfaults in PHP-Extensions systematisch eingrenzen

In PHP-Umgebungen wie Magento sind fehlerhafte C-Erweiterungen die mit Abstand häufigste Ursache für Segfaults, weil PHP selbst als interpretierte Sprache Speicherzugriffe absichert, native Extensions diese Absicherung aber umgehen können. Ein Backtrace, der eine Funktion innerhalb einer .so-Datei wie opcache.so, redis.so oder einer Xdebug-Bibliothek als obersten Frame zeigt, deutet direkt auf die verantwortliche Erweiterung hin. Die Kombination aus PHP-Version, Extension-Version und Betriebssystem-Architektur ist dabei entscheidend: Viele solcher Segfaults sind bekannte, bereits gemeldete Kompatibilitätsprobleme zwischen einer bestimmten PHP-Minor-Version und einer Extension, die in einem älteren Release-Zyklus entwickelt wurde.

Ein systematischer Ansatz zur Eingrenzung ist das schrittweise Deaktivieren einzelner Extensions über php.ini, kombiniert mit der Beobachtung, ob der Segfault reproduzierbar verschwindet. Bei OPcache-bezogenen Abstürzen hilft zusätzlich das Deaktivieren von opcache.jit, da der PHP-JIT-Compiler in frühen 8.x-Versionen mehrfach an Randfällen scheiterte, die klassische, interpretierte Ausführung aber stabil blieb. Diese gezielte Isolation nach Extension ist oft schneller als die vollständige gdb-Analyse und sollte parallel zur Backtrace-Untersuchung laufen.


; Systematic extension isolation — disable one at a time and observe
; /etc/php/8.4/fpm/conf.d/99-debug-isolation.ini
; extension=redis.so       ; commented out during isolation testing
; zend_extension=xdebug.so ; commented out during isolation testing

; If OPcache/JIT is suspected, disable JIT while keeping the cache itself
opcache.jit=disable
opcache.jit_buffer_size=0

7. Core Dumps in Produktivumgebungen sicher handhaben

Core Dumps aktiv zu lassen bringt zwei praktische Risiken mit sich, die vor dem produktiven Einsatz bedacht werden müssen. Erstens können Core Dumps sensible Daten enthalten, etwa Datenbank-Passwörter oder Session-Tokens, die zum Absturzzeitpunkt im Prozessspeicher lagen, weshalb die Zugriffsrechte auf /var/lib/systemd/coredump/ restriktiv gehalten werden sollten. Zweitens kann ein Dienst, der wiederholt und in kurzen Abständen abstürzt, durch die Größe der Core Dumps selbst zu einem vollen Datenträger führen, besonders bei Anwendungen mit hohem Speicherverbrauch, deren Core Dumps entsprechend groß ausfallen.

systemd-coredump begrenzt Größe und Anzahl gespeicherter Dumps über Storage=, Compress= und MaxUse= in /etc/systemd/coredump.conf, was beide Risiken pragmatisch adressiert: Kompression reduziert den Speicherbedarf erheblich, während MaxUse verhindert, dass eine Absturzserie den verfügbaren Speicherplatz komplett aufbraucht. Für produktive Magento-Server empfiehlt sich, Core Dumps standardmäßig aktiviert zu lassen, aber mit klaren Obergrenzen, statt sie präventiv komplett zu deaktivieren und beim nächsten Vorfall ohne jede Diagnosemöglichkeit dazustehen.


# /etc/systemd/coredump.conf
[Coredump]
Storage=external
Compress=yes
ProcessSizeMax=2G
ExternalSizeMax=2G
MaxUse=10G
KeepFree=5G

8. Reproduktion erzwingen statt auf den nächsten Absturz zu warten

Wenn ein Segfault zu selten auftritt, um auf einen weiteren Vorfall zu warten, hilft es, den vermuteten Auslöser aus dem Backtrace gezielt zu reproduzieren. Wurde etwa eine bestimmte Redis-Operation als Auslöser identifiziert, lässt sich ein minimales PHP-Skript schreiben, das genau diese Operation isoliert und wiederholt unter Last ausführt, im Idealfall unter gdb --args php script.php, sodass ein erneuter Absturz sofort in einer laufenden gdb-Sitzung landet, statt erst nachträglich einen Core Dump analysieren zu müssen.

Für schwer reproduzierbare Fälle mit Verdacht auf Race Conditions zwischen Threads oder Prozessen liefert gdb mit catch signal SIGSEGV und automatisiertem bt bei jedem Auftreten eine Möglichkeit, mehrere Abstürze über Zeit zu sammeln und auf Gemeinsamkeiten im Backtrace zu prüfen. Stimmen mehrere unabhängige Abstürze im obersten Frame überein, ist das ein starker Beweis dafür, dass tatsächlich ein reproduzierbarer Bug vorliegt und nicht etwa Hardware-Fehler oder kosmische Strahlung, wie in seltenen Fällen fälschlich vermutet wird.

9. Absturzanalyse-Werkzeuge im Vergleich

Je nach Situation und verfügbaren Vorbereitungen eignen sich unterschiedliche Werkzeuge zur Analyse eines Core Dumps. Die folgende Übersicht ordnet die vorgestellten Ansätze nach Voraussetzung und Aussagekraft.

Werkzeug Voraussetzung Aussagekraft Typischer Einsatz
coredumpctl list systemd-coredump aktiv Übersicht, kein Detail Erste Sichtung nach Vorfall
gdb bt (ohne Symbole) Core Dump vorhanden Gering Nur grobe Bibliothekszuordnung
gdb bt full (mit Symbolen) Debug-Symbole installiert Hoch Exakte Codezeile und Variablen
Gezielte Reproduktion Vermuteter Auslöser bekannt Sehr hoch Bestätigung der Root Cause

In der Praxis beginnt die Untersuchung eines Segfaults immer mit coredumpctl list zur Bestätigung, dass überhaupt ein verwertbarer Dump existiert, gefolgt von der Installation passender Debug-Symbole, ohne die jeder weitere Schritt an Aussagekraft verliert. Erst danach liefert gdb bt full die entscheidenden Details, und eine gezielte Reproduktion bestätigt die vermutete Ursache, bevor ein Fix als produktionsreif gilt.

Mironsoft

Linux-Absturzanalyse und Server-Troubleshooting für Magento- und PHP-Infrastruktur

Segfaults ohne verwertbaren Backtrace?

Wir konfigurieren Core Dumps korrekt, installieren passende Debug-Symbole und analysieren mit gdb, welche Extension oder Codestelle für den Absturz verantwortlich ist, statt bei jedem Vorfall erneut im Dunkeln zu tappen.

Core-Dump-Setup

systemd-coredump, ulimit und Debug-Symbole produktionstauglich konfigurieren

Backtrace-Analyse

gdb-gestützte Eingrenzung bis zur verantwortlichen Extension oder Codezeile

Reproduktion & Fix

Gezielte Reproduktion des Auslösers zur Bestätigung vor dem Produktions-Fix

10. Zusammenfassung

Ein Segfault ist kein Rätsel ohne Lösung, sondern ein technisch präzise analysierbares Ereignis, sofern ein Core Dump korrekt aktiviert und gesichert wurde. Die Grundlage bilden ulimit -c beziehungsweise LimitCORE in der systemd-Unit sowie ein sinnvoll konfigurierter core_pattern, meist über systemd-coredump. coredumpctl vereinfacht das Auffinden vorhandener Dumps erheblich, während gdb mit installierten Debug-Symbolen einen vollständigen Backtrace bis zur konkreten Codezeile liefert.

In PHP-Umgebungen sind fehlerhafte native Extensions die häufigste Ursache für Segfaults, erkennbar am obersten Frame im Backtrace innerhalb einer .so-Datei. Systematisches Deaktivieren einzelner Extensions und gezielte Reproduktion des vermuteten Auslösers bestätigen die Ursache, bevor ein Fix als abgeschlossen gilt. Wer Core Dumps standardmäßig aktiviert lässt, aber Größe und Anzahl über systemd-coredump begrenzt, hat bei jedem zukünftigen Absturz sofort die nötigen Daten für eine schnelle Diagnose zur Hand.

Core Dumps und Segfaults analysieren: Das Wichtigste auf einen Blick

Aktivierung

LimitCORE=infinity in der systemd-Unit, passender core_pattern über systemd-coredump.

Auffinden

coredumpctl list und coredumpctl debug laden automatisch den passenden Dump samt Binary.

Auswertung

gdb bt full mit installierten Debug-Symbolen liefert Funktionsnamen, Zeilennummern und lokale Variablen.

Häufigste Ursache

Fehlerhafte native PHP-Extensions, erkennbar am obersten Backtrace-Frame in einer .so-Datei.

11. FAQ: Core Dumps und Segfaults mit gdb analysieren

1Warum entsteht kein Core Dump?
Meist ulimit -c auf 0. Bei systemd-Diensten zusätzlich LimitCORE=infinity in der Unit setzen.
2Wohin schreibt der Kernel Dumps?
Über core_pattern an systemd-coredump, gespeichert in /var/lib/systemd/coredump/.
3Dumps finden ohne manuelle Suche?
coredumpctl list für die Übersicht, coredumpctl debug für den direkten gdb-Einstieg.
4Nur Hexadressen im Backtrace?
Fehlende Debug-Symbole. dbgsym-Pakete (Debian) oder debuginfo-install (RHEL) beheben das.
5Lokale Variablen zum Absturz anzeigen?
bt full in gdb zeigt alle lokalen Variablen jedes Stack Frames.
6Welche Extension verursacht den Fehler?
Der oberste Frame zeigt meist die .so-Datei der verantwortlichen Erweiterung direkt an.
7OPcache JIT bei Verdacht deaktivieren?
Als Diagnoseschritt sinnvoll, der Opcode-Cache selbst bleibt dabei erhalten.
8Sind Core Dumps ein Sicherheitsrisiko?
Ja, sie können Passwörter oder Tokens enthalten. Zugriffsrechte restriktiv halten.
9Festplatte vor Dumps schützen?
MaxUse und Compress in coredump.conf begrenzen Größe und Anzahl automatisch.
10Seltenen Segfault gezielt reproduzieren?
Auslöser isolieren und unter gdb --args php script.php wiederholt ausführen.