Skip to content

Extract strings from DWARF debug information (.debug_info, .debug_str, .debug_line) #62

Description

@unclesp1d3r

Overview

Extract meaningful strings and metadata from DWARF debug sections present in non-stripped binaries. DWARF debug information contains high-confidence, developer-chosen identifiers that provide significant value for binary analysis even when traditional symbols are unavailable.

Background: What is DWARF?

DWARF (Debugging With Attributed Record Formats) is a standardized debugging data format used by compilers to embed source-level information into binaries. It's the dominant debug format for ELF (Linux/Unix) and Mach-O (macOS) binaries compiled with -g flags.

Key DWARF Sections

  • .debug_info: Core debugging data containing DIEs (Debug Information Entries) with function/variable names, types, and source locations
  • .debug_str: String table containing all text references from .debug_info
  • .debug_line: Line number program mapping machine instructions to source file paths and line numbers
  • .debug_abbrev: Abbreviation declarations describing DIE structure (needed for parsing .debug_info)
  • .debug_types (DWARF 4), .debug_str_offsets (DWARF 5): Additional optimization sections

Value Proposition

High-Confidence Identifiers

DWARF data is structured and intentional—not arbitrary byte patterns. Extracting from DWARF provides:

  • Function names: handle_authentication, decrypt_payload, validate_license
  • Variable names: secret_key, api_endpoint, config_path
  • Type information: struct UserCredentials, class DatabaseConnection
  • Source file paths: /home/builder/project/src/crypto/aes.c, revealing project structure

Intelligence Value

  • Build environment disclosure: Absolute paths expose developer machines, CI systems, directory structures
  • Code organization: Source file names reveal architectural patterns and module boundaries
  • Semantic context: Variable/function names provide intent rather than raw string literals
  • Reverse engineering: Symbolic names dramatically accelerate understanding compiled code

Complementary to Existing Extraction

DWARF augments rather than replaces existing string extraction:

  • Symbols: DWARF works when .symtab is stripped but debug sections remain
  • Section data: DWARF names often don't appear in .rodata (they're in .debug_str)
  • Imports/exports: DWARF reveals internal implementation details, not just API boundaries

Proposed Implementation

1. Add gimli Dependency

[dependencies]
gimli = "0.29"
object = "0.36"  # Provides DWARF section reader interface

Rationale: gimli is the de-facto Rust DWARF parser, maintained by the Rust debugging tools team and used by addr2line, cargo, and debuggers.

2. Extend Existing Types

In src/types.rs:

  • StringSource::DebugInfo already exists ✅
  • Add new Tag variants:
    pub enum Tag {
        // ... existing tags
        DwarfSymbol,      // Function/variable name from DW_AT_name
        DwarfFilePath,    // Source file path from DW_AT_comp_dir / DW_AT_decl_file
        DwarfType,        // Type name from DW_TAG_structure_type, DW_TAG_class_type
    }

3. Create DWARF Extraction Module

New file: src/extraction/dwarf.rs

use gimli::{Dwarf, EndianSlice, RunTimeEndian};
use object::{Object, ObjectSection};

pub struct DwarfExtractor {
    skip_dwarf: bool,
    max_section_size: Option<usize>,
}

impl DwarfExtractor {
    pub fn extract(&self, data: &[u8], format: BinaryFormat) -> Result<Vec<FoundString>> {
        // 1. Load DWARF sections using object crate
        // 2. Parse with gimli::Dwarf
        // 3. Iterate compilation units
        // 4. Extract DW_AT_name, DW_AT_comp_dir, DW_AT_decl_file
        // 5. Return FoundString with high scores (90+)
    }
}

4. Integration Points

In src/container/elf.rs:

  • Classify DWARF sections correctly (already done: SectionType::Debug for .debug_* ✅)
  • Ensure DWARF sections are included in ContainerInfo

In src/extraction/mod.rs:

  • Import and instantiate DwarfExtractor
  • Call after section-based extraction
  • Coordinate with deduplication logic

5. CLI Integration

In src/main.rs (when CLI is implemented):

#[derive(Parser)]
struct Args {
    // ... existing args
    
    /// Skip DWARF debug section extraction (faster for large binaries)
    #[arg(long)]
    skip_dwarf: bool,
    
    /// Maximum DWARF section size to process (in MB)
    #[arg(long, default_value = "100")]
    max_dwarf_size: usize,
}

Technical Considerations

Performance

  • DWARF parsing is CPU-intensive: A single .debug_info section can be 50-200MB in optimized Rust binaries with full debug info
  • Mitigation strategies:
    • --skip-dwarf flag for performance-critical scenarios
    • Size limits (--max-dwarf-size) to skip enormous sections
    • Lazy parsing: only process compilation units, skip full type graphs
    • Skip .debug_types initially (less string content, high complexity)

Binary Size Realities

  • Stripped binaries (strip --strip-debug): No DWARF sections → graceful no-op
  • Partially stripped (strip --strip-unneeded): May retain DWARF → full extraction
  • Debug builds: Massive DWARF sections (10-100x code size) → sampling or limits needed

Scoring Strategy

Assign high scores since DWARF strings are definitionally meaningful:

  • Function/variable names (DW_AT_name): Score 95
  • Source file paths (DW_AT_comp_dir, DW_AT_decl_file): Score 90
  • Type names (DW_TAG_structure_type): Score 92

These should rank above most .rodata strings but below critical items like hardcoded URLs/keys.

Deduplication

  • Problem: A string like parse_config may appear in:

    1. .debug_str (DWARF)
    2. .symtab (symbol table)
    3. .dynstr (dynamic symbols)
    4. .rodata (error messages mentioning the function)
  • Solution: Deduplication by (text, encoding) tuple in final output, preserving highest score and all relevant tags.

Security & Privacy

  • Build path disclosure: DWARF exposes absolute paths like /home/alice/secret-project/src/
    • This is intentional for binary analysis—users examining untrusted binaries want this intel
    • Document in output that DWARF reveals build environment details

Implementation Checklist

  • Add gimli and object dependencies to Cargo.toml
  • Create src/extraction/dwarf.rs module
  • Add DwarfSymbol, DwarfFilePath, DwarfType tags to Tag enum
  • Implement DwarfExtractor::extract() method
    • Load DWARF sections from ELF/Mach-O
    • Parse .debug_info compilation units
    • Extract DW_AT_name attributes → FoundString with Tag::DwarfSymbol
    • Extract DW_AT_comp_dir / DW_AT_decl_file → Tag::DwarfFilePath
    • Extract structure/class type names → Tag::DwarfType
  • Add --skip-dwarf and --max-dwarf-size CLI flags
  • Integrate into main extraction pipeline
  • Add deduplication logic for DWARF + symbol table overlap
  • Write unit tests with small DWARF samples
  • Write integration tests:
    • Test with stripped binary (no DWARF)
    • Test with debug build (full DWARF)
    • Test with large DWARF section (size limits)
  • Document DWARF extraction in README and --help

Testing Strategy

Unit Tests

  • Mock DWARF sections with known DIEs
  • Verify extraction of specific DW_AT_name values
  • Test score assignment logic

Integration Tests

Create test fixtures:

  1. tests/fixtures/hello_debug: Minimal C program compiled with -g
  2. tests/fixtures/hello_stripped: Same binary with strip --strip-debug
  3. tests/fixtures/rust_debug: Rust binary with full debug info (tests demangling + DWARF)

Expected behavior:

  • hello_debug: Extract function names (main, printf), source path
  • hello_stripped: Gracefully skip, no errors
  • rust_debug: Extract Rust function names, handle DWARF 4/5 versions

References

Success Criteria

  1. ✅ Extract all DW_AT_name attributes from .debug_info
  2. ✅ Extract source file paths from line number programs
  3. ✅ Handle DWARF versions 2-5 gracefully
  4. ✅ --skip-dwarf flag works correctly
  5. ✅ No crashes on malformed DWARF (handle gimli parse errors)
  6. ✅ Deduplication prevents duplicate strings from DWARF + symtab
  7. ✅ Documentation includes DWARF extraction examples

Activity

  1. added theissue type on Nov 10, 2025
  2. traycerai commented on Nov 10, 2025

    @traycerai

    Plan

    Observations

    The codebase features a modular architecture with established container parsing for ELF, PE, and Mach-O formats using the goblin crate. The types.rs module includes StringSource::DebugInfo and SectionType::Debug, facilitating DWARF integration. Extraction and classification modules are placeholders awaiting implementation. The ELF parser correctly identifies DWARF sections like .debug_info and .debug_str. CLI structure in main.rs supports extensible argument parsing. Documentation and test fixtures exist but lack DWARF-specific content. The project follows Rust best practices with Cargo dependencies and integration testing patterns.

    Approach

    Implement DWARF string extraction by adding gimli and object dependencies for parsing. Create a dwarf.rs module to load DWARF sections, traverse DIEs in compilation units, and extract high-value strings from DW_AT_name, DW_AT_comp_dir, and DW_AT_decl_file attributes. Extend the Tag enum with DwarfSymbol, DwarfFilePath, and DwarfType variants. Integrate into the extraction pipeline with configurable skipping via CLI flags. Assign scores of 90-95 to DWARF strings based on their structured nature. Add unit and integration tests using debug-compiled fixtures, and update documentation to cover the new feature.

    Reasoning

    Examined the repository structure and key files including Cargo.toml, types.rs, extraction mod, container parsers, main.rs, and documentation. Reviewed existing section classification logic in ELF parser to confirm DWARF section handling. Studied the proposed implementation in the ticket for gimli usage patterns, attribute extraction, and scoring strategy. Analyzed test fixtures and integration test patterns to plan appropriate testing coverage. Consulted gimli documentation examples for DIE traversal and string resolution techniques.

    Proposed File Changes

    📄 Cargo.toml (MODIFY) 🔗

    Add the following dependencies to the [dependencies] section:

    • gimli = "0.29" for DWARF parsing capabilities, including support for reading compilation units, traversing DIEs, and extracting attribute values.
    • object = "0.36" to interface with binary sections, load DWARF data into buffers, and handle endianness detection as demonstrated in gimli examples.

    These crates enable robust DWARF section processing without introducing optional features, keeping the core binary lightweight while providing essential debug information extraction.

    📄 src/types.rs (MODIFY) 🔗

    Extend the Tag enum with new variants to classify DWARF-extracted strings:

    • DwarfSymbol for function and variable names derived from DW_AT_name attributes on DW_TAG_subprogram and DW_TAG_variable DIEs.
    • DwarfFilePath for source file paths resolved from DW_AT_comp_dir and DW_AT_decl_file attributes, building on the existing FilePath tag for consistency.
    • DwarfType for type names from DW_TAG_structure_type, DW_TAG_class_type, and similar DIEs representing structs, classes, and enums.

    Use #[serde(rename = "dwarf-symbol")], #[serde(rename = "dwarf-file-path")], and #[serde(rename = "dwarf-type")] attributes to ensure proper JSON serialization. These tags enable filtering and identification of DWARF-sourced content in outputs, complementing existing tags like Symbol and FilePath.

    📄 src/extraction/mod.rs (MODIFY) 🔗

    References

    Introduce the extraction module structure by defining:

    • ExtractionConfig struct with fields: skip_dwarf: bool (default: false), max_dwarf_size: Option<usize> (default: Some(100 * 1024 * 1024) for 100MB limit), and other extraction parameters like minimum string lengths.

    • Public function pub fn extract_strings(data: &[u8], container_info: &ContainerInfo, config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>> to orchestrate extraction from multiple sources, including a conditional call to DWARF extraction if not skipped.

    • Module declaration pub mod dwarf; to expose the new submodule.

    • Basic error handling and logging for extraction failures.

    This establishes the pipeline foundation, allowing DWARF extraction to integrate seamlessly as one phase among section scanning and symbol table processing.

    📄 src/extraction/dwarf.rs (NEW) 🔗

    References

    Implement the DWARF extraction module as follows:

    • Define pub fn extract_dwarf_strings(sections: &[Section], data: &[u8], config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>> as the entry point.

    • Identify relevant DWARF sections (.debug_info, .debug_str, .debug_line, .debug_abbrev, .debug_types) from the provided sections vector, skipping if config.skip_dwarf is true or section size exceeds max_dwarf_size.

    • Use the object crate to create an Object from data and load section data into gimli::DwarfSections buffers.

    • Construct gimli::Dwarf with EndianSlice readers, detecting endianness from the binary format.

    • Iterate over compilation units using dwarf.units() and type units with dwarf.debug_types().

    • For each unit, traverse DIEs with unit.entries() and next_dfs() to visit all entries depth-first.

    • Extract strings via:

      • DW_AT_name: Use dwarf.attr_string(unit, attr.value())? to get UTF-8 strings, create FoundString with text, encoding: Encoding::Utf8, source: StringSource::DebugInfo, tags: vec![Tag::DwarfSymbol], score: 95.
      • DW_AT_comp_dir: Resolve as directory path, tag with Tag::DwarfFilePath, score 90.
      • DW_AT_decl_file: Combine with line program (unit.line_program) to resolve full file path using header.file(index).as_ref()?.path().to_string_lossy(), prepend DW_AT_comp_dir if available, tag Tag::DwarfFilePath, score 90.
      • For type DIEs (DW_TAG_structure_type, etc.): Extract name with Tag::DwarfType, score 92.
    • Set offset to approximate position (section offset + attribute offset), section to the source section name, rva: None, length: text.len() as u32.

    • Deduplicate within DWARF results using a HashSet<String> before returning.

    • Handle errors gracefully: malformed sections return empty vec, log warnings for parse failures.

    • Support DWARF versions 2-5 implicitly via gimli's compatibility layer.

    Reference gimli examples for DwarfSections::load, unit iteration, and attribute resolution to ensure correct API usage.

    📄 src/main.rs (MODIFY) 🔗

    References

    Enhance the CLI parsing and main logic to support DWARF extraction:

    • Add to Cli struct (using clap::Parser): #[arg(long, default_value_t = false, help = "Skip DWARF debug section extraction (faster for large binaries)")] skip_dwarf: bool, and #[arg(long, default_value_t = 100, help = "Maximum DWARF section size to process (in MB)")] max_dwarf_size: usize,.

    • In the main function, after parsing the binary and obtaining ContainerInfo:

      • Create ExtractionConfig { skip_dwarf: cli.skip_dwarf, max_dwarf_size: Some(cli.max_dwarf_size * 1024 * 1024), ..Default::default() }.
      • Call extraction::extract_strings(&file_data, &container_info, &config)? to get Vec<FoundString>.
      • Proceed to classification, ranking, and output as per existing pipeline (placeholders to be filled).
    • Update error handling to propagate extraction errors.

    • For now, if extraction is not yet fully implemented, add a debug print showing config values to verify flag parsing.

    This integrates user controls into the workflow, enabling performance tuning for DWARF processing.

    📄 src/lib.rs (MODIFY) 🔗

    References

    Update the library documentation and public API:

    • In the module docstring, add a section describing DWARF extraction: "Supports extraction from DWARF debug sections using the gimli crate, providing function names, source paths, and type information with high confidence scores."

    • Re-export ExtractionConfig from extraction module: pub use extraction::{extract_strings, ExtractionConfig};.

    • Update "Current Implementation Status" to note: "DWARF extraction: Implemented via src/extraction/dwarf.rs, integrated into main pipeline."

    • Add an example usage snippet showing DWARF-enabled extraction.

    This ensures the crate's public interface reflects the new functionality and guides library users on DWARF features.

    📄 tests/integration_dwarf.rs (NEW) 🔗

    References

    Create comprehensive integration tests for DWARF extraction, following patterns from tests/integration_elf.rs:

    • Use #[test] functions with fixtures: Assume new fixtures tests/fixtures/hello_debug (C program compiled with gcc -g), tests/fixtures/hello_stripped (stripped version), and tests/fixtures/rust_debug (Rust binary with debug info).

    • Test section detection: Verify parse_elf identifies DWARF sections as SectionType::Debug.

    • Test extraction with debug binary: Call extract_strings with skip_dwarf: false, assert extracted strings include expected DW_AT_name like "main", "printf" with Tag::DwarfSymbol, score >=95, source: StringSource::DebugInfo.

    • Test file path extraction: Assert paths like "hello.c" or full /path/to/hello.c with Tag::DwarfFilePath, score 90.

    • Test type extraction: For Rust fixture, verify struct names with Tag::DwarfType.

    • Test skip flag: With skip_dwarf: true, assert no DWARF strings in results.

    • Test size limit: Mock a large section, verify skipping when exceeding max_dwarf_size.

    • Test stripped binary: No crash, empty DWARF results.

    • Test malformed DWARF: Use a corrupted fixture, ensure graceful error handling without panic.

    • Use insta::assert_snapshot! for output validation, comparing JSON-serialized FoundString vectors.

    • Add #[cfg(feature = "integration")] if needed, and helper functions like get_fixture_path("hello_debug").

    These tests validate the full pipeline, from section loading to string creation and scoring.

    📄 README.md (MODIFY) 🔗

    Enhance the README to highlight DWARF extraction capabilities:

    • In "Features" section, add bullet: "🔍 DWARF Debug Extraction: Retrieve function names, variable identifiers, type information, and source file paths from debug sections in non-stripped binaries."

    • In "Usage" section, include CLI examples:

      # Full extraction including DWARF
      cargo run -- target/debug/my_binary
      
      # Skip DWARF for performance
      cargo run -- --skip-dwarf target/debug/my_binary
      
      # Limit DWARF section size
      cargo run -- --max-dwarf-size 50 target/debug/my_binary
    • Update "Development Status" or "Roadmap" to mark DWARF extraction as ✅ Implemented.

    • In "Advantages" section, add: "- Extracts semantic identifiers from DWARF debug info, revealing internal implementation details beyond surface-level strings."

    • Add to "Acknowledgements": "- gimli crate for robust DWARF parsing."

    • Include a brief example output showing a DWARF-extracted function name with tags and score.

    These updates inform users about the feature, its benefits, and usage options.

    📄 docs/src/string-extraction.md (MODIFY) 🔗

    References

    Expand the string extraction documentation with a dedicated DWARF section:

    • Add heading "## DWARF Debug Information Extraction" describing the value of extracting from .debug_info, .debug_str, .debug_line, etc., including examples of function names, paths, and types.

    • Detail the implementation: gimli crate usage, DIE traversal, attribute extraction (DW_AT_name, etc.), and path resolution via line programs.

    • Cover scoring: 95 for symbols, 90 for paths, 92 for types, explaining high confidence due to structured data.

    • Discuss performance mitigations: skip flag, size limits, and when to use stripped binaries.

    • Include deduplication notes: How DWARF strings merge with symtab/rodata results, preserving best score and tags.

    • Provide code snippets (non-executable) showing extraction flow and FoundString creation.

    • Reference DWARF standard and gimli docs.

    • End with usage example in JSON output format.

    This comprehensive doc serves as a user guide and technical reference for the feature.

    📄 .kiro/specs/stringy-binary-analyzer/tasks.md (MODIFY) 🔗

    Update the tasks document by adding or completing the DWARF extraction task:

    • Insert or modify task Implement File Path Classification for POSIX, Windows, and Registry Paths #17 (or appropriate number): "Implement DWARF debug information extraction"
      • Subtasks:
        • Add gimli and object dependencies
        • Create src/extraction/dwarf.rs module
        • Extend Tag enum with DwarfSymbol, DwarfFilePath, DwarfType
        • Implement DIE traversal and attribute extraction (DW_AT_name, DW_AT_comp_dir, DW_AT_decl_file)
        • Add CLI flags --skip-dwarf and --max-dwarf-size
        • Integrate into extraction pipeline with deduplication
        • Implement scoring (90-95 range)
        • Add unit tests for attribute parsing
        • Add integration tests for debug/stripped/large binaries
        • Update documentation (README, string-extraction.md)
      • Requirements: High-confidence string extraction from debug sections, performance controls.

    Mark subtasks as completed based on this plan's implementation. Ensure the task aligns with the epic for enhanced analyzer capabilities.

    Import In IDE

    VSCode Icon Cursor Icon Windsurf Icon

    🤖 Prompt for AI Agents
    I have created the following plan after thorough exploration and analysis of the codebase. Follow the below plan verbatim. Trust the files and references. Do not re-verify what's written in the plan. Explore only when absolutely necessary. First implement all the proposed file changes and then I'll review all the changes together at the end.
    
    ### Observations
    
    The codebase features a modular architecture with established container parsing for ELF, PE, and Mach-O formats using the `goblin` crate. The `types.rs` module includes `StringSource::DebugInfo` and `SectionType::Debug`, facilitating DWARF integration. Extraction and classification modules are placeholders awaiting implementation. The ELF parser correctly identifies DWARF sections like `.debug_info` and `.debug_str`. CLI structure in `main.rs` supports extensible argument parsing. Documentation and test fixtures exist but lack DWARF-specific content. The project follows Rust best practices with Cargo dependencies and integration testing patterns.
    
    ### Approach
    
    Implement DWARF string extraction by adding `gimli` and `object` dependencies for parsing. Create a `dwarf.rs` module to load DWARF sections, traverse DIEs in compilation units, and extract high-value strings from `DW_AT_name`, `DW_AT_comp_dir`, and `DW_AT_decl_file` attributes. Extend the `Tag` enum with `DwarfSymbol`, `DwarfFilePath`, and `DwarfType` variants. Integrate into the extraction pipeline with configurable skipping via CLI flags. Assign scores of 90-95 to DWARF strings based on their structured nature. Add unit and integration tests using debug-compiled fixtures, and update documentation to cover the new feature.
    
    ### Reasoning
    
    Examined the repository structure and key files including Cargo.toml, types.rs, extraction mod, container parsers, main.rs, and documentation. Reviewed existing section classification logic in ELF parser to confirm DWARF section handling. Studied the proposed implementation in the ticket for gimli usage patterns, attribute extraction, and scoring strategy. Analyzed test fixtures and integration test patterns to plan appropriate testing coverage. Consulted gimli documentation examples for DIE traversal and string resolution techniques.
    
    ## Proposed File Changes
    
    ### Cargo.toml(MODIFY)
    
    Add the following dependencies to the `[dependencies]` section:
    
    - `gimli = "0.29"` for DWARF parsing capabilities, including support for reading compilation units, traversing DIEs, and extracting attribute values.
    - `object = "0.36"` to interface with binary sections, load DWARF data into buffers, and handle endianness detection as demonstrated in gimli examples.
    
    These crates enable robust DWARF section processing without introducing optional features, keeping the core binary lightweight while providing essential debug information extraction.
    
    ### src/types.rs(MODIFY)
    
    Extend the `Tag` enum with new variants to classify DWARF-extracted strings:
    
    - `DwarfSymbol` for function and variable names derived from `DW_AT_name` attributes on `DW_TAG_subprogram` and `DW_TAG_variable` DIEs.
    - `DwarfFilePath` for source file paths resolved from `DW_AT_comp_dir` and `DW_AT_decl_file` attributes, building on the existing `FilePath` tag for consistency.
    - `DwarfType` for type names from `DW_TAG_structure_type`, `DW_TAG_class_type`, and similar DIEs representing structs, classes, and enums.
    
    Use `#[serde(rename = "dwarf-symbol")]`, `#[serde(rename = "dwarf-file-path")]`, and `#[serde(rename = "dwarf-type")]` attributes to ensure proper JSON serialization. These tags enable filtering and identification of DWARF-sourced content in outputs, complementing existing tags like `Symbol` and `FilePath`.
    
    ### src/extraction/mod.rs(MODIFY)
    
    References: 
    
    - src/types.rs(MODIFY)
    
    Introduce the extraction module structure by defining:
    
    - `ExtractionConfig` struct with fields: `skip_dwarf: bool` (default: false), `max_dwarf_size: Option<usize>` (default: Some(100 * 1024 * 1024) for 100MB limit), and other extraction parameters like minimum string lengths.
    
    - Public function `pub fn extract_strings(data: &[u8], container_info: &ContainerInfo, config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>>` to orchestrate extraction from multiple sources, including a conditional call to DWARF extraction if not skipped.
    
    - Module declaration `pub mod dwarf;` to expose the new submodule.
    
    - Basic error handling and logging for extraction failures.
    
    This establishes the pipeline foundation, allowing DWARF extraction to integrate seamlessly as one phase among section scanning and symbol table processing.
    
    ### src/extraction/dwarf.rs(NEW)
    
    References: 
    
    - src/types.rs(MODIFY)
    - src/container/mod.rs
    
    Implement the DWARF extraction module as follows:
    
    - Define `pub fn extract_dwarf_strings(sections: &[Section], data: &[u8], config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>>` as the entry point.
    
    - Identify relevant DWARF sections (`.debug_info`, `.debug_str`, `.debug_line`, `.debug_abbrev`, `.debug_types`) from the provided `sections` vector, skipping if `config.skip_dwarf` is true or section size exceeds `max_dwarf_size`.
    
    - Use the `object` crate to create an `Object` from `data` and load section data into `gimli::DwarfSections` buffers.
    
    - Construct `gimli::Dwarf` with `EndianSlice` readers, detecting endianness from the binary format.
    
    - Iterate over compilation units using `dwarf.units()` and type units with `dwarf.debug_types()`.
    
    - For each unit, traverse DIEs with `unit.entries()` and `next_dfs()` to visit all entries depth-first.
    
    - Extract strings via:
      - `DW_AT_name`: Use `dwarf.attr_string(unit, attr.value())?` to get UTF-8 strings, create `FoundString` with `text`, `encoding: Encoding::Utf8`, `source: StringSource::DebugInfo`, `tags: vec![Tag::DwarfSymbol]`, `score: 95`.
      - `DW_AT_comp_dir`: Resolve as directory path, tag with `Tag::DwarfFilePath`, score 90.
      - `DW_AT_decl_file`: Combine with line program (`unit.line_program`) to resolve full file path using `header.file(index).as_ref()?.path().to_string_lossy()`, prepend `DW_AT_comp_dir` if available, tag `Tag::DwarfFilePath`, score 90.
      - For type DIEs (`DW_TAG_structure_type`, etc.): Extract name with `Tag::DwarfType`, score 92.
    
    - Set `offset` to approximate position (section offset + attribute offset), `section` to the source section name, `rva: None`, `length: text.len() as u32`.
    
    - Deduplicate within DWARF results using a `HashSet<String>` before returning.
    
    - Handle errors gracefully: malformed sections return empty vec, log warnings for parse failures.
    
    - Support DWARF versions 2-5 implicitly via gimli's compatibility layer.
    
    Reference gimli examples for `DwarfSections::load`, unit iteration, and attribute resolution to ensure correct API usage.
    
    ### src/main.rs(MODIFY)
    
    References: 
    
    - src/extraction/mod.rs(MODIFY)
    
    Enhance the CLI parsing and main logic to support DWARF extraction:
    
    - Add to `Cli` struct (using `clap::Parser`): `#[arg(long, default_value_t = false, help = "Skip DWARF debug section extraction (faster for large binaries)")] skip_dwarf: bool,` and `#[arg(long, default_value_t = 100, help = "Maximum DWARF section size to process (in MB)")] max_dwarf_size: usize,`.
    
    - In the `main` function, after parsing the binary and obtaining `ContainerInfo`:
      - Create `ExtractionConfig { skip_dwarf: cli.skip_dwarf, max_dwarf_size: Some(cli.max_dwarf_size * 1024 * 1024), ..Default::default() }`.
      - Call `extraction::extract_strings(&file_data, &container_info, &config)?` to get `Vec<FoundString>`.
      - Proceed to classification, ranking, and output as per existing pipeline (placeholders to be filled).
    
    - Update error handling to propagate extraction errors.
    
    - For now, if extraction is not yet fully implemented, add a debug print showing config values to verify flag parsing.
    
    This integrates user controls into the workflow, enabling performance tuning for DWARF processing.
    
    ### src/lib.rs(MODIFY)
    
    References: 
    
    - src/extraction/mod.rs(MODIFY)
    
    Update the library documentation and public API:
    
    - In the module docstring, add a section describing DWARF extraction: "Supports extraction from DWARF debug sections using the gimli crate, providing function names, source paths, and type information with high confidence scores."
    
    - Re-export `ExtractionConfig` from `extraction` module: `pub use extraction::{extract_strings, ExtractionConfig};`.
    
    - Update "Current Implementation Status" to note: "DWARF extraction: Implemented via src/extraction/dwarf.rs, integrated into main pipeline."
    
    - Add an example usage snippet showing DWARF-enabled extraction.
    
    This ensures the crate's public interface reflects the new functionality and guides library users on DWARF features.
    
    ### tests/integration_dwarf.rs(NEW)
    
    References: 
    
    - tests/integration_elf.rs
    - tests/fixtures/README.md
    
    Create comprehensive integration tests for DWARF extraction, following patterns from `tests/integration_elf.rs`:
    
    - Use `#[test]` functions with fixtures: Assume new fixtures `tests/fixtures/hello_debug` (C program compiled with `gcc -g`), `tests/fixtures/hello_stripped` (stripped version), and `tests/fixtures/rust_debug` (Rust binary with debug info).
    
    - Test section detection: Verify `parse_elf` identifies DWARF sections as `SectionType::Debug`.
    
    - Test extraction with debug binary: Call `extract_strings` with `skip_dwarf: false`, assert extracted strings include expected `DW_AT_name` like "main", "printf" with `Tag::DwarfSymbol`, score >=95, `source: StringSource::DebugInfo`.
    
    - Test file path extraction: Assert paths like "hello.c" or full `/path/to/hello.c` with `Tag::DwarfFilePath`, score 90.
    
    - Test type extraction: For Rust fixture, verify struct names with `Tag::DwarfType`.
    
    - Test skip flag: With `skip_dwarf: true`, assert no DWARF strings in results.
    
    - Test size limit: Mock a large section, verify skipping when exceeding `max_dwarf_size`.
    
    - Test stripped binary: No crash, empty DWARF results.
    
    - Test malformed DWARF: Use a corrupted fixture, ensure graceful error handling without panic.
    
    - Use `insta::assert_snapshot!` for output validation, comparing JSON-serialized `FoundString` vectors.
    
    - Add `#[cfg(feature = "integration")]` if needed, and helper functions like `get_fixture_path("hello_debug")`.
    
    These tests validate the full pipeline, from section loading to string creation and scoring.
    
    ### README.md(MODIFY)
    
    Enhance the README to highlight DWARF extraction capabilities:
    
    - In "Features" section, add bullet: "🔍 DWARF Debug Extraction: Retrieve function names, variable identifiers, type information, and source file paths from debug sections in non-stripped binaries."
    
    - In "Usage" section, include CLI examples:
      ```bash
      # Full extraction including DWARF
      cargo run -- target/debug/my_binary
      
      # Skip DWARF for performance
      cargo run -- --skip-dwarf target/debug/my_binary
      
      # Limit DWARF section size
      cargo run -- --max-dwarf-size 50 target/debug/my_binary
      ```
    
    - Update "Development Status" or "Roadmap" to mark DWARF extraction as ✅ Implemented.
    
    - In "Advantages" section, add: "- Extracts semantic identifiers from DWARF debug info, revealing internal implementation details beyond surface-level strings."
    
    - Add to "Acknowledgements": "- gimli crate for robust DWARF parsing."
    
    - Include a brief example output showing a DWARF-extracted function name with tags and score.
    
    These updates inform users about the feature, its benefits, and usage options.
    
    ### docs/src/string-extraction.md(MODIFY)
    
    References: 
    
    - src/extraction/dwarf.rs(NEW)
    
    Expand the string extraction documentation with a dedicated DWARF section:
    
    - Add heading "## DWARF Debug Information Extraction" describing the value of extracting from `.debug_info`, `.debug_str`, `.debug_line`, etc., including examples of function names, paths, and types.
    
    - Detail the implementation: gimli crate usage, DIE traversal, attribute extraction (`DW_AT_name`, etc.), and path resolution via line programs.
    
    - Cover scoring: 95 for symbols, 90 for paths, 92 for types, explaining high confidence due to structured data.
    
    - Discuss performance mitigations: skip flag, size limits, and when to use stripped binaries.
    
    - Include deduplication notes: How DWARF strings merge with symtab/rodata results, preserving best score and tags.
    
    - Provide code snippets (non-executable) showing extraction flow and `FoundString` creation.
    
    - Reference DWARF standard and gimli docs.
    
    - End with usage example in JSON output format.
    
    This comprehensive doc serves as a user guide and technical reference for the feature.
    
    ### .kiro/specs/stringy-binary-analyzer/tasks.md(MODIFY)
    
    Update the tasks document by adding or completing the DWARF extraction task:
    
    - Insert or modify task #17 (or appropriate number): "Implement DWARF debug information extraction"
      - Subtasks:
        - [x] Add gimli and object dependencies
        - [x] Create src/extraction/dwarf.rs module
        - [x] Extend Tag enum with DwarfSymbol, DwarfFilePath, DwarfType
        - [x] Implement DIE traversal and attribute extraction (DW_AT_name, DW_AT_comp_dir, DW_AT_decl_file)
        - [x] Add CLI flags --skip-dwarf and --max-dwarf-size
        - [x] Integrate into extraction pipeline with deduplication
        - [x] Implement scoring (90-95 range)
        - [x] Add unit tests for attribute parsing
        - [x] Add integration tests for debug/stripped/large binaries
        - [x] Update documentation (README, string-extraction.md)
      - Requirements: High-confidence string extraction from debug sections, performance controls.
    
    Mark subtasks as completed based on this plan's implementation. Ensure the task aligns with the epic for enhanced analyzer capabilities.

    Developer Humor

    In the depths of .debug_info, where DIEs dwell,\n> Gimli parses the secrets that compilers tell.\n> Function names emerge, paths come to light,\n> With scores so high, they're a reverse engineer's delight!\n> But strip the debug, and they vanish from sight—\n> Use --skip-dwarf if you want speed, not insight. 🛠️🔍


    Execution Information

    Branch: main
    Commit: 37cfc7c


    💡 Tips

    Supported Commands (Inside Comments)

    • Use @traycerai generate to iterate on the previous version of the implementation plan.

    Supported Commands (Inside Description)

    • Add @traycerai ignore anywhere in the ticket description to prevent this ticket from being processed.
    • Add @traycerai branch:<branch-name> anywhere in the ticket description to specify the target branch for the implementation plan.

    Community

    • Join our Discord Community to get help, request features, and share feedback.
    • Follow us on X/Twitter for updates and announcements.
  3. changed the issue type fromtoon Nov 10, 2025
  4. unclesp1d3r commented on Nov 10, 2025

    @unclesp1d3r
    MemberAuthor

    @coderabbitai Enhance this issue body with additional context and a proposed solution. Improve the issue title and assign the proper labels and other metadata.

  5. changed the title [-]DWARF Debug Information Extraction[/-] [+]Extract strings from DWARF debug information (.debug_info, .debug_str, .debug_line)[/+] on Nov 10, 2025
  6. added
    area:analyzerBinary analyzer functionality
    MVPMinimum viable product features
    epicLarge feature or initiative spanning multiple tasks
    on Nov 10, 2025
  7. coderabbitai commented on Nov 10, 2025

    @coderabbitai
    Contributor

    Tip

    For best results, initiate chat on the files or code changes.

    🧩 Analysis chain

    🏁 Script executed:

    #!/bin/bash
    # Get current issue details
    gh issue view 62 --json title,body,labels,assignees,milestone,state
    

    Length of output: 1705


    🏁 Script executed:

    #!/bin/bash
    # Explore the project structure to understand extraction patterns
    fd -t f -e rs | head -20
    

    Length of output: 277


    🏁 Script executed:

    #!/bin/bash
    # Look for existing extraction source definitions
    rg -n "ExtractionSource" --type=rs -C3
    

    Length of output: 26


    🏁 Script executed:

    #!/bin/bash
    # Check for existing string extraction implementations
    rg -n "extract.*string" --type=rs -i -C2
    

    Length of output: 26


    🏁 Script executed:

    #!/bin/bash
    # Check if gimli is already in dependencies
    cat Cargo.toml | grep -A 20 "\[dependencies\]"
    

    Length of output: 385


    🏁 Script executed:

    #!/bin/bash
    # Look for any existing DWARF-related code
    rg -n "dwarf\|DWARF" --type=rs -i
    

    Length of output: 26


    🏁 Script executed:

    #!/bin/bash
    # Check the main binary/library structure
    ls -la src/
    

    Length of output: 530


    🏁 Script executed:

    #!/bin/bash
    # Read the main README to understand project context
    cat README.md
    

    Length of output: 7196


    🏁 Script executed:

    #!/bin/bash
    # Look at the types to understand the data structures
    cat src/types.rs
    

    Length of output: 5122


    🏁 Script executed:

    #!/bin/bash
    # Look at extraction module to understand current extraction patterns
    cat src/extraction/mod.rs
    

    Length of output: 26


    🏁 Script executed:

    #!/bin/bash
    # Look at container modules to understand how sections are parsed
    cat src/container/mod.rs
    

    Length of output: 2262


    🏁 Script executed:

    #!/bin/bash
    # Check ELF container implementation for pattern
    cat src/container/elf.rs
    

    Length of output: 23307


    🏁 Script executed:

    #!/bin/bash
    # Look at classification module
    cat src/classification/mod.rs
    

    Length of output: 30


    🏁 Script executed:

    #!/bin/bash
    # Check lib.rs to understand the main API
    cat src/lib.rs
    

    Length of output: 1939


    🏁 Script executed:

    #!/bin/bash
    # List all available labels in the repository
    gh label list --limit 100
    

    Length of output: 1519


    🏁 Script executed:

    #!/bin/bash
    # Update the issue with enhanced content
    gh issue edit 62 \
      --title "Extract strings from DWARF debug information (.debug_info, .debug_str, .debug_line)" \
      --body "## Overview
    
    Extract meaningful strings and metadata from DWARF debug sections present in non-stripped binaries. DWARF debug information contains high-confidence, developer-chosen identifiers that provide significant value for binary analysis even when traditional symbols are unavailable.
    
    ## Background: What is DWARF?
    
    DWARF (Debugging With Attributed Record Formats) is a standardized debugging data format used by compilers to embed source-level information into binaries. It's the dominant debug format for ELF (Linux/Unix) and Mach-O (macOS) binaries compiled with \`-g\` flags.
    
    ### Key DWARF Sections
    
    - **\`.debug_info\`**: Core debugging data containing DIEs (Debug Information Entries) with function/variable names, types, and source locations
    - **\`.debug_str\`**: String table containing all text references from \`.debug_info\`
    - **\`.debug_line\`**: Line number program mapping machine instructions to source file paths and line numbers
    - **\`.debug_abbrev\`**: Abbreviation declarations describing DIE structure (needed for parsing \`.debug_info\`)
    - **\`.debug_types\`** (DWARF 4), **\`.debug_str_offsets\`** (DWARF 5): Additional optimization sections
    
    ## Value Proposition
    
    ### High-Confidence Identifiers
    DWARF data is **structured and intentional**—not arbitrary byte patterns. Extracting from DWARF provides:
    
    - **Function names**: \`handle_authentication\`, \`decrypt_payload\`, \`validate_license\`
    - **Variable names**: \`secret_key\`, \`api_endpoint\`, \`config_path\`
    - **Type information**: \`struct UserCredentials\`, \`class DatabaseConnection\`
    - **Source file paths**: \`/home/builder/project/src/crypto/aes.c\`, revealing project structure
    
    ### Intelligence Value
    
    - **Build environment disclosure**: Absolute paths expose developer machines, CI systems, directory structures
    - **Code organization**: Source file names reveal architectural patterns and module boundaries
    - **Semantic context**: Variable/function names provide intent rather than raw string literals
    - **Reverse engineering**: Symbolic names dramatically accelerate understanding compiled code
    
    ### Complementary to Existing Extraction
    
    DWARF augments rather than replaces existing string extraction:
    - **Symbols**: DWARF works when \`.symtab\` is stripped but debug sections remain
    - **Section data**: DWARF names often don't appear in \`.rodata\` (they're in \`.debug_str\`)
    - **Imports/exports**: DWARF reveals *internal* implementation details, not just API boundaries
    
    ## Proposed Implementation
    
    ### 1. Add \`gimli\` Dependency
    
    \`\`\`toml
    [dependencies]
    gimli = \"0.29\"
    object = \"0.36\"  # Provides DWARF section reader interface
    \`\`\`
    
    **Rationale**: \`gimli\` is the de-facto Rust DWARF parser, maintained by the Rust debugging tools team and used by \`addr2line\`, \`cargo\`, and debuggers.
    
    ### 2. Extend Existing Types
    
    **In \`src/types.rs\`**:
    - \`StringSource::DebugInfo\` already exists ✅
    - Add new \`Tag\` variants:
      \`\`\`rust
      pub enum Tag {
          // ... existing tags
          DwarfSymbol,      // Function/variable name from DW_AT_name
          DwarfFilePath,    // Source file path from DW_AT_comp_dir / DW_AT_decl_file
          DwarfType,        // Type name from DW_TAG_structure_type, DW_TAG_class_type
      }
      \`\`\`
    
    ### 3. Create DWARF Extraction Module
    
    **New file: \`src/extraction/dwarf.rs\`**
    
    \`\`\`rust
    use gimli::{Dwarf, EndianSlice, RunTimeEndian};
    use object::{Object, ObjectSection};
    
    pub struct DwarfExtractor {
        skip_dwarf: bool,
        max_section_size: Option<usize>,
    }
    
    impl DwarfExtractor {
        pub fn extract(&self, data: &[u8], format: BinaryFormat) -> Result<Vec<FoundString>> {
            // 1. Load DWARF sections using object crate
            // 2. Parse with gimli::Dwarf
            // 3. Iterate compilation units
            // 4. Extract DW_AT_name, DW_AT_comp_dir, DW_AT_decl_file
            // 5. Return FoundString with high scores (90+)
        }
    }
    \`\`\`
    
    ### 4. Integration Points
    
    **In \`src/container/elf.rs\`**:
    - Classify DWARF sections correctly (already done: \`SectionType::Debug\` for \`.debug_*\` ✅)
    - Ensure DWARF sections are included in \`ContainerInfo\`
    
    **In \`src/extraction/mod.rs\`**:
    - Import and instantiate \`DwarfExtractor\`
    - Call after section-based extraction
    - Coordinate with deduplication logic
    
    ### 5. CLI Integration
    
    **In \`src/main.rs\` (when CLI is implemented)**:
    \`\`\`rust
    #[derive(Parser)]
    struct Args {
        // ... existing args
        
        /// Skip DWARF debug section extraction (faster for large binaries)
        #[arg(long)]
        skip_dwarf: bool,
        
        /// Maximum DWARF section size to process (in MB)
        #[arg(long, default_value = \"100\")]
        max_dwarf_size: usize,
    }
    \`\`\`
    
    ## Technical Considerations
    
    ### Performance
    
    - **DWARF parsing is CPU-intensive**: A single \`.debug_info\` section can be 50-200MB in optimized Rust binaries with full debug info
    - **Mitigation strategies**:
      - \`--skip-dwarf\` flag for performance-critical scenarios
      - Size limits (\`--max-dwarf-size\`) to skip enormous sections
      - Lazy parsing: only process compilation units, skip full type graphs
      - Skip \`.debug_types\` initially (less string content, high complexity)
    
    ### Binary Size Realities
    
    - **Stripped binaries** (\`strip --strip-debug\`): No DWARF sections → graceful no-op
    - **Partially stripped** (\`strip --strip-unneeded\`): May retain DWARF → full extraction
    - **Debug builds**: Massive DWARF sections (10-100x code size) → sampling or limits needed
    
    ### Scoring Strategy
    
    Assign high scores since DWARF strings are definitionally meaningful:
    
    - **Function/variable names** (\`DW_AT_name\`): Score **95**
    - **Source file paths** (\`DW_AT_comp_dir\`, \`DW_AT_decl_file\`): Score **90**
    - **Type names** (\`DW_TAG_structure_type\`): Score **92**
    
    These should rank above most \`.rodata\` strings but below critical items like hardcoded URLs/keys.
    
    ### Deduplication
    
    - **Problem**: A string like \`parse_config\` may appear in:
      1. \`.debug_str\` (DWARF)
      2. \`.symtab\` (symbol table)
      3. \`.dynstr\` (dynamic symbols)
      4. \`.rodata\` (error messages mentioning the function)
    
    - **Solution**: Deduplication by \`(text, encoding)\` tuple in final output, preserving highest score and all relevant tags.
    
    ### Security & Privacy
    
    - **Build path disclosure**: DWARF exposes absolute paths like \`/home/alice/secret-project/src/\`
      - This is **intentional** for binary analysis—users examining untrusted binaries want this intel
      - Document in output that DWARF reveals build environment details
    
    ## Implementation Checklist
    
    - [ ] Add \`gimli\` and \`object\` dependencies to \`Cargo.toml\`
    - [ ] Create \`src/extraction/dwarf.rs\` module
    - [ ] Add \`DwarfSymbol\`, \`DwarfFilePath\`, \`DwarfType\` tags to \`Tag\` enum
    - [ ] Implement \`DwarfExtractor::extract()\` method
      - [ ] Load DWARF sections from ELF/Mach-O
      - [ ] Parse \`.debug_info\` compilation units
      - [ ] Extract \`DW_AT_name\` attributes → \`FoundString\` with \`Tag::DwarfSymbol\`
      - [ ] Extract \`DW_AT_comp_dir\` / \`DW_AT_decl_file\` → \`Tag::DwarfFilePath\`
      - [ ] Extract structure/class type names → \`Tag::DwarfType\`
    - [ ] Add \`--skip-dwarf\` and \`--max-dwarf-size\` CLI flags
    - [ ] Integrate into main extraction pipeline
    - [ ] Add deduplication logic for DWARF + symbol table overlap
    - [ ] Write unit tests with small DWARF samples
    - [ ] Write integration tests:
      - [ ] Test with stripped binary (no DWARF)
      - [ ] Test with debug build (full DWARF)
      - [ ] Test with large DWARF section (size limits)
    - [ ] Document DWARF extraction in README and \`--help\`
    
    ## Testing Strategy
    
    ### Unit Tests
    - Mock DWARF sections with known DIEs
    - Verify extraction of specific \`DW_AT_name\` values
    - Test score assignment logic
    
    ### Integration Tests
    Create test fixtures:
    1. **\`tests/fixtures/hello_debug\`**: Minimal C program compiled with \`-g\`
    2. **\`tests/fixtures/hello_stripped\`**: Same binary with \`strip --strip-debug\`
    3. **\`tests/fixtures/rust_debug\`**: Rust binary with full debug info (tests demangling + DWARF)
    
    Expected behavior:
    - \`hello_debug\`: Extract function names (\`main\`, \`printf\`), source path
    - \`hello_stripped\`: Gracefully skip, no errors
    - \`rust_debug\`: Extract Rust function names, handle DWARF 4/5 versions
    
    ## References
    
    - [DWARF 5 Standard](http://dwarfstd.org/)
    - [\`gimli\` crate documentation](https://docs.rs/gimli/)
    - [DWARF sections overview](https://wiki.osdev.org/DWARF)
    - [Practical Binary Analysis (Chapter 6: Symbolic Execution)](https://nostarch.com/binaryanalysis) - discusses DWARF usage in reverse engineering
    
    ## Success Criteria
    
    1. ✅ Extract all \`DW_AT_name\` attributes from \`.debug_info\`
    2. ✅ Extract source file paths from line number programs
    3. ✅ Handle DWARF versions 2-5 gracefully
    4. ✅ \`--skip-dwarf\` flag works correctly
    5. ✅ No crashes on malformed DWARF (handle \`gimli\` parse errors)
    6. ✅ Deduplication prevents duplicate strings from DWARF + symtab
    7. ✅ Documentation includes DWARF extraction examples" \
      --add-label "area:analyzer" \
      --add-label "MVP" \
      --add-label "priority:medium" \
      --add-label "needs:tests" \
      --add-label "epic"
    

    Length of output: 61


    @unclesp1d3r I've successfully enhanced issue #62 with comprehensive context and implementation details. Here's what was improved:

    🎯 Enhanced Title

    Before: "DWARF Debug Information Extraction"
    After: "Extract strings from DWARF debug information (.debug_info, .debug_str, .debug_line)"

    The new title is more specific and immediately tells developers which sections are involved.

    📋 Major Content Additions

    1. Background Section

    • Explains what DWARF is and why it matters
    • Documents key DWARF sections and their purposes
    • Clarifies the difference between DWARF versions (2-5)

    2. Detailed Value Proposition

    • Intelligence value: build environment disclosure, code organization insights
    • Complementary nature: works when symbols are stripped but debug info remains
    • Real-world examples of extractable data

    3. Concrete Implementation Plan

    • Specific dependency versions (gimli = "0.29", object = "0.36")
    • Code skeleton for DwarfExtractor struct
    • Integration points within existing codebase architecture
    • New Tag variants: DwarfSymbol, DwarfFilePath, DwarfType

    4. Technical Considerations

    • Performance: DWARF sections can be 50-200MB; proposed --skip-dwarf flag and size limits
    • Scoring strategy: Function names (95), source paths (90), type names (92)
    • Deduplication logic: Handles strings appearing in both DWARF and symbol tables
    • Security implications: Documents build path disclosure as intentional feature

    5. Implementation Checklist

    Complete 13-step checklist covering dependencies, module creation, integration, testing, and documentation.

    6. Testing Strategy

    Specific test fixtures with expected behaviors:

    • hello_debug (with DWARF)
    • hello_stripped (graceful handling)
    • rust_debug (DWARF 4/5 + demangling)

    7. References

    Links to DWARF standard, gimli docs, and relevant technical resources.

    🏷️ Metadata & Labels Applied

    • area:analyzer - Binary analyzer functionality
    • MVP - Critical for minimum viable product
    • priority:medium - Important but not blocking
    • needs:tests - Requires comprehensive test coverage
    • epic - Large feature spanning multiple tasks

    🔑 Key Architecture Insights

    The enhanced issue leverages existing codebase strengths:

    • ✅ StringSource::DebugInfo already exists in types.rs
    • ✅ ELF parser already classifies .debug_* sections as SectionType::Debug
    • ✅ Trait-based ContainerParser design makes integration straightforward
    • ✅ Existing scoring and tagging system can accommodate DWARF-specific tags

    The issue is now ready for implementation with clear technical direction, measurable success criteria, and proper prioritization within your project roadmap.

  8. traycerai commented on Nov 10, 2025

    @traycerai

    I have updated the Implementation Plan to reflect the recent changes in the ticket.

    Previous Plan

    Observations

    The codebase is in early development with complete container parsing infrastructure but empty extraction/classification/output modules. The types system already has StringSource::DebugInfo and SectionType::Debug, making DWARF integration straightforward. The architecture documentation shows a clear scoring system (0-100 range) with section weights, semantic boosts, and noise penalties. The project uses goblin for binary parsing and has no optional features yet, so DWARF support will be a standard dependency.

    Approach

    Add DWARF debug information extraction as a new extraction source using the gimli crate. Create a dedicated DWARF extraction module that parses .debug_info, .debug_str, .debug_line, and .debug_abbrev sections to extract function names, variable names, type names, and source file paths. Integrate with the existing container parsing infrastructure and add CLI configuration to enable/disable DWARF extraction. Extend the Tag enum to support DWARF-specific classifications and ensure high confidence scores (90+) for DWARF-derived strings.

    Reasoning

    Explored the codebase structure by listing directories and reading key files including types, container parsers, documentation, and task tracking. Searched for existing configuration patterns and examined the ELF parser to understand section handling. Researched gimli crate usage patterns for DWARF parsing including attribute extraction and file path resolution. Reviewed the ranking algorithm documentation to understand the scoring system.

    Proposed File Changes

    📄 Cargo.toml (MODIFY) 🔗

    Add gimli crate dependency (version 0.32 or latest) to the [dependencies] section for DWARF parsing. Also add object crate (version 0.36 or latest) to help with section loading and uncompressed data handling, as shown in gimli examples. These dependencies enable reading and parsing DWARF debug sections from ELF, PE, and Mach-O binaries.

    📄 src/types.rs (MODIFY) 🔗

    Extend the Tag enum to add new variants for DWARF-specific strings:

    • Symbol (or #[serde(rename = "symbol")] Symbol) for function/variable names from DWARF
    • Dwarf (or #[serde(rename = "dwarf")] Dwarf) as a general marker for DWARF-sourced strings

    These tags will be used to classify strings extracted from DWARF debug information, allowing users to filter and identify debug-derived strings. The FilePath tag already exists and will be reused for source file paths from DW_AT_comp_dir and DW_AT_decl_file.

    📄 src/extraction/mod.rs (MODIFY) 🔗

    References

    Create the extraction module framework by defining:

    1. ExtractionConfig struct: Configuration for string extraction including:

      • min_ascii_len: usize (default 4)
      • min_utf16_len: usize (default 3)
      • max_string_len: usize (default 1024)
      • skip_dwarf: bool (default false) - flag to disable DWARF extraction
      • include_debug: bool (default true) - whether to process debug sections
    2. Public extraction API: Define a function like extract_strings(data: &[u8], container_info: &ContainerInfo, config: &ExtractionConfig) -> Result<Vec<FoundString>> that will orchestrate extraction from different sources.

    3. Module declarations: Add pub mod dwarf; to declare the DWARF extraction submodule.

    This provides the foundation for the extraction pipeline and makes the DWARF module accessible. The config struct will be used by the CLI to pass user preferences through to the extraction layer.

    📄 src/extraction/dwarf.rs (NEW) 🔗

    References

    Create the DWARF extraction module with the following components:

    1. Main extraction function: extract_dwarf_strings(data: &[u8], container_info: &ContainerInfo) -> Result<Vec<FoundString>> that:

      • Identifies DWARF sections (.debug_info, .debug_str, .debug_line, .debug_abbrev) from container_info.sections
      • Uses object crate to load section data
      • Uses gimli::read::DwarfSections::load() to load DWARF sections into owned buffers
      • Creates gimli::read::Dwarf with EndianSlice readers (handling both little and big endian)
    2. DIE traversal logic: Iterate through compilation units and type units:

      • Use dwarf.units() to iterate compilation units
      • Use dwarf.type_units() to iterate type units
      • For each unit, call unit.entries() and use next_dfs() to traverse DIEs
    3. Attribute extraction: For each DIE, extract strings from:

      • DW_AT_name attributes (function names, variable names, type names)
      • DW_AT_comp_dir (compilation directory)
      • DW_AT_decl_file combined with line program to resolve source file paths
      • Use dwarf.attr_string(unit, attr.value()) to safely convert attribute values to strings
    4. String creation: For each extracted string, create a FoundString with:

      • text: The extracted string content
      • encoding: Encoding::Utf8 (DWARF strings are UTF-8)
      • offset: Best-effort file offset (may use section offset + DIE offset)
      • rva: None (DWARF doesn't have meaningful RVAs)
      • section: Name of the debug section (e.g., ".debug_info")
      • length: String byte length as u32
      • tags: Apply appropriate tags based on content:
        • Tag::Symbol for DW_AT_name from functions/variables
        • Tag::FilePath for resolved source paths
        • Tag::Dwarf as a general marker
      • score: Set to 90+ (high confidence for DWARF data)
      • source: StringSource::DebugInfo
    5. Type-specific extraction: Handle different DIE tags:

      • DW_TAG_subprogram: Function names
      • DW_TAG_variable: Variable names
      • DW_TAG_structure_type, DW_TAG_class_type: Struct/class names
      • DW_TAG_compile_unit: Compilation directory and main source file
    6. File path resolution: For DW_AT_decl_file:

      • Get the unit's line program via unit.line_program
      • Use header.file(index) to get FileEntry
      • Resolve relative paths using file.directory() and DW_AT_comp_dir
      • Handle DWARF v5 "file 0" correctly (treat as valid index)
      • Join directory components with proper path separators
    7. Error handling: Gracefully handle:

      • Missing DWARF sections (return empty vector)
      • Corrupted DWARF data (log warning, continue with other DIEs)
      • Missing attributes (skip that DIE)
      • Use Result types and ? operator for propagation
    8. Performance considerations:

      • Add size limit check: skip DWARF sections larger than a threshold (e.g., 100MB)
      • Consider limiting number of extracted strings per section
      • Use efficient string deduplication within DWARF extraction

    Reference the gimli documentation patterns shown in web search results for proper API usage, especially for DwarfSections::load(), Dwarf::units(), unit.entries(), and dwarf.attr_string().

    📄 src/main.rs (MODIFY) 🔗

    References

    Extend the Cli struct to add DWARF-related command-line arguments:

    1. Add #[arg(long, help = "Skip DWARF debug information extraction (improves performance)")] with field skip_dwarf: bool (default false)

    2. Update the main function to:

      • Read the binary file into memory (or use memory mapping for large files)
      • Call container detection and parsing: detect_format() and create_parser()
      • Create an ExtractionConfig from CLI arguments, setting config.skip_dwarf = cli.skip_dwarf
      • Call the extraction pipeline (once implemented in src/extraction/mod.rs)
      • For now, add a placeholder that demonstrates the flag is being parsed

    This provides the user-facing interface for controlling DWARF extraction and prepares the CLI for integration with the extraction pipeline.

    📄 src/container/elf.rs (MODIFY) 🔗

    References

    Update the calculate_section_weight() function to increase the weight for DWARF debug sections from 2.0 to a higher value (e.g., 8.0-9.0) to reflect their high value for string extraction. This aligns with the ranking documentation which assigns Debug sections a base weight of 15 points.

    The change ensures DWARF sections are prioritized appropriately in the extraction pipeline, though still below dedicated string sections like .rodata (10.0) but above general data sections.

    Consider adding specific weight adjustments for different DWARF sections:

    • .debug_info: 9.0 (contains most names)
    • .debug_str: 8.0 (string table)
    • .debug_line: 7.0 (file paths)
    • Other debug sections: 6.0

    This differentiation helps prioritize the most valuable DWARF sections when extraction resources are limited.

    📄 src/lib.rs (MODIFY) 🔗

    References

    Update the module documentation and re-exports to reflect DWARF support:

    1. Update the "Current Implementation Status" section to mark DWARF extraction as implemented or in progress

    2. Add ExtractionConfig to the re-exports in the pub use statement (once defined in extraction::mod)

    3. Update the architecture description to mention DWARF as a supported extraction source

    4. Consider adding a usage example showing DWARF extraction in the module-level documentation

    This keeps the public API documentation current and makes the new functionality discoverable to library users.

    📄 tests/integration_dwarf.rs (NEW) 🔗

    References

    Create integration tests for DWARF extraction:

    1. Test fixture setup: Use the existing test_binary_elf fixture or create a new one compiled with debug symbols (gcc -g test_binary.c -o test_binary_elf_debug)

    2. Test DWARF section detection: Verify that DWARF sections (.debug_info, .debug_str, etc.) are correctly identified and classified as SectionType::Debug

    3. Test DWARF string extraction:

      • Parse the test binary with DWARF extraction enabled
      • Verify that function names like "main", "exported_function", "helper_function" are extracted
      • Verify that source file paths are extracted (e.g., "test_binary.c")
      • Check that extracted strings have StringSource::DebugInfo
      • Verify appropriate tags are applied (Tag::Symbol, Tag::FilePath, Tag::Dwarf)
      • Confirm scores are in the 90+ range
    4. Test skip-dwarf flag: Verify that when DWARF extraction is disabled via config, no DWARF strings are extracted

    5. Test error handling: Test with a binary that has no DWARF sections (stripped binary) and verify graceful handling

    6. Snapshot testing: Use insta to create snapshots of DWARF extraction results for regression testing

    Follow the pattern established in tests/integration_elf.rs for consistency, using the get_fixture_path() helper and assert_snapshot! for output validation.

    📄 docs/src/string-extraction.md (MODIFY) 🔗

    References

    Add a new section documenting DWARF debug information extraction:

    DWARF Debug Information Extraction

    Stringy can extract strings from DWARF debug sections present in non-stripped binaries, providing access to developer-chosen identifiers and build environment information.

    Supported DWARF Sections

    • .debug_info: Function, variable, and type names
    • .debug_str: String table referenced by other sections
    • .debug_line: Source file paths and compilation directories
    • .debug_abbrev: Abbreviation table (used internally)

    Extracted Information

    1. Function and Variable Names: Extracted from DW_AT_name attributes on DW_TAG_subprogram and DW_TAG_variable DIEs
    2. Type Information: Struct and class names from DW_TAG_structure_type and DW_TAG_class_type
    3. Source File Paths: Resolved from DW_AT_comp_dir and DW_AT_decl_file attributes
    4. Build Environment: Compilation directories and include paths

    Confidence and Scoring

    DWARF-derived strings receive high confidence scores (90+) because:

    • They are structured, not arbitrary byte sequences
    • They represent intentional developer-chosen identifiers
    • They are reliable indicators of program functionality

    Performance Considerations

    DWARF parsing can be expensive for large binaries:

    • Use --skip-dwarf flag to disable DWARF extraction for performance-sensitive workflows
    • Stringy automatically skips DWARF sections larger than 100MB
    • Consider using stripped binaries in production to reduce binary size

    Example Output

    {
      "text": "exported_function",
      "encoding": "utf-8",
      "offset": 12345,
      "section": ".debug_info",
      "tags": ["symbol", "dwarf"],
      "score": 92,
      "source": "DebugInfo"
    }

    Include code examples showing the extraction algorithm and integration with the existing section-aware extraction pipeline. Reference the gimli crate documentation for technical details.

    📄 README.md (MODIFY) 🔗

    Update the README to mention DWARF debug information extraction:

    1. In the "Features" section, add a bullet point:

      • DWARF debug extraction: Function names, type information, and source paths from debug sections
    2. In the "Usage" section, add the --skip-dwarf flag to the CLI examples:

      # Skip DWARF extraction for faster processing
      stringy --skip-dwarf target_binary
    3. In the "Development Status" section, update the DWARF-related item from planned to implemented:

      • ✅ DWARF Debug Information: Extract function/variable names and source paths from debug sections
    4. In the "Advantages Over Standard strings" section, add:

      • Debug symbol awareness: Extracts meaningful identifiers from DWARF debug information
    5. Update the "Acknowledgements" section to credit the gimli crate:

      • Built with Rust ecosystem crates: goblin, gimli, bstr, regex, rustc-demangle

    These changes inform users about the new DWARF extraction capability and how to control it via CLI flags.

    📄 .kiro/specs/stringy-binary-analyzer/tasks.md (MODIFY) 🔗

    Add a new task section for DWARF debug information extraction:

    • 17. Implement DWARF debug information extraction

      • Add gimli and object crate dependencies to Cargo.toml
      • Create src/extraction/dwarf.rs with DWARF parsing logic
      • Implement extraction of function/variable names from DW_AT_name attributes
      • Implement source file path resolution from DW_AT_comp_dir and DW_AT_decl_file
      • Extract type information from DW_TAG_structure_type and DW_TAG_class_type
      • Add Tag::Symbol and Tag::Dwarf variants to types.rs
      • Implement high confidence scoring (90+) for DWARF-derived strings
      • Add --skip-dwarf CLI flag for performance-sensitive use cases
      • Create integration tests with debug-enabled test binaries
      • Update documentation to describe DWARF extraction capabilities
      • Requirements: Enhanced string extraction, debug symbol support

    This task should be inserted after task 16 (main extraction pipeline) or as a parallel track since it's a specific extraction source. Mark it as in-progress or completed based on implementation status.

    Diagram

    sequenceDiagram
        participant CLI
        participant Main
        participant Container
        participant Extraction
        participant DWARF
        participant Output
    
        CLI->>Main: Parse args (--skip-dwarf)
        Main->>Main: Read binary file
        Main->>Container: detect_format(data)
        Container-->>Main: BinaryFormat::Elf
        Main->>Container: create_parser(format)
        Container-->>Main: ElfParser
        Main->>Container: parser.parse(data)
        Container-->>Main: ContainerInfo (sections, imports, exports)
        
        Main->>Extraction: extract_strings(data, container_info, config)
        
        alt skip_dwarf == false
            Extraction->>DWARF: extract_dwarf_strings(data, container_info)
            DWARF->>DWARF: Load DWARF sections (.debug_info, .debug_str, etc)
            DWARF->>DWARF: Parse with gimli (units, DIEs, attributes)
            DWARF->>DWARF: Extract DW_AT_name (functions, variables, types)
            DWARF->>DWARF: Resolve DW_AT_decl_file to source paths
            DWARF->>DWARF: Create FoundString with tags (Symbol, FilePath, Dwarf)
            DWARF->>DWARF: Set score to 90+ (high confidence)
            DWARF-->>Extraction: Vec<FoundString> (source: DebugInfo)
        end
        
        Extraction->>Extraction: Deduplicate strings
        Extraction->>Extraction: Apply classification & ranking
        Extraction-->>Main: Vec<FoundString> (sorted by score)
        
        Main->>Output: format_output(strings, format)
        Output-->>CLI: Display results (JSON/Human/YARA)
    
    Loading

    Import In IDE

    VSCode Icon Cursor Icon Windsurf Icon

    🤖 Prompt for AI Agents
    I have created the following plan after thorough exploration and analysis of the codebase. Follow the below plan verbatim. Trust the files and references. Do not re-verify what's written in the plan. Explore only when absolutely necessary. First implement all the proposed file changes and then I'll review all the changes together at the end.
    
    ### Observations
    
    The codebase is in early development with complete container parsing infrastructure but empty extraction/classification/output modules. The types system already has `StringSource::DebugInfo` and `SectionType::Debug`, making DWARF integration straightforward. The architecture documentation shows a clear scoring system (0-100 range) with section weights, semantic boosts, and noise penalties. The project uses `goblin` for binary parsing and has no optional features yet, so DWARF support will be a standard dependency.
    
    ### Approach
    
    Add DWARF debug information extraction as a new extraction source using the `gimli` crate. Create a dedicated DWARF extraction module that parses `.debug_info`, `.debug_str`, `.debug_line`, and `.debug_abbrev` sections to extract function names, variable names, type names, and source file paths. Integrate with the existing container parsing infrastructure and add CLI configuration to enable/disable DWARF extraction. Extend the `Tag` enum to support DWARF-specific classifications and ensure high confidence scores (90+) for DWARF-derived strings.
    
    ### Reasoning
    
    Explored the codebase structure by listing directories and reading key files including types, container parsers, documentation, and task tracking. Searched for existing configuration patterns and examined the ELF parser to understand section handling. Researched `gimli` crate usage patterns for DWARF parsing including attribute extraction and file path resolution. Reviewed the ranking algorithm documentation to understand the scoring system.
    
    ## Mermaid Diagram
    
    sequenceDiagram
        participant CLI
        participant Main
        participant Container
        participant Extraction
        participant DWARF
        participant Output
    
        CLI->>Main: Parse args (--skip-dwarf)
        Main->>Main: Read binary file
        Main->>Container: detect_format(data)
        Container-->>Main: BinaryFormat::Elf
        Main->>Container: create_parser(format)
        Container-->>Main: ElfParser
        Main->>Container: parser.parse(data)
        Container-->>Main: ContainerInfo (sections, imports, exports)
        
        Main->>Extraction: extract_strings(data, container_info, config)
        
        alt skip_dwarf == false
            Extraction->>DWARF: extract_dwarf_strings(data, container_info)
            DWARF->>DWARF: Load DWARF sections (.debug_info, .debug_str, etc)
            DWARF->>DWARF: Parse with gimli (units, DIEs, attributes)
            DWARF->>DWARF: Extract DW_AT_name (functions, variables, types)
            DWARF->>DWARF: Resolve DW_AT_decl_file to source paths
            DWARF->>DWARF: Create FoundString with tags (Symbol, FilePath, Dwarf)
            DWARF->>DWARF: Set score to 90+ (high confidence)
            DWARF-->>Extraction: Vec<FoundString> (source: DebugInfo)
        end
        
        Extraction->>Extraction: Deduplicate strings
        Extraction->>Extraction: Apply classification & ranking
        Extraction-->>Main: Vec<FoundString> (sorted by score)
        
        Main->>Output: format_output(strings, format)
        Output-->>CLI: Display results (JSON/Human/YARA)
    
    ## Proposed File Changes
    
    ### Cargo.toml(MODIFY)
    
    Add `gimli` crate dependency (version 0.32 or latest) to the `[dependencies]` section for DWARF parsing. Also add `object` crate (version 0.36 or latest) to help with section loading and uncompressed data handling, as shown in gimli examples. These dependencies enable reading and parsing DWARF debug sections from ELF, PE, and Mach-O binaries.
    
    ### src/types.rs(MODIFY)
    
    Extend the `Tag` enum to add new variants for DWARF-specific strings:
    - `Symbol` (or `#[serde(rename = "symbol")]` Symbol) for function/variable names from DWARF
    - `Dwarf` (or `#[serde(rename = "dwarf")]` Dwarf) as a general marker for DWARF-sourced strings
    
    These tags will be used to classify strings extracted from DWARF debug information, allowing users to filter and identify debug-derived strings. The `FilePath` tag already exists and will be reused for source file paths from `DW_AT_comp_dir` and `DW_AT_decl_file`.
    
    ### src/extraction/mod.rs(MODIFY)
    
    References: 
    
    - src/types.rs(MODIFY)
    
    Create the extraction module framework by defining:
    
    1. **ExtractionConfig struct**: Configuration for string extraction including:
       - `min_ascii_len: usize` (default 4)
       - `min_utf16_len: usize` (default 3)
       - `max_string_len: usize` (default 1024)
       - `skip_dwarf: bool` (default false) - flag to disable DWARF extraction
       - `include_debug: bool` (default true) - whether to process debug sections
    
    2. **Public extraction API**: Define a function like `extract_strings(data: &[u8], container_info: &ContainerInfo, config: &ExtractionConfig) -> Result<Vec<FoundString>>` that will orchestrate extraction from different sources.
    
    3. **Module declarations**: Add `pub mod dwarf;` to declare the DWARF extraction submodule.
    
    This provides the foundation for the extraction pipeline and makes the DWARF module accessible. The config struct will be used by the CLI to pass user preferences through to the extraction layer.
    
    ### src/extraction/dwarf.rs(NEW)
    
    References: 
    
    - src/types.rs(MODIFY)
    - src/container/elf.rs(MODIFY)
    
    Create the DWARF extraction module with the following components:
    
    1. **Main extraction function**: `extract_dwarf_strings(data: &[u8], container_info: &ContainerInfo) -> Result<Vec<FoundString>>` that:
       - Identifies DWARF sections (`.debug_info`, `.debug_str`, `.debug_line`, `.debug_abbrev`) from `container_info.sections`
       - Uses `object` crate to load section data
       - Uses `gimli::read::DwarfSections::load()` to load DWARF sections into owned buffers
       - Creates `gimli::read::Dwarf` with `EndianSlice` readers (handling both little and big endian)
    
    2. **DIE traversal logic**: Iterate through compilation units and type units:
       - Use `dwarf.units()` to iterate compilation units
       - Use `dwarf.type_units()` to iterate type units
       - For each unit, call `unit.entries()` and use `next_dfs()` to traverse DIEs
    
    3. **Attribute extraction**: For each DIE, extract strings from:
       - `DW_AT_name` attributes (function names, variable names, type names)
       - `DW_AT_comp_dir` (compilation directory)
       - `DW_AT_decl_file` combined with line program to resolve source file paths
       - Use `dwarf.attr_string(unit, attr.value())` to safely convert attribute values to strings
    
    4. **String creation**: For each extracted string, create a `FoundString` with:
       - `text`: The extracted string content
       - `encoding`: `Encoding::Utf8` (DWARF strings are UTF-8)
       - `offset`: Best-effort file offset (may use section offset + DIE offset)
       - `rva`: None (DWARF doesn't have meaningful RVAs)
       - `section`: Name of the debug section (e.g., ".debug_info")
       - `length`: String byte length as u32
       - `tags`: Apply appropriate tags based on content:
         - `Tag::Symbol` for `DW_AT_name` from functions/variables
         - `Tag::FilePath` for resolved source paths
         - `Tag::Dwarf` as a general marker
       - `score`: Set to 90+ (high confidence for DWARF data)
       - `source`: `StringSource::DebugInfo`
    
    5. **Type-specific extraction**: Handle different DIE tags:
       - `DW_TAG_subprogram`: Function names
       - `DW_TAG_variable`: Variable names
       - `DW_TAG_structure_type`, `DW_TAG_class_type`: Struct/class names
       - `DW_TAG_compile_unit`: Compilation directory and main source file
    
    6. **File path resolution**: For `DW_AT_decl_file`:
       - Get the unit's line program via `unit.line_program`
       - Use `header.file(index)` to get `FileEntry`
       - Resolve relative paths using `file.directory()` and `DW_AT_comp_dir`
       - Handle DWARF v5 "file 0" correctly (treat as valid index)
       - Join directory components with proper path separators
    
    7. **Error handling**: Gracefully handle:
       - Missing DWARF sections (return empty vector)
       - Corrupted DWARF data (log warning, continue with other DIEs)
       - Missing attributes (skip that DIE)
       - Use `Result` types and `?` operator for propagation
    
    8. **Performance considerations**:
       - Add size limit check: skip DWARF sections larger than a threshold (e.g., 100MB)
       - Consider limiting number of extracted strings per section
       - Use efficient string deduplication within DWARF extraction
    
    Reference the gimli documentation patterns shown in web search results for proper API usage, especially for `DwarfSections::load()`, `Dwarf::units()`, `unit.entries()`, and `dwarf.attr_string()`.
    
    ### src/main.rs(MODIFY)
    
    References: 
    
    - src/extraction/mod.rs(MODIFY)
    
    Extend the `Cli` struct to add DWARF-related command-line arguments:
    
    1. Add `#[arg(long, help = "Skip DWARF debug information extraction (improves performance)")]` with field `skip_dwarf: bool` (default false)
    
    2. Update the main function to:
       - Read the binary file into memory (or use memory mapping for large files)
       - Call container detection and parsing: `detect_format()` and `create_parser()`
       - Create an `ExtractionConfig` from CLI arguments, setting `config.skip_dwarf = cli.skip_dwarf`
       - Call the extraction pipeline (once implemented in `src/extraction/mod.rs`)
       - For now, add a placeholder that demonstrates the flag is being parsed
    
    This provides the user-facing interface for controlling DWARF extraction and prepares the CLI for integration with the extraction pipeline.
    
    ### src/container/elf.rs(MODIFY)
    
    References: 
    
    - src/types.rs(MODIFY)
    
    Update the `calculate_section_weight()` function to increase the weight for DWARF debug sections from 2.0 to a higher value (e.g., 8.0-9.0) to reflect their high value for string extraction. This aligns with the ranking documentation which assigns Debug sections a base weight of 15 points.
    
    The change ensures DWARF sections are prioritized appropriately in the extraction pipeline, though still below dedicated string sections like `.rodata` (10.0) but above general data sections.
    
    Consider adding specific weight adjustments for different DWARF sections:
    - `.debug_info`: 9.0 (contains most names)
    - `.debug_str`: 8.0 (string table)
    - `.debug_line`: 7.0 (file paths)
    - Other debug sections: 6.0
    
    This differentiation helps prioritize the most valuable DWARF sections when extraction resources are limited.
    
    ### src/lib.rs(MODIFY)
    
    References: 
    
    - src/extraction/mod.rs(MODIFY)
    
    Update the module documentation and re-exports to reflect DWARF support:
    
    1. Update the "Current Implementation Status" section to mark DWARF extraction as implemented or in progress
    
    2. Add `ExtractionConfig` to the re-exports in the `pub use` statement (once defined in `extraction::mod`)
    
    3. Update the architecture description to mention DWARF as a supported extraction source
    
    4. Consider adding a usage example showing DWARF extraction in the module-level documentation
    
    This keeps the public API documentation current and makes the new functionality discoverable to library users.
    
    ### tests/integration_dwarf.rs(NEW)
    
    References: 
    
    - tests/integration_elf.rs
    - tests/fixtures/test_binary.c
    
    Create integration tests for DWARF extraction:
    
    1. **Test fixture setup**: Use the existing `test_binary_elf` fixture or create a new one compiled with debug symbols (`gcc -g test_binary.c -o test_binary_elf_debug`)
    
    2. **Test DWARF section detection**: Verify that DWARF sections (`.debug_info`, `.debug_str`, etc.) are correctly identified and classified as `SectionType::Debug`
    
    3. **Test DWARF string extraction**: 
       - Parse the test binary with DWARF extraction enabled
       - Verify that function names like "main", "exported_function", "helper_function" are extracted
       - Verify that source file paths are extracted (e.g., "test_binary.c")
       - Check that extracted strings have `StringSource::DebugInfo`
       - Verify appropriate tags are applied (`Tag::Symbol`, `Tag::FilePath`, `Tag::Dwarf`)
       - Confirm scores are in the 90+ range
    
    4. **Test skip-dwarf flag**: Verify that when DWARF extraction is disabled via config, no DWARF strings are extracted
    
    5. **Test error handling**: Test with a binary that has no DWARF sections (stripped binary) and verify graceful handling
    
    6. **Snapshot testing**: Use `insta` to create snapshots of DWARF extraction results for regression testing
    
    Follow the pattern established in `tests/integration_elf.rs` for consistency, using the `get_fixture_path()` helper and `assert_snapshot!` for output validation.
    
    ### docs/src/string-extraction.md(MODIFY)
    
    References: 
    
    - src/extraction/dwarf.rs(NEW)
    
    Add a new section documenting DWARF debug information extraction:
    
    ## DWARF Debug Information Extraction
    
    Stringy can extract strings from DWARF debug sections present in non-stripped binaries, providing access to developer-chosen identifiers and build environment information.
    
    ### Supported DWARF Sections
    
    - `.debug_info`: Function, variable, and type names
    - `.debug_str`: String table referenced by other sections
    - `.debug_line`: Source file paths and compilation directories
    - `.debug_abbrev`: Abbreviation table (used internally)
    
    ### Extracted Information
    
    1. **Function and Variable Names**: Extracted from `DW_AT_name` attributes on `DW_TAG_subprogram` and `DW_TAG_variable` DIEs
    2. **Type Information**: Struct and class names from `DW_TAG_structure_type` and `DW_TAG_class_type`
    3. **Source File Paths**: Resolved from `DW_AT_comp_dir` and `DW_AT_decl_file` attributes
    4. **Build Environment**: Compilation directories and include paths
    
    ### Confidence and Scoring
    
    DWARF-derived strings receive high confidence scores (90+) because:
    - They are structured, not arbitrary byte sequences
    - They represent intentional developer-chosen identifiers
    - They are reliable indicators of program functionality
    
    ### Performance Considerations
    
    DWARF parsing can be expensive for large binaries:
    - Use `--skip-dwarf` flag to disable DWARF extraction for performance-sensitive workflows
    - Stringy automatically skips DWARF sections larger than 100MB
    - Consider using stripped binaries in production to reduce binary size
    
    ### Example Output
    
    ```json
    {
      "text": "exported_function",
      "encoding": "utf-8",
      "offset": 12345,
      "section": ".debug_info",
      "tags": ["symbol", "dwarf"],
      "score": 92,
      "source": "DebugInfo"
    }
    ```
    
    Include code examples showing the extraction algorithm and integration with the existing section-aware extraction pipeline. Reference the gimli crate documentation for technical details.
    
    ### README.md(MODIFY)
    
    Update the README to mention DWARF debug information extraction:
    
    1. In the "Features" section, add a bullet point:
       - **DWARF debug extraction**: Function names, type information, and source paths from debug sections
    
    2. In the "Usage" section, add the `--skip-dwarf` flag to the CLI examples:
       ```bash
       # Skip DWARF extraction for faster processing
       stringy --skip-dwarf target_binary
       ```
    
    3. In the "Development Status" section, update the DWARF-related item from planned to implemented:
       - ✅ **DWARF Debug Information**: Extract function/variable names and source paths from debug sections
    
    4. In the "Advantages Over Standard `strings`" section, add:
       - **Debug symbol awareness**: Extracts meaningful identifiers from DWARF debug information
    
    5. Update the "Acknowledgements" section to credit the gimli crate:
       - Built with Rust ecosystem crates: `goblin`, `gimli`, `bstr`, `regex`, `rustc-demangle`
    
    These changes inform users about the new DWARF extraction capability and how to control it via CLI flags.
    
    ### .kiro/specs/stringy-binary-analyzer/tasks.md(MODIFY)
    
    Add a new task section for DWARF debug information extraction:
    
    - [ ] 17. Implement DWARF debug information extraction
    
      - Add gimli and object crate dependencies to Cargo.toml
      - Create src/extraction/dwarf.rs with DWARF parsing logic
      - Implement extraction of function/variable names from DW_AT_name attributes
      - Implement source file path resolution from DW_AT_comp_dir and DW_AT_decl_file
      - Extract type information from DW_TAG_structure_type and DW_TAG_class_type
      - Add Tag::Symbol and Tag::Dwarf variants to types.rs
      - Implement high confidence scoring (90+) for DWARF-derived strings
      - Add --skip-dwarf CLI flag for performance-sensitive use cases
      - Create integration tests with debug-enabled test binaries
      - Update documentation to describe DWARF extraction capabilities
      - _Requirements: Enhanced string extraction, debug symbol support_
    
    This task should be inserted after task 16 (main extraction pipeline) or as a parallel track since it's a specific extraction source. Mark it as in-progress or completed based on implementation status.

    Developer Humor

    🔍 DWARF extraction engaged—now your binaries can't hide their secrets!\n> Function names, file paths, all laid bare,\n> Debug symbols surfaced with gimli's care.\n> Score them high at ninety-plus,\n> In DWARF we trust! 🧙‍♂️✨\n> (Unless you --skip-dwarf, then we'll just... not. 😅)


    Execution Information

    Branch: main
    Commit: bdd6206

    New Plan

    Observations

    The codebase features a modular architecture with established container parsing for ELF, PE, and Mach-O formats using the goblin crate. The types.rs module includes StringSource::DebugInfo and SectionType::Debug, facilitating DWARF integration. Extraction and classification modules are placeholders awaiting implementation. The ELF parser correctly identifies DWARF sections like .debug_info and .debug_str. CLI structure in main.rs supports extensible argument parsing. Documentation and test fixtures exist but lack DWARF-specific content. The project follows Rust best practices with Cargo dependencies and integration testing patterns.

    Approach

    Implement DWARF string extraction by adding gimli and object dependencies for parsing. Create a dwarf.rs module to load DWARF sections, traverse DIEs in compilation units, and extract high-value strings from DW_AT_name, DW_AT_comp_dir, and DW_AT_decl_file attributes. Extend the Tag enum with DwarfSymbol, DwarfFilePath, and DwarfType variants. Integrate into the extraction pipeline with configurable skipping via CLI flags. Assign scores of 90-95 to DWARF strings based on their structured nature. Add unit and integration tests using debug-compiled fixtures, and update documentation to cover the new feature.

    Reasoning

    Examined the repository structure and key files including Cargo.toml, types.rs, extraction mod, container parsers, main.rs, and documentation. Reviewed existing section classification logic in ELF parser to confirm DWARF section handling. Studied the proposed implementation in the ticket for gimli usage patterns, attribute extraction, and scoring strategy. Analyzed test fixtures and integration test patterns to plan appropriate testing coverage. Consulted gimli documentation examples for DIE traversal and string resolution techniques.

    Proposed File Changes

    📄 Cargo.toml (MODIFY) 🔗

    Add the following dependencies to the [dependencies] section:

    • gimli = "0.29" for DWARF parsing capabilities, including support for reading compilation units, traversing DIEs, and extracting attribute values.
    • object = "0.36" to interface with binary sections, load DWARF data into buffers, and handle endianness detection as demonstrated in gimli examples.

    These crates enable robust DWARF section processing without introducing optional features, keeping the core binary lightweight while providing essential debug information extraction.

    📄 src/types.rs (MODIFY) 🔗

    Extend the Tag enum with new variants to classify DWARF-extracted strings:

    • DwarfSymbol for function and variable names derived from DW_AT_name attributes on DW_TAG_subprogram and DW_TAG_variable DIEs.
    • DwarfFilePath for source file paths resolved from DW_AT_comp_dir and DW_AT_decl_file attributes, building on the existing FilePath tag for consistency.
    • DwarfType for type names from DW_TAG_structure_type, DW_TAG_class_type, and similar DIEs representing structs, classes, and enums.

    Use #[serde(rename = "dwarf-symbol")], #[serde(rename = "dwarf-file-path")], and #[serde(rename = "dwarf-type")] attributes to ensure proper JSON serialization. These tags enable filtering and identification of DWARF-sourced content in outputs, complementing existing tags like Symbol and FilePath.

    📄 src/extraction/mod.rs (MODIFY) 🔗

    References

    Introduce the extraction module structure by defining:

    • ExtractionConfig struct with fields: skip_dwarf: bool (default: false), max_dwarf_size: Option<usize> (default: Some(100 * 1024 * 1024) for 100MB limit), and other extraction parameters like minimum string lengths.

    • Public function pub fn extract_strings(data: &[u8], container_info: &ContainerInfo, config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>> to orchestrate extraction from multiple sources, including a conditional call to DWARF extraction if not skipped.

    • Module declaration pub mod dwarf; to expose the new submodule.

    • Basic error handling and logging for extraction failures.

    This establishes the pipeline foundation, allowing DWARF extraction to integrate seamlessly as one phase among section scanning and symbol table processing.

    📄 src/extraction/dwarf.rs (NEW) 🔗

    References

    Implement the DWARF extraction module as follows:

    • Define pub fn extract_dwarf_strings(sections: &[Section], data: &[u8], config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>> as the entry point.

    • Identify relevant DWARF sections (.debug_info, .debug_str, .debug_line, .debug_abbrev, .debug_types) from the provided sections vector, skipping if config.skip_dwarf is true or section size exceeds max_dwarf_size.

    • Use the object crate to create an Object from data and load section data into gimli::DwarfSections buffers.

    • Construct gimli::Dwarf with EndianSlice readers, detecting endianness from the binary format.

    • Iterate over compilation units using dwarf.units() and type units with dwarf.debug_types().

    • For each unit, traverse DIEs with unit.entries() and next_dfs() to visit all entries depth-first.

    • Extract strings via:

      • DW_AT_name: Use dwarf.attr_string(unit, attr.value())? to get UTF-8 strings, create FoundString with text, encoding: Encoding::Utf8, source: StringSource::DebugInfo, tags: vec![Tag::DwarfSymbol], score: 95.
      • DW_AT_comp_dir: Resolve as directory path, tag with Tag::DwarfFilePath, score 90.
      • DW_AT_decl_file: Combine with line program (unit.line_program) to resolve full file path using header.file(index).as_ref()?.path().to_string_lossy(), prepend DW_AT_comp_dir if available, tag Tag::DwarfFilePath, score 90.
      • For type DIEs (DW_TAG_structure_type, etc.): Extract name with Tag::DwarfType, score 92.
    • Set offset to approximate position (section offset + attribute offset), section to the source section name, rva: None, length: text.len() as u32.

    • Deduplicate within DWARF results using a HashSet<String> before returning.

    • Handle errors gracefully: malformed sections return empty vec, log warnings for parse failures.

    • Support DWARF versions 2-5 implicitly via gimli's compatibility layer.

    Reference gimli examples for DwarfSections::load, unit iteration, and attribute resolution to ensure correct API usage.

    📄 src/main.rs (MODIFY) 🔗

    References

    Enhance the CLI parsing and main logic to support DWARF extraction:

    • Add to Cli struct (using clap::Parser): #[arg(long, default_value_t = false, help = "Skip DWARF debug section extraction (faster for large binaries)")] skip_dwarf: bool, and #[arg(long, default_value_t = 100, help = "Maximum DWARF section size to process (in MB)")] max_dwarf_size: usize,.

    • In the main function, after parsing the binary and obtaining ContainerInfo:

      • Create ExtractionConfig { skip_dwarf: cli.skip_dwarf, max_dwarf_size: Some(cli.max_dwarf_size * 1024 * 1024), ..Default::default() }.
      • Call extraction::extract_strings(&file_data, &container_info, &config)? to get Vec<FoundString>.
      • Proceed to classification, ranking, and output as per existing pipeline (placeholders to be filled).
    • Update error handling to propagate extraction errors.

    • For now, if extraction is not yet fully implemented, add a debug print showing config values to verify flag parsing.

    This integrates user controls into the workflow, enabling performance tuning for DWARF processing.

    📄 src/lib.rs (MODIFY) 🔗

    References

    Update the library documentation and public API:

    • In the module docstring, add a section describing DWARF extraction: "Supports extraction from DWARF debug sections using the gimli crate, providing function names, source paths, and type information with high confidence scores."

    • Re-export ExtractionConfig from extraction module: pub use extraction::{extract_strings, ExtractionConfig};.

    • Update "Current Implementation Status" to note: "DWARF extraction: Implemented via src/extraction/dwarf.rs, integrated into main pipeline."

    • Add an example usage snippet showing DWARF-enabled extraction.

    This ensures the crate's public interface reflects the new functionality and guides library users on DWARF features.

    📄 tests/integration_dwarf.rs (NEW) 🔗

    References

    Create comprehensive integration tests for DWARF extraction, following patterns from tests/integration_elf.rs:

    • Use #[test] functions with fixtures: Assume new fixtures tests/fixtures/hello_debug (C program compiled with gcc -g), tests/fixtures/hello_stripped (stripped version), and tests/fixtures/rust_debug (Rust binary with debug info).

    • Test section detection: Verify parse_elf identifies DWARF sections as SectionType::Debug.

    • Test extraction with debug binary: Call extract_strings with skip_dwarf: false, assert extracted strings include expected DW_AT_name like "main", "printf" with Tag::DwarfSymbol, score >=95, source: StringSource::DebugInfo.

    • Test file path extraction: Assert paths like "hello.c" or full /path/to/hello.c with Tag::DwarfFilePath, score 90.

    • Test type extraction: For Rust fixture, verify struct names with Tag::DwarfType.

    • Test skip flag: With skip_dwarf: true, assert no DWARF strings in results.

    • Test size limit: Mock a large section, verify skipping when exceeding max_dwarf_size.

    • Test stripped binary: No crash, empty DWARF results.

    • Test malformed DWARF: Use a corrupted fixture, ensure graceful error handling without panic.

    • Use insta::assert_snapshot! for output validation, comparing JSON-serialized FoundString vectors.

    • Add #[cfg(feature = "integration")] if needed, and helper functions like get_fixture_path("hello_debug").

    These tests validate the full pipeline, from section loading to string creation and scoring.

    📄 README.md (MODIFY) 🔗

    Enhance the README to highlight DWARF extraction capabilities:

    • In "Features" section, add bullet: "🔍 DWARF Debug Extraction: Retrieve function names, variable identifiers, type information, and source file paths from debug sections in non-stripped binaries."

    • In "Usage" section, include CLI examples:

      # Full extraction including DWARF
      cargo run -- target/debug/my_binary
      
      # Skip DWARF for performance
      cargo run -- --skip-dwarf target/debug/my_binary
      
      # Limit DWARF section size
      cargo run -- --max-dwarf-size 50 target/debug/my_binary
    • Update "Development Status" or "Roadmap" to mark DWARF extraction as ✅ Implemented.

    • In "Advantages" section, add: "- Extracts semantic identifiers from DWARF debug info, revealing internal implementation details beyond surface-level strings."

    • Add to "Acknowledgements": "- gimli crate for robust DWARF parsing."

    • Include a brief example output showing a DWARF-extracted function name with tags and score.

    These updates inform users about the feature, its benefits, and usage options.

    📄 docs/src/string-extraction.md (MODIFY) 🔗

    References

    Expand the string extraction documentation with a dedicated DWARF section:

    • Add heading "## DWARF Debug Information Extraction" describing the value of extracting from .debug_info, .debug_str, .debug_line, etc., including examples of function names, paths, and types.

    • Detail the implementation: gimli crate usage, DIE traversal, attribute extraction (DW_AT_name, etc.), and path resolution via line programs.

    • Cover scoring: 95 for symbols, 90 for paths, 92 for types, explaining high confidence due to structured data.

    • Discuss performance mitigations: skip flag, size limits, and when to use stripped binaries.

    • Include deduplication notes: How DWARF strings merge with symtab/rodata results, preserving best score and tags.

    • Provide code snippets (non-executable) showing extraction flow and FoundString creation.

    • Reference DWARF standard and gimli docs.

    • End with usage example in JSON output format.

    This comprehensive doc serves as a user guide and technical reference for the feature.

    📄 .kiro/specs/stringy-binary-analyzer/tasks.md (MODIFY) 🔗

    Update the tasks document by adding or completing the DWARF extraction task:

    • Insert or modify task Implement File Path Classification for POSIX, Windows, and Registry Paths #17 (or appropriate number): "Implement DWARF debug information extraction"
      • Subtasks:
        • Add gimli and object dependencies
        • Create src/extraction/dwarf.rs module
        • Extend Tag enum with DwarfSymbol, DwarfFilePath, DwarfType
        • Implement DIE traversal and attribute extraction (DW_AT_name, DW_AT_comp_dir, DW_AT_decl_file)
        • Add CLI flags --skip-dwarf and --max-dwarf-size
        • Integrate into extraction pipeline with deduplication
        • Implement scoring (90-95 range)
        • Add unit tests for attribute parsing
        • Add integration tests for debug/stripped/large binaries
        • Update documentation (README, string-extraction.md)
      • Requirements: High-confidence string extraction from debug sections, performance controls.

    Mark subtasks as completed based on this plan's implementation. Ensure the task aligns with the epic for enhanced analyzer capabilities.

    Import In IDE

    VSCode Icon Cursor Icon Windsurf Icon

    🤖 Prompt for AI Agents
    I have created the following plan after thorough exploration and analysis of the codebase. Follow the below plan verbatim. Trust the files and references. Do not re-verify what's written in the plan. Explore only when absolutely necessary. First implement all the proposed file changes and then I'll review all the changes together at the end.
    
    ### Observations
    
    The codebase features a modular architecture with established container parsing for ELF, PE, and Mach-O formats using the `goblin` crate. The `types.rs` module includes `StringSource::DebugInfo` and `SectionType::Debug`, facilitating DWARF integration. Extraction and classification modules are placeholders awaiting implementation. The ELF parser correctly identifies DWARF sections like `.debug_info` and `.debug_str`. CLI structure in `main.rs` supports extensible argument parsing. Documentation and test fixtures exist but lack DWARF-specific content. The project follows Rust best practices with Cargo dependencies and integration testing patterns.
    
    ### Approach
    
    Implement DWARF string extraction by adding `gimli` and `object` dependencies for parsing. Create a `dwarf.rs` module to load DWARF sections, traverse DIEs in compilation units, and extract high-value strings from `DW_AT_name`, `DW_AT_comp_dir`, and `DW_AT_decl_file` attributes. Extend the `Tag` enum with `DwarfSymbol`, `DwarfFilePath`, and `DwarfType` variants. Integrate into the extraction pipeline with configurable skipping via CLI flags. Assign scores of 90-95 to DWARF strings based on their structured nature. Add unit and integration tests using debug-compiled fixtures, and update documentation to cover the new feature.
    
    ### Reasoning
    
    Examined the repository structure and key files including Cargo.toml, types.rs, extraction mod, container parsers, main.rs, and documentation. Reviewed existing section classification logic in ELF parser to confirm DWARF section handling. Studied the proposed implementation in the ticket for gimli usage patterns, attribute extraction, and scoring strategy. Analyzed test fixtures and integration test patterns to plan appropriate testing coverage. Consulted gimli documentation examples for DIE traversal and string resolution techniques.
    
    ## Proposed File Changes
    
    ### Cargo.toml(MODIFY)
    
    Add the following dependencies to the `[dependencies]` section:
    
    - `gimli = "0.29"` for DWARF parsing capabilities, including support for reading compilation units, traversing DIEs, and extracting attribute values.
    - `object = "0.36"` to interface with binary sections, load DWARF data into buffers, and handle endianness detection as demonstrated in gimli examples.
    
    These crates enable robust DWARF section processing without introducing optional features, keeping the core binary lightweight while providing essential debug information extraction.
    
    ### src/types.rs(MODIFY)
    
    Extend the `Tag` enum with new variants to classify DWARF-extracted strings:
    
    - `DwarfSymbol` for function and variable names derived from `DW_AT_name` attributes on `DW_TAG_subprogram` and `DW_TAG_variable` DIEs.
    - `DwarfFilePath` for source file paths resolved from `DW_AT_comp_dir` and `DW_AT_decl_file` attributes, building on the existing `FilePath` tag for consistency.
    - `DwarfType` for type names from `DW_TAG_structure_type`, `DW_TAG_class_type`, and similar DIEs representing structs, classes, and enums.
    
    Use `#[serde(rename = "dwarf-symbol")]`, `#[serde(rename = "dwarf-file-path")]`, and `#[serde(rename = "dwarf-type")]` attributes to ensure proper JSON serialization. These tags enable filtering and identification of DWARF-sourced content in outputs, complementing existing tags like `Symbol` and `FilePath`.
    
    ### src/extraction/mod.rs(MODIFY)
    
    References: 
    
    - src/types.rs(MODIFY)
    
    Introduce the extraction module structure by defining:
    
    - `ExtractionConfig` struct with fields: `skip_dwarf: bool` (default: false), `max_dwarf_size: Option<usize>` (default: Some(100 * 1024 * 1024) for 100MB limit), and other extraction parameters like minimum string lengths.
    
    - Public function `pub fn extract_strings(data: &[u8], container_info: &ContainerInfo, config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>>` to orchestrate extraction from multiple sources, including a conditional call to DWARF extraction if not skipped.
    
    - Module declaration `pub mod dwarf;` to expose the new submodule.
    
    - Basic error handling and logging for extraction failures.
    
    This establishes the pipeline foundation, allowing DWARF extraction to integrate seamlessly as one phase among section scanning and symbol table processing.
    
    ### src/extraction/dwarf.rs(NEW)
    
    References: 
    
    - src/types.rs(MODIFY)
    - src/container/mod.rs
    
    Implement the DWARF extraction module as follows:
    
    - Define `pub fn extract_dwarf_strings(sections: &[Section], data: &[u8], config: &ExtractionConfig) -> Result<Vec<FoundString>, Box<dyn Error>>` as the entry point.
    
    - Identify relevant DWARF sections (`.debug_info`, `.debug_str`, `.debug_line`, `.debug_abbrev`, `.debug_types`) from the provided `sections` vector, skipping if `config.skip_dwarf` is true or section size exceeds `max_dwarf_size`.
    
    - Use the `object` crate to create an `Object` from `data` and load section data into `gimli::DwarfSections` buffers.
    
    - Construct `gimli::Dwarf` with `EndianSlice` readers, detecting endianness from the binary format.
    
    - Iterate over compilation units using `dwarf.units()` and type units with `dwarf.debug_types()`.
    
    - For each unit, traverse DIEs with `unit.entries()` and `next_dfs()` to visit all entries depth-first.
    
    - Extract strings via:
      - `DW_AT_name`: Use `dwarf.attr_string(unit, attr.value())?` to get UTF-8 strings, create `FoundString` with `text`, `encoding: Encoding::Utf8`, `source: StringSource::DebugInfo`, `tags: vec![Tag::DwarfSymbol]`, `score: 95`.
      - `DW_AT_comp_dir`: Resolve as directory path, tag with `Tag::DwarfFilePath`, score 90.
      - `DW_AT_decl_file`: Combine with line program (`unit.line_program`) to resolve full file path using `header.file(index).as_ref()?.path().to_string_lossy()`, prepend `DW_AT_comp_dir` if available, tag `Tag::DwarfFilePath`, score 90.
      - For type DIEs (`DW_TAG_structure_type`, etc.): Extract name with `Tag::DwarfType`, score 92.
    
    - Set `offset` to approximate position (section offset + attribute offset), `section` to the source section name, `rva: None`, `length: text.len() as u32`.
    
    - Deduplicate within DWARF results using a `HashSet<String>` before returning.
    
    - Handle errors gracefully: malformed sections return empty vec, log warnings for parse failures.
    
    - Support DWARF versions 2-5 implicitly via gimli's compatibility layer.
    
    Reference gimli examples for `DwarfSections::load`, unit iteration, and attribute resolution to ensure correct API usage.
    
    ### src/main.rs(MODIFY)
    
    References: 
    
    - src/extraction/mod.rs(MODIFY)
    
    Enhance the CLI parsing and main logic to support DWARF extraction:
    
    - Add to `Cli` struct (using `clap::Parser`): `#[arg(long, default_value_t = false, help = "Skip DWARF debug section extraction (faster for large binaries)")] skip_dwarf: bool,` and `#[arg(long, default_value_t = 100, help = "Maximum DWARF section size to process (in MB)")] max_dwarf_size: usize,`.
    
    - In the `main` function, after parsing the binary and obtaining `ContainerInfo`:
      - Create `ExtractionConfig { skip_dwarf: cli.skip_dwarf, max_dwarf_size: Some(cli.max_dwarf_size * 1024 * 1024), ..Default::default() }`.
      - Call `extraction::extract_strings(&file_data, &container_info, &config)?` to get `Vec<FoundString>`.
      - Proceed to classification, ranking, and output as per existing pipeline (placeholders to be filled).
    
    - Update error handling to propagate extraction errors.
    
    - For now, if extraction is not yet fully implemented, add a debug print showing config values to verify flag parsing.
    
    This integrates user controls into the workflow, enabling performance tuning for DWARF processing.
    
    ### src/lib.rs(MODIFY)
    
    References: 
    
    - src/extraction/mod.rs(MODIFY)
    
    Update the library documentation and public API:
    
    - In the module docstring, add a section describing DWARF extraction: "Supports extraction from DWARF debug sections using the gimli crate, providing function names, source paths, and type information with high confidence scores."
    
    - Re-export `ExtractionConfig` from `extraction` module: `pub use extraction::{extract_strings, ExtractionConfig};`.
    
    - Update "Current Implementation Status" to note: "DWARF extraction: Implemented via src/extraction/dwarf.rs, integrated into main pipeline."
    
    - Add an example usage snippet showing DWARF-enabled extraction.
    
    This ensures the crate's public interface reflects the new functionality and guides library users on DWARF features.
    
    ### tests/integration_dwarf.rs(NEW)
    
    References: 
    
    - tests/integration_elf.rs
    - tests/fixtures/README.md
    
    Create comprehensive integration tests for DWARF extraction, following patterns from `tests/integration_elf.rs`:
    
    - Use `#[test]` functions with fixtures: Assume new fixtures `tests/fixtures/hello_debug` (C program compiled with `gcc -g`), `tests/fixtures/hello_stripped` (stripped version), and `tests/fixtures/rust_debug` (Rust binary with debug info).
    
    - Test section detection: Verify `parse_elf` identifies DWARF sections as `SectionType::Debug`.
    
    - Test extraction with debug binary: Call `extract_strings` with `skip_dwarf: false`, assert extracted strings include expected `DW_AT_name` like "main", "printf" with `Tag::DwarfSymbol`, score >=95, `source: StringSource::DebugInfo`.
    
    - Test file path extraction: Assert paths like "hello.c" or full `/path/to/hello.c` with `Tag::DwarfFilePath`, score 90.
    
    - Test type extraction: For Rust fixture, verify struct names with `Tag::DwarfType`.
    
    - Test skip flag: With `skip_dwarf: true`, assert no DWARF strings in results.
    
    - Test size limit: Mock a large section, verify skipping when exceeding `max_dwarf_size`.
    
    - Test stripped binary: No crash, empty DWARF results.
    
    - Test malformed DWARF: Use a corrupted fixture, ensure graceful error handling without panic.
    
    - Use `insta::assert_snapshot!` for output validation, comparing JSON-serialized `FoundString` vectors.
    
    - Add `#[cfg(feature = "integration")]` if needed, and helper functions like `get_fixture_path("hello_debug")`.
    
    These tests validate the full pipeline, from section loading to string creation and scoring.
    
    ### README.md(MODIFY)
    
    Enhance the README to highlight DWARF extraction capabilities:
    
    - In "Features" section, add bullet: "🔍 DWARF Debug Extraction: Retrieve function names, variable identifiers, type information, and source file paths from debug sections in non-stripped binaries."
    
    - In "Usage" section, include CLI examples:
      ```bash
      # Full extraction including DWARF
      cargo run -- target/debug/my_binary
      
      # Skip DWARF for performance
      cargo run -- --skip-dwarf target/debug/my_binary
      
      # Limit DWARF section size
      cargo run -- --max-dwarf-size 50 target/debug/my_binary
      ```
    
    - Update "Development Status" or "Roadmap" to mark DWARF extraction as ✅ Implemented.
    
    - In "Advantages" section, add: "- Extracts semantic identifiers from DWARF debug info, revealing internal implementation details beyond surface-level strings."
    
    - Add to "Acknowledgements": "- gimli crate for robust DWARF parsing."
    
    - Include a brief example output showing a DWARF-extracted function name with tags and score.
    
    These updates inform users about the feature, its benefits, and usage options.
    
    ### docs/src/string-extraction.md(MODIFY)
    
    References: 
    
    - src/extraction/dwarf.rs(NEW)
    
    Expand the string extraction documentation with a dedicated DWARF section:
    
    - Add heading "## DWARF Debug Information Extraction" describing the value of extracting from `.debug_info`, `.debug_str`, `.debug_line`, etc., including examples of function names, paths, and types.
    
    - Detail the implementation: gimli crate usage, DIE traversal, attribute extraction (`DW_AT_name`, etc.), and path resolution via line programs.
    
    - Cover scoring: 95 for symbols, 90 for paths, 92 for types, explaining high confidence due to structured data.
    
    - Discuss performance mitigations: skip flag, size limits, and when to use stripped binaries.
    
    - Include deduplication notes: How DWARF strings merge with symtab/rodata results, preserving best score and tags.
    
    - Provide code snippets (non-executable) showing extraction flow and `FoundString` creation.
    
    - Reference DWARF standard and gimli docs.
    
    - End with usage example in JSON output format.
    
    This comprehensive doc serves as a user guide and technical reference for the feature.
    
    ### .kiro/specs/stringy-binary-analyzer/tasks.md(MODIFY)
    
    Update the tasks document by adding or completing the DWARF extraction task:
    
    - Insert or modify task #17 (or appropriate number): "Implement DWARF debug information extraction"
      - Subtasks:
        - [x] Add gimli and object dependencies
        - [x] Create src/extraction/dwarf.rs module
        - [x] Extend Tag enum with DwarfSymbol, DwarfFilePath, DwarfType
        - [x] Implement DIE traversal and attribute extraction (DW_AT_name, DW_AT_comp_dir, DW_AT_decl_file)
        - [x] Add CLI flags --skip-dwarf and --max-dwarf-size
        - [x] Integrate into extraction pipeline with deduplication
        - [x] Implement scoring (90-95 range)
        - [x] Add unit tests for attribute parsing
        - [x] Add integration tests for debug/stripped/large binaries
        - [x] Update documentation (README, string-extraction.md)
      - Requirements: High-confidence string extraction from debug sections, performance controls.
    
    Mark subtasks as completed based on this plan's implementation. Ensure the task aligns with the epic for enhanced analyzer capabilities.

    Developer Humor

    In the depths of .debug_info, where DIEs dwell,\n> Gimli parses the secrets that compilers tell.\n> Function names emerge, paths come to light,\n> With scores so high, they're a reverse engineer's delight!\n> But strip the debug, and they vanish from sight—\n> Use --skip-dwarf if you want speed, not insight. 🛠️🔍


    Execution Information

    Branch: main
    Commit: 37cfc7c

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    MVPMinimum viable product featuresarea:analyzerBinary analyzer functionalityenhancementNew feature or requestepicLarge feature or initiative spanning multiple taskslang:rustRust implementationneeds:testsNeeds test coveragepriority:mediumMedium priority task

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions