Skip to content

DwarfLines

Description

Parsed .debug_line content. Entries are flat and sorted-by- address per the line-number program’s natural emission order inside each compilation unit. Lookups do a linear scan across all CUs.

Fields

Name Description
allocator Allocator backing entries + string_pool.
entries All (address, file, line, …) rows, in CU / program order.
string_pool Owned buffer holding the file / directory strings that entries borrows from. Required because .debug_line file/dir entries are interleaved byte-strings inside the section — we copy them into a contiguous pool so the Elf’s lifetime doesn’t have to match ours.

Usage example (Cross-references)

Usage examples (Cross-references)
        bool has_sidecar;
    #if FEATURE_PARSER_DWARF
        DwarfLines dwarf;
        bool       dwarf_built;
        bool       dwarf_ok;
        bool       dwarf_built;
        bool       dwarf_ok;
        DwarfLines sidecar_dwarf;
        bool       sidecar_dwarf_built;
        bool       sidecar_dwarf_ok;
        DwarfLineEntries entries;
        Str              string_pool;
    } DwarfLines;
    
    ///
    /// TAGS: Parser, DWARF, Lookup
    ///
    const DwarfLineEntry *DwarfLinesResolve(const DwarfLines *self, u64 vaddr);
    
    ///
    /// TAGS: Parser, DWARF, Lines, Deinit, Lifecycle
    ///
    void DwarfLinesDeinit(DwarfLines *self);
    
    // ===========================================================================
    
    static bool lnp_emit(
        DwarfLines      *out,
        Str             *pool,
        const CuStrings *cs,
        const LineProgHeader *hdr,
        const CuStrings      *cs,
        DwarfLines           *out,
        U64Vec               *pending_file_offsets,
        U64Vec               *pending_dir_offsets
    // ---------------------------------------------------------------------------
    
    bool dwarf_lines_build_from_elf(DwarfLines *out, const Elf *elf, Allocator *alloc) {
        if (!out || !elf || !alloc) {
            LOG_FATAL("DwarfLinesBuildFromElf: NULL argument");
    }
    
    void DwarfLinesDeinit(DwarfLines *self) {
        if (!self)
            return;
    // ---------------------------------------------------------------------------
    
    const DwarfLineEntry *DwarfLinesResolve(const DwarfLines *self, u64 vaddr) {
        if (!self || VecLen(&self->entries) == 0)
            return NULL;
    // Build a DwarfLines from a raw `.debug_line` payload through `base`.
    // Returns the build result; on true the caller owns `*lines` + `*elf`.
    static bool build_from_dl(DwarfLines *lines, Elf *elf, Allocator *base, const u8 *dl, u64 dl_len) {
        static u8 elfbuf[8192];
        u64       elf_len = 0;
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        bool       ok    = built;
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        bool       ok    = built;
    // tests. Returns u64max-or-mismatch-safe: scans for the first non-end_sequence
    // row and reports its address via *out, returns whether one was found.
    static bool first_real_row_address(const DwarfLines *lines, u64 *out) {
        for (u64 i = 0; i < VecLen(&lines->entries); ++i) {
            const DwarfLineEntry *e = &VecAt(&lines->entries, i);
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        bool       ok    = built;
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        bool       ok    = built;
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        bool       ok    = built;
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        bool       ok    = built;
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        // Real code rejects the truncated trailing unit (returns false).
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        if (built)
    
        Elf        elf;
        DwarfLines lines;
        bool       built = build_from_dl(&lines, &elf, base, dl, dl_len);
        if (built)
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, ALLOCATOR_OF(&alloc));
        bool       ok    = built && VecLen(&lines.entries) > 0;
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        bool       ok    = false;
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        bool       ok    = built;
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        // The malformed unit is rejected: either the build fails outright, or
        DefaultAllocator alloc;
        Elf              elf;
        DwarfLines       lines;
        bool             built;
    } LinesFixture;
    // Run a crafted program and return a built DwarfLines via `*lines`.
    // Returns true if the build succeeded (caller must Deinit on true).
    static bool build_lines_from_program(DwarfLines *lines, Allocator *base, const u8 *prog, u64 prog_len) {
        u8  dl[512];
        u64 dl_len = build_line_with_program(dl, prog, prog_len);
    }
    
    static bool lines_from_debug_line(DwarfLines *out, Elf *elf, const u8 *dl, u64 dl_len, Allocator *base) {
        static u8 elfbuf[8192];
        u64       elf_len = 0;
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        // The over-long extended record must be rejected: either the build fails
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_from_program(&lines, base, prog, (u64)(p - prog));
        bool       ok    = built;
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_from_program(&lines, base, prog, (u64)(p - prog));
        bool       ok    = built;
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_from_program(&lines, base, prog, (u64)(p - prog));
        bool       ok    = built;
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_from_program(&lines, base, prog, (u64)(p - prog));
        bool       ok    = built;
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_from_program(&lines, base, prog, (u64)(p - prog));
        bool       ok    = built;
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_from_program(&lines, base, prog, (u64)(p - prog));
        bool       ok    = built;
    
    static bool build_lines_custom(
        DwarfLines *lines,
        Allocator  *base,
        u8          opcode_base,
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_custom(&lines, base, 20, std_lengths, prog, (u64)(p - prog));
        bool       ok    = built;
        p     = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_custom(&lines, base, 15, std_lengths, prog, (u64)(p - prog));
        bool       ok    = built;
        p    = emit_end_sequence(p);
    
        DwarfLines lines;
        bool       built = build_lines_from_program(&lines, base, prog, (u64)(p - prog));
        bool       ok    = built;
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
    
        Elf        elf;
        DwarfLines lines;
        bool       built = lines_from_debug_line(&lines, &elf, dl, dl_len, base);
        bool       ok    = !built || VecLen(&lines.entries) == 0;
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        bool       ok    = built; // 562: `ok=true`->false => built would be false.
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        // Real code: rejected -> built == false. Mutant (ok=true): built == true.
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        // Real code rejects the overrun -> built == false. Mutant returns true.
        }
    
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        bool       ok    = built;
    
        size       before = DebugAllocatorLiveCount(&dbg);
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        bool       ok    = built;
    
        size       before = DebugAllocatorLiveCount(&dbg);
        DwarfLines lines;
        bool       built = DwarfLinesBuildFromElf(&lines, &elf, base);
        bool       ok    = built;
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            // Real code must build this valid CU; a build failure here is a kill.
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
    
        Elf        elf;
        DwarfLines lines;
        bool       built = lines_from_debug_line(&lines, &elf, dl, dl_len, base);
    
        Elf        elf;
        DwarfLines lines;
        if (!lines_from_debug_line(&lines, &elf, dl, dl_len, base)) {
            DefaultAllocatorDeinit(&alloc);
Last updated on