dwarf-expert · git:20260902.1fe14a3 · 2026-09-02 · sha256 1fc6ce80af2df126

dwarf-expert git:20260902.1fe14a3A

Immutable. This exact content is served forever at /api/v1/blob/1fc6ce80af2df126.

---
name: dwarf-expert
description: 'Use when inspecting, searching, verifying, or parsing DWARF debug info: DIEs, DW_TAG_/DW_AT_ entries, .debug_* sections, line tables, or llvm-dwarfdump/readelf output. Returns the requested query, verification, explanation, or parser with tool and platform identified.'
---

# DWARF expert

## Contract

| Field | Bound contract |
|---|---|
| Trigger | The user asks to inspect, search, verify, explain, or programmatically parse DWARF debug information, DIEs, DW_TAG_/DW_AT_ entries, .debug_* sections, line tables, or llvm-dwarfdump/readelf output. |
| Authority | Reversible local: inspect binaries and print query or integrity results; write only a verifier summary via `--verify-json` or code the user explicitly requests as a parser. Input binaries, object files, and dSYM bundles remain unchanged. |
| Side effect | Default operations read binaries and print to the terminal; `--verify-json` may write a machine-readable verifier summary, and an explicit parser-development request may create code. No mutation of input binaries, object files, or dSYM bundles. |
| Done | The requested DIE/address/name query, integrity verification, standard explanation, or parser implementation is complete; tool implementation and platform/container format are identified; searches escalate from accelerator lookup to exhaustive search to structured parsing; optional attributes, abstract-origin/specification indirection, and wrapped type chains are handled; and any written parser or JSON output matches the requested surface. |

## Inputs

- A binary, object file, or dSYM bundle to inspect (required for query, search, and verification work; not required for pure standard-explanation questions).
- The query surface: a DIE name or address to look up, an attribute or type predicate to filter, a structural query, an integrity-verification request, a DWARF-standard question, or a parser-development request.
- Optional: target DWARF version, compiler, or optimization level when relevant to verification or quality comparison.

## Procedure

