Core dump inspection (inspector:coredump)

May 2, 2026 · View on GitHub

inspector:coredump runs the same memory analysis as inspector:memory against an ELF core file instead of a live process. It's the post-mortem counterpart to the online analyzer, and a useful fallback when live dumping cannot be used.

When to use

  • The process has already died: you have a core file (from the kernel core_pattern, systemd-coredump, Docker runtime dump, cloud platform artifact, CI sidecar, etc.) but no live PID to attach to.
  • Live dump fails: if inspector:memory / inspector:memory:dump cannot attach (ptrace denied, sandboxed container, unusual glibc / musl layout, ZTS TLS scan failing on an exotic target), taking a core dump with a tool you already have (gcore, kill -SIGSEGV, kernel-level dump) and feeding it to inspector:coredump is a reliable workaround — it reads ELF notes and memory pages out of the core file instead of going through /proc/<pid>/mem.
  • Reproducing an incident from an archived dump: core files are portable. A dump taken in production can be analyzed later on a dev machine, as long as the matching PHP binary and shared libraries can be provided (see --dependency-root).

For live analysis of a still-running process, use inspector:memory or inspector:memory:dump. For reuse of an analyzer output across tools, use the captured-snapshot pipeline described in memory-report.md and rmem-explore-and-serve.md.

Quick start

# Take a non-destructive core dump of a live process
$ sudo gcore -o /tmp/myapp 12345
# → /tmp/myapp.12345

# Run the memory analyzer against the core file (.rmem is the fastest
# format and is what every analyser reads natively)
$ php ./reli inspector:coredump /tmp/myapp.12345 --pid 12345 \
    -f rmem -o snapshot.rmem

# Feed the output into the normal analysis pipeline
$ php ./reli inspector:memory:report snapshot.rmem
$ php ./reli rmem:explore snapshot.rmem

-f sqlite3 is also supported if you want to query the same snapshot with SQL tools — inspector:memory:report / inspector:memory:compare accept either format. rmem:explore, rmem:query, rmem:serve, and rmem:mcp read .rmem only.

The output of inspector:coredump uses the same MemoryProfilerSettings as inspector:memory, so every output format (json, sqlite3, rmem, mysql, postgresql, report, report-json) is supported. Which downstream tool you can feed depends on the format:

  • inspector:memory:report and inspector:memory:compare accept .rmem (binary) or SQLite (.db / .sqlite).
  • rmem:explore, rmem:query, rmem:serve, and rmem:mcp require .rmem.

Arguments and options

Required

Argument / optionDescription
<core-file>Path to the ELF core file to read.
--pid, -pThe PID the target process had at the time of the dump. This is used to resolve the binary / shared-library layout that matches the core.

Core-file specific

OptionDescription
--dependency-root, -rPath prefix applied to every binary / shared-library path referenced by the core. Use this when the dump was taken inside a container or chroot and the PHP binary / libs are not at the same absolute path on the analysis host. For example, -r /proc/<pid>/root when the target container is still alive on the same host, or -r /var/lib/docker/.../merged / a locally extracted image root.
--memory-limitSet the analyzer's own memory_limit (e.g. 2G). Core files can be large; the analyzer holds data structures proportional to the live heap.
--no-cacheDisable the binary analysis cache (~/.cache/reli/binary-analysis/). Useful if you are analyzing a dump whose binary differs from one the cache already knows about.

Target PHP options (same as other inspector commands)

--php-version, --php-regex, --libpthread-regex, --zts-globals-regex, --php-path, --libpthread-path behave the same way as in inspector:trace / inspector:memory. Auto-detection usually works; override only if the binary layout inside the core differs from what reli can infer.

Output options (same as inspector:memory)

--output-format / -f, --output / -o, --pretty-print, --db-host, --db-port, --db-name, --db-user, --db-password, --memory-limit-error-file, --memory-limit-error-line, --memory-limit-error-max-depth — see memory-profiler.md for full semantics.

Taking a core dump

Any tool that produces a standard ELF core will work. A few common options:

  • gcore (from gdb) — non-destructive, the target keeps running:

    sudo gcore -o /tmp/myapp <pid>
    
  • Signal-based — for a crash-repro workflow:

    kill -SIGSEGV <pid>        # process dies, kernel writes a core
    

    Make sure ulimit -c and /proc/sys/kernel/core_pattern are set so that the core actually lands somewhere you can read.

  • systemd-coredump — on systems that route cores to the journal:

    coredumpctl dump <pid-or-unit> --output=/tmp/core
    
  • Containerized / production artifact — many orchestrators capture a core on OOM-kill or segfault automatically; consult your platform.

Include enough memory in the dump

The analyzer needs to read back PHP heap chunks, the VM stack, and several read-only segments of the binary for symbol resolution. The kernel's per-process coredump_filter controls which VMAs end up in the core. For live captures via gcore, set it to 0x7f to include private + shared + file-backed + ELF-header pages before dumping:

echo 0x7f | sudo tee /proc/<pid>/coredump_filter
sudo gcore -o /tmp/myapp <pid>

See man 5 core for the full bitmask.

Limitations

  • ZTS PHP 8.2+ stripped binaries: _tsrm_ls_cache isn't in .dynsym, so reli falls back to a brute-force TLS scan over the thread's TLS block. Post-mortem this needs the saved core to contain the TLS pages of a thread that has actually served a request — an idle worker whose slot is still zero will not validate. The integration test in CoreDumpReaderIntegrationTest.php uses an auto_prepend_file PID-writer that doesn't keep the worker on a request, so the ZTS variants of that suite stay skipped; in production, take the core while the target is mid-request (e.g. a usleep-tail script under load) and ZTS post-mortem succeeds.
  • Dependencies must be available: the analyzer resolves symbols from the PHP binary and linked shared objects. If the analysis host doesn't have the same files at the paths the core references, use --dependency-root to point at a directory that does (e.g. a locally extracted container root filesystem).
  • Core must contain the relevant memory pages. A dump taken with a restrictive coredump_filter may be missing pages the analyzer needs; it will report an error or produce a partial result.

See also

  • inspector:memory — the live-process equivalent. Output format and downstream pipeline are shared.
  • inspector:memory:dump — reli's own compact .rdump dump format for offline analysis; prefer it over gcore + inspector:coredump when the target is still alive and reli can attach.
  • inspector:memory:report — generate an automated analysis report from the output.
  • rmem:explore — interactive TUI over the .rmem output.
  • gcore comparison — internals note on trade-offs between reli's native dump and ELF core files.