Skip to main content
Provides expertise for analyzing DWARF debug files and understanding the DWARF debug format/standard (v3-v5). Helps you work with DWARF information in compiled binaries. Author: Evan Hellman

Installation

/plugin install trailofbits/skills/plugins/dwarf-expert

When to Use

Use this plugin when you need to:
  • Understand or parse DWARF debug information from compiled binaries
  • Answer questions about the DWARF standard (v3, v4, v5)
  • Write or review code that interacts with DWARF data
  • Use dwarfdump or readelf to extract debug information
  • Verify DWARF data integrity using llvm-dwarfdump --verify
  • Work with DWARF parsing libraries (libdwarf, pyelftools, gimli, etc.)

When NOT to Use

This plugin is NOT suitable for:
  • DWARF v1/v2 Analysis - Expertise limited to versions 3, 4, and 5
  • General ELF Parsing - Use standard ELF tools if DWARF data isn’t needed
  • Executable Debugging - Use dedicated debugging tools (gdb, lldb) for runtime behavior
  • Binary Reverse Engineering - Use dedicated RE tools (Ghidra, IDA) unless specifically analyzing DWARF sections
  • Compiler Debugging - DWARF generation issues are compiler-specific, not covered here

Authoritative Sources

The plugin uses these authoritative sources for DWARF standard information:

dwarfstd.org

Official DWARF specification via web search

LLVM Source

Reference implementations in llvm/lib/DebugInfo/DWARF/

libdwarf

Reference C implementation at github.com/davea42/libdwarf-code

Key LLVM Reference Files

  • DWARFDie.cpp - DIE handling and attribute access
  • DWARFUnit.cpp - Compilation unit parsing
  • DWARFDebugLine.cpp - Line number information
  • DWARFVerifier.cpp - Validation logic

Verification Workflows

Structural Validation

Validate DWARF data integrity using llvm-dwarfdump:
llvm-dwarfdump --verify <binary>

Common Verification Patterns

Verify binaries have valid DWARF before distribution
llvm-dwarfdump --verify --quiet myapp
echo $?  # 0 = success, non-zero = errors found
Use --statistics to detect debug info quality regressions
llvm-dwarfdump --statistics build1/myapp > stats1.json
llvm-dwarfdump --statistics build2/myapp > stats2.json
jq -s '.[0] - .[1]' stats1.json stats2.json
Identify malformed DWARF causing debugger issues
llvm-dwarfdump --verify --error-display=full problematic_binary
Validate parser output against known-good binaries
llvm-dwarfdump --verify --verify-json=errors.json test_binary

Parsing DWARF Information

Using dwarfdump

The primary tool for parsing and displaying DWARF information. More effective than readelf for DWARF-specific tasks.
# Display version (check if libdwarf or LLVM implementation)
dwarfdump --version

# Dump all DWARF sections
dwarfdump --all myapp

# Dump specific section
dwarfdump --debug-info myapp

Using readelf

For general ELF information, but prefer dwarfdump for DWARF-specific parsing.
# Display all debug sections
readelf --debug-dump myapp

# Display specific section
readelf --debug-dump=info myapp

Working With Code

Common DWARF Libraries

libdwarf
C/C++
Offers a simpler, lower-level interface. Used to implement dwarfdump.URL: https://github.com/davea42/libdwarf-code
pyelftools
Python
Also supports parsing of ELF files in general.URL: https://github.com/eliben/pyelftools
gimli
Rust
Designed for performant access to DWARF data. May require other dependencies (such as object) to open and parse entire DWARF files.URL: https://github.com/gimli-rs/gimli
debug/dwarf
Go
LibObjectFile
.NET
Also supports interfacing with object files (ELF, PE/COFF, etc) in general.URL: https://github.com/xoofx/LibObjectFile

Code Writing Guidelines

1

Prefer Python for scripting

Use Python for simpler DWARF code unless another language is specified
2

Leverage existing libraries

Use libraries listed above rather than parsing from scratch
3

Refer to library documentation

Check both in-code and online documentation when using libraries
4

Rely on authoritative sources

Use dwarfstd.org specifications or LLVM/libdwarf source for ground truth

Code Review Guidelines

When reviewing DWARF-related code, consider:
  • Edge Cases: Unhandled DIE node types, abstract base DIE nodes, specification DIE nodes
  • Optional Attributes: Ensure code handles missing optional attributes gracefully
  • Special DIE Types: Abstract origins, inlined instances, template instantiations
  • Only Suggest Changes: Don’t modify code during review unless explicitly asked

Advanced Searching

For name matches or address lookups:
dwarfdump --find=my_function myapp
dwarfdump --lookup=0x401000 myapp
For complex queries, combine dwarfdump with filtering tools:
1

Initial filtering

dwarfdump myapp | grep "float \*"
2

Get DIE address

dwarfdump myapp | grep -B 5 "float \*"
3

Refine filtering

dwarfdump myapp | grep -B 5 "float \*" | grep "DW_TAG_formal_parameter"
4

Print complete DWARF info

dwarfdump --lookup=0x1234 --show-children myapp
For highly complex queries, write a Python script using pyelftools:
from elftools.elf.elffile import ELFFile
from elftools.dwarf.die import DIE

with open('myapp', 'rb') as f:
    elffile = ELFFile(f)
    if not elffile.has_dwarf_info():
        print('No DWARF info')
        exit(1)
    
    dwarfinfo = elffile.get_dwarf_info()
    for CU in dwarfinfo.iter_CUs():
        for DIE in CU.iter_DIEs():
            # Custom search logic here
            if DIE.tag == 'DW_TAG_formal_parameter':
                # Check attributes, print matches, etc.
                pass

Decision Tree

Use this to choose your approach:
┌─ Need to verify DWARF data integrity?
│   └─ Use `llvm-dwarfdump --verify`
├─ Need to answer questions about the DWARF standard?
│   └─ Search dwarfstd.org or reference LLVM/libdwarf source
├─ Need simple section dump or general ELF info?
│   └─ Use `readelf`
├─ Need to parse, search, and/or dump DWARF DIE nodes?
│   └─ Use `dwarfdump`
└─ Need to write, modify, or review code that interacts with DWARF data?
    └─ Use appropriate library (pyelftools, libdwarf, gimli, etc.)

Examples

# Find all parameters of a specific function
dwarfdump --name my_function --show-children --recurse-depth=1 myapp
When searching for specific DIE nodes, start with --find (fast accelerator table lookup) and fall back to --name (exhaustive search) if needed.
The --statistics output is useful for comparing debug info quality across compiler versions and optimization levels.

Build docs developers (and LLMs) love