1. Identify the tool implementation and platform before running anything. Run `dwarfdump --version` first: a bare `dwarfdump` may be libdwarf's or LLVM's, and the options below are LLVM's. On macOS, linked Mach-O executables do not carry DWARF; it stays in `.o` files until `dsymutil` collects it into a `.dSYM` bundle; point the tool at the dSYM or object files, not the executable. `pyelftools` is ELF-only, so for Mach-O scripted work stay with the LLVM tools. Done when: the tool implementation and platform are identified.
2. Prefer `dwarfdump` over `readelf` for DWARF-specific work. Use `readelf --debug-dump=<section>` (with `--dwarf-depth=<n>` / `--dwarf-start=<n>` to limit depth or start offset) only for general ELF structure or when `dwarfdump` is unavailable. Done when: the appropriate tool is selected for the query type.
3. For a name or address match, escalate: try `--find=<name>` (accelerator-table exact lookup, fast but not exhaustive) first, fall back to `--name=<pattern>` (`--ignore-case`, `--regex` available) for exhaustive DIE-name search, and use `--lookup=<address>` to find the DIE covering a program address. Done when: the name or address is found or the escalation ladder is exhausted with a not-found report.
4. For an attribute or type query (e.g. all parameters of type `float *`), dump and filter: `grep -B` pulls in the header line carrying each DIE's offset, then print each DIE at its offset with `--debug-info=<offset> --show-children` (`--lookup` takes a program address, not a DIE offset). Use `--show-children` / `--show-parents` (with `--recurse-depth` / `--parent-recurse-depth`) to include child or parent DIEs, and `--show-form` when attribute encoding details matter. Done when: every matching DIE is printed with its offset and the requested children/parents/forms.
5. For a multi-attribute or structural query where grep pipelines turn brittle, write a Python script using `pyelftools` instead of continuing to grep. Done when: the structural query is resolved with a `pyelftools` script.
6. For integrity verification, run `llvm-dwarfdump --verify <binary>` for structural checks (unit chains, DIE relationships, address ranges); control detail with `--error-display=<quiet|summary|details|full>`, write a machine-readable summary with `--verify-json=<path>`, and use `--quiet` for exit-code-only checks. Run `llvm-dwarfdump --statistics <binary>` for debug-info quality metrics as JSON to compare across compiler versions or optimization levels. Verify after producing DWARF (compilers, binary rewriters), when a debugger misbehaves on a binary, and when developing DWARF tooling against known-good files. Done when: the `--verify` exit code and error detail are reported, and `--statistics` JSON is produced when quality comparison was requested.
7. When a current-generation compiler emitted an old DWARF version, the build explicitly passed `-gdwarf-N`; modern gcc and clang default to v4/v5, so check the build system rather than assuming a toolchain default. GCC embeds its flags in `DW_AT_producer` (the pin is often readable there); clang's producer string carries no flags. Old versions read the same way apart from surface forms: in v2 output, member offsets appear as location expressions (`DW_OP_plus_uconst`) and linkage names as `DW_AT_MIPS_linkage_name`. Done when: the DWARF version is confirmed from the build system or producer string.
8. For a DWARF-standard question where precision matters, look the detail up instead of answering from memory, escalating through authoritative sources: dwarfstd.org (the official specification; web-search specific sections), LLVM's `llvm/lib/DebugInfo/DWARF/` (`DWARFDie.cpp`, `DWARFUnit.cpp`, `DWARFDebugLine.cpp`, `DWARFVerifier.cpp` as a reference implementation), and libdwarf at github.com/davea42/libdwarf-code (the reference C implementation). Done when: the question is answered with a citation naming which source answered it.
9. For an explicitly requested parser, prefer an existing library over parsing by hand: `libdwarf` (C/C++, low-level, used to implement `dwarfdump`), `pyelftools` (Python, also parses ELF), `gimli` paired with `object` (Rust, to load container files), `debug/dwarf` (Go standard library), or `LibObjectFile` (.NET, also handles ELF/PE). Default to Python with `pyelftools` for one-off scripts unless the task dictates otherwise. Done when: the parser is implemented using a named library.
10. In every search, verification, and parser, handle the DWARF-specific pitfalls: attributes are optional (a DIE may omit `DW_AT_name`, `DW_AT_type`, ranges); attribute indirection resolves through `DW_AT_abstract_origin` (inlined instances) and `DW_AT_specification` (out-of-line definitions) before concluding data is absent; and type chains walk `DW_AT_type` links through qualifiers and modifiers (`DW_TAG_const_type`, `DW_TAG_pointer_type`, ...) to reach the base type. Done when: optional attributes, abstract-origin/specification indirection, and wrapped type chains are handled in every search, verification, and parser.

## Failure and recovery
If the tool implementation is ambiguous and `dwarfdump --version` does not identify LLVM's `llvm-dwarfdump`, do not assume LLVM option semantics; fall back to `readelf --debug-dump` or locate `llvm-dwarfdump` explicitly, and stop and report rather than running flags the tool does not support. If `dwarfdump` finds no DWARF on a linked Mach-O executable, locate the `.dSYM` bundle or `.o` files and re-run against those; do not conclude the binary lacks debug info. If `--find` misses, accelerator-table lookup is fast but not exhaustive; a miss escalates to `--name`, then to dump-and-filter, then to a `pyelftools` script; never report "not found" from `--find` alone. Before reporting an attribute absent, resolve `DW_AT_abstract_origin` / `DW_AT_specification` indirection and walk the `DW_AT_type` chain; the data may live on a referenced DIE. On verification failure, report the `--verify` exit code and the `--error-display` / `--verify-json` detail verbatim; do not summarize a structural failure as "looks fine," and if a verifier summary file was written, name its path. A query that resolves some DIEs but not others returns the resolved set with each unresolved item named and the reason; it never silently drops failures. Input binaries, object files, and dSYM bundles are never modified: the only writes permitted are a `--verify-json` summary path or parser code the user explicitly requested, and if no such write was requested, nothing is written.

## Output
A terminal query result (matched DIE tree, address-covering DIE, or filtered attribute set with offsets and tool/platform identified), an integrity report (verify exit code, error detail, statistics JSON when requested), a standard explanation grounded in an authoritative source, or a parser implementation using a named library.