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
- Identify the tool implementation and platform before running anything. Run
dwarfdump --versionfirst: a baredwarfdumpmay 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.ofiles untildsymutilcollects it into a.dSYMbundle; point the tool at the dSYM or object files, not the executable.pyelftoolsis ELF-only, so for Mach-O scripted work stay with the LLVM tools. Done when: the tool implementation and platform are identified. - Prefer
dwarfdumpoverreadelffor DWARF-specific work. Usereadelf --debug-dump=<section>(with--dwarf-depth=<n>/--dwarf-start=<n>to limit depth or start offset) only for general ELF structure or whendwarfdumpis unavailable. Done when: the appropriate tool is selected for the query type. - 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,--regexavailable) 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. - For an attribute or type query (e.g. all parameters of type
float *), dump and filter:grep -B 1 <pattern>pulls in the header line carrying each DIE's offset, then print each DIE at its offset with--debug-info=<offset> --show-children(--lookuptakes 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-formwhen attribute encoding details matter. Done when: every matching DIE is printed with its offset and the requested children/parents/forms. - For a multi-attribute or structural query where grep pipelines turn brittle, write a Python script using
pyelftoolsonly if the user has explicitly requested a script or parser; otherwise, continue dumping and filtering and report the findings without creating code. Done when: the structural query is resolved, either with apyelftoolsscript (if requested) or a terminal report. - 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--quietfor exit-code-only checks. Runllvm-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--verifyexit code and error detail are reported, and--statisticsJSON is produced when quality comparison was requested. - 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 inDW_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 asDW_AT_MIPS_linkage_name. Done when: the DWARF version is confirmed from the build system or producer string. - 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.cppas 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. - For an explicitly requested parser, prefer an existing library over parsing by hand:
libdwarf(C/C++, low-level, used to implementdwarfdump),pyelftools(Python, also parses ELF),gimlipaired withobject(Rust, to load container files),debug/dwarf(Go standard library), orLibObjectFile(.NET, also handles ELF/PE). Default to Python withpyelftoolsfor one-off scripts unless the task dictates otherwise. Done when: the parser is implemented using a named library. - 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 throughDW_AT_abstract_origin(inlined instances) andDW_AT_specification(out-of-line definitions) before concluding data is absent; and type chains walkDW_AT_typelinks 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.