Skip to content
Back to skills

Dwarf Debug Format

ASecurity

Use when inspecting .debug_info or .debug_line sections with dwarfdump or readelf, working with split-DWARF .dwo files, setting up debuginfod, or checking how LTO and stripping affect debug info.

  • 54 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 20, 2026
ai-agentsrustbashexpressgit

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add OutlineDriven/outline-driven-development --skill dwarf-debug-format --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dwarf Debug Format?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dwarf Debug Format
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/outlinedriven-dwarf-debug-format-outline-driven-development/badge)](https://www.skillsdirectory.com/skills/outlinedriven-dwarf-debug-format-outline-driven-development)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dwarf-debug-format
description: 'Use when inspecting .debug_info or .debug_line sections with dwarfdump or readelf, working with split-DWARF .dwo files, setting up debuginfod, or checking how LTO and stripping affect debug info.'
disable-model-invocation: true
---

# DWARF debug format

## Contract

| Field | Bound contract |
|---|---|
| Trigger | DWARF sections in an ELF binary need listing or reading, `.dwo` split files need producing or packaging, debuginfod needs configuring, or LTO and stripping change what debug info survives. |
| Authority | Read-only. Emits analysis and commands for the operator to run on the target; no file writes, no rollback needed. No remote mutation. |
| Side effect | Inspection commands and a verdict in chat. Nothing is written. |
| Done | The debug info question is answered from the binary's own sections, or the missing piece (`.dwo`, debug package, build ID) is named. |

## Inputs

1. Binary or object file (required): the ELF file whose debug info is in question.
2. Toolchain (optional): `readelf` and `llvm-dwarfdump` cover most queries; `dwarfdump` and `eu-strip` come from libdwarf and elfutils packages.
3. Build ID (optional): needed for debuginfod lookups.

## Procedure

1. List the DWARF sections.

   ```bash
   readelf -S prog | grep "\.debug"
   ```

   | Section | Contents |
   |---|---|
   | `.debug_info` | DIEs: types, variables, functions |
   | `.debug_abbrev` | Abbreviation table for `.debug_info` |
   | `.debug_line` | Source line to address mapping |
   | `.debug_str` | Identifier strings |
   | `.debug_loc` / `.debug_loclists` | Variable location expressions (DWARF 4 / DWARF 5) |
   | `.debug_ranges` / `.debug_rnglists` | Non-contiguous address ranges (DWARF 4 / DWARF 5) |
   | `.debug_aranges` | Address to compilation unit lookup |
   | `.debug_pubnames` / `.debug_names` | Global name index (DWARF 4 / DWARF 5) |
   | `.debug_frame` | DWARF call frame information; `.eh_frame` is the runtime unwinding variant |
   | `.debug_addr` | Address table (DWARF 5) |
   | `.debug_line_str` | Line-table strings (DWARF 5) |

   Done when: the present sections are listed and named.
2. Inspect the contents.

   ```bash
   readelf --debug-dump=info prog      # DIEs
   readelf --debug-dump=lines prog     # line table
   llvm-dwarfdump --debug-info prog    # more readable DIE dump
   llvm-dwarfdump --statistics prog    # debug info size and quality metrics
   dwarfdump prog                      # full dump, when libdwarf's dwarfdump is installed
   ```

   Done when: the target section's contents are on screen.
3. Read the DIE structure. Debug info is a tree of Debug Information Entries. Each DIE has a tag (`DW_TAG_*`) and attributes (`DW_AT_*`).

   ```text
   DW_TAG_compile_unit
     DW_AT_producer  : "GNU C17 13.2.0"
     DW_AT_name      : "main.c"
     DW_AT_comp_dir  : "/home/user/project"
     DW_TAG_subprogram
       DW_AT_name    : "add"
       DW_AT_low_pc  : 0x401130        # function start
       DW_AT_high_pc : 0x401150        # function end
       DW_TAG_formal_parameter
         DW_AT_name     : "a"
         DW_AT_location : DW_OP_reg5   # x86-64 register rdi
   ```

   Common tags: `compile_unit`, `subprogram`, `variable`, `formal_parameter`, `typedef`, `structure_type`, `member`, `array_type`, `pointer_type`, `base_type`. Common attributes: `name`, `type`, `location`, `low_pc`, `high_pc`, `byte_size`, `encoding`, `file`, `line`. Done when: the DIE of interest is located and its attributes are read.
4. Work with split DWARF. `-gsplit-dwarf` writes debug info to `.dwo` sidecars so the linker never processes it.

   ```bash
   gcc -g -gsplit-dwarf -O2 -c main.c -o main.o   # main.o plus main.dwo
   gcc main.o -o prog                             # prog references main.dwo
   dwarfdump prog | grep dwo_name                 # DW_AT_GNU_dwo_name holds the path
   dwp -o prog.dwp prog                           # GNU: pack .dwo files into one .dwp
   llvm-dwp -o prog.dwp prog                      # LLVM equivalent
   ```

   GDB resolves `.dwo` and `.dwp` files placed next to the binary. Done when: the binary links without debug input and GDB still resolves symbols.
5. Configure debuginfod for remote symbols.

   ```bash
   export DEBUGINFOD_URLS="https://debuginfod.elfutils.org/"
   gdb /usr/bin/git                     # fetches missing debug info over HTTP
   debuginfod-find debuginfo <build-id-or-path>
   debuginfod-find source <build-id> /path/to/source.c
   ```

   ```gdb
   (gdb) set debuginfod enabled on
   (gdb) set debuginfod verbose 1
   ```

   Run a private server with `debuginfod -d /var/cache/debuginfod -p 8002 /path/to/binaries/` and point `DEBUGINFOD_URLS` at `http://localhost:8002`. Done when: GDB fetches symbols for a stripped system binary.
6. Judge LTO's effect. `-flto` generates DWARF after link-time optimization, so merged, inlined, or eliminated entities lose their debug entries. `-flto=thin` (Clang) keeps more. For maximum debug info, build a separate `-Og -g` binary without LTO. In Rust, the dev profile already defaults to `lto = "off"`; enabling `lto` in a release profile trades debug detail for optimization. Done when: the LTO/debug tradeoff is stated for the build in question.
7. Strip binaries while keeping symbols.

   ```bash
   objcopy --only-keep-debug prog prog.debug
   strip --strip-debug prog
   objcopy --add-gnu-debuglink=prog.debug prog   # GDB finds prog.debug automatically
   eu-strip -f prog.debug prog                   # elfutils: split in one step
   readelf -n prog | grep -i debug               # verify the link
   llvm-dwarfdump --statistics prog              # check what debug info remains
   size --format=SysV prog                       # section sizes
   ```

   Done when: the stripped binary resolves symbols through its debug link or a symbol store.

## Failure and recovery

- `readelf -S` shows no `.debug_*` sections: the binary was built without `-g` or was stripped. Rebuild with `-g` or locate the matching debug file by build ID.
- `.dwo` files not found: they must sit next to the objects or be packed into a `.dwp`. Check `DW_AT_GNU_dwo_name` for the expected path.
- debuginfod fetch fails: confirm `DEBUGINFOD_URLS` is set in the environment GDB inherits, and that the distro runs a server for that package.
- LTO build loses the variable being chased: rebuild that translation unit without `-flto`, or debug the `-Og` build instead.
- DWARF version mismatch: older tools cannot parse DWARF 5 sections. Use a current `readelf` or `llvm-dwarfdump`, or rebuild with `-gdwarf-4`.

## Output

An answer grounded in the binary's own sections: the DIE or line-table entry found, the `.dwo`/debuginfod path configured, or the named reason the debug info is absent.

Files in this skill

  • SKILL.md6.6 KB
  • agents/openai.yaml267 B

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…