Skip to content

ElfSection

Description

Decoded section header. name is borrowed from the file’s .shstrtab and stays valid until ElfDeinit.

Usage example (Cross-references)

Usage examples (Cross-references)
        u32  info;       // section-specific
        u64  entry_size; // for table-shaped sections
    } ElfSection;
    
    ///
    } ElfSegment;
    
    typedef Vec(ElfSection) ElfSections;
    typedef Vec(ElfSymbol) ElfSymbols;
    typedef Vec(ElfSegment) ElfSegments;
            LOG_FATAL("DwarfFunctionsBuildFromElf: NULL argument");
        }
        const ElfSection *info_sec   = ElfFindSection(elf, ".debug_info");
        const ElfSection *abbrev_sec = ElfFindSection(elf, ".debug_abbrev");
        const ElfSection *str_sec    = ElfFindSection(elf, ".debug_str");
        }
        const ElfSection *info_sec   = ElfFindSection(elf, ".debug_info");
        const ElfSection *abbrev_sec = ElfFindSection(elf, ".debug_abbrev");
        const ElfSection *str_sec    = ElfFindSection(elf, ".debug_str");
        const ElfSection *info_sec   = ElfFindSection(elf, ".debug_info");
        const ElfSection *abbrev_sec = ElfFindSection(elf, ".debug_abbrev");
        const ElfSection *str_sec    = ElfFindSection(elf, ".debug_str");
    
        const u8 *info_b   = info_sec ? BufData(ElfBuf(elf)) + info_sec->offset : NULL;
        // CFI only there and leaves .eh_frame empty (the project's unwinder and
        // Sys/Backtrace would otherwise find no frames on such binaries).
        const ElfSection *eh = ElfFindSection(elf, ".eh_frame");
        bool              ok;
        if (eh && eh->size > 0) {
            ok                 = cfi_parse_section(out, BufData(ElfBuf(elf)) + eh->offset, eh->addr, eh->size, false);
        } else {
            const ElfSection *df = ElfFindSection(elf, ".debug_frame");
            if (!df || df->size == 0) {
                return true; // No CFI in this binary — still success, just empty.
            BufReadFmt(&iter, FMT_SHDR64_LE, name, type, flags, addr, offset, size_, link, info, addralign, entsize);
    
            ElfSection s;
            s.name       = elf_str_at(self, shstr_off, shstr_size, name);
            s.type       = type;
    // ---------------------------------------------------------------------------
    
    static bool elf_decode_symbol_table(Elf *self, const ElfSection *symtab, ElfSymbols *out) {
        if (!symtab || symtab->size == 0) {
            return true;
            return false;
        }
        const ElfSection *strtab = VecPtrAt(&self->sections, strtab_idx);
        if (!elf_range_ok(self, strtab->offset, strtab->size)) {
            LOG_ERROR("Elf: strtab out of range");
    
    static bool elf_decode_symbols(Elf *self) {
        const ElfSection *symtab    = NULL;
        const ElfSection *dynsymtab = NULL;
    static bool elf_decode_symbols(Elf *self) {
        const ElfSection *symtab    = NULL;
        const ElfSection *dynsymtab = NULL;
    
        for (u64 i = 0; i < VecLen(&self->sections); ++i) {
    
        for (u64 i = 0; i < VecLen(&self->sections); ++i) {
            const ElfSection *s = VecPtrAt(&self->sections, i);
            if (s->type == ELF_SECTION_TYPE_SYMTAB) {
                symtab = s;
    };
    
    static void elf_decode_build_id(Elf *self, const ElfSection *note) {
        if (!elf_range_ok(self, note->offset, note->size) || note->size < 16) {
            return;
    }
    
    static void elf_decode_debug_link(Elf *self, const ElfSection *dl) {
        if (!elf_range_ok(self, dl->offset, dl->size) || dl->size < 5) {
            return;
    
    static void elf_decode_debug_metadata(Elf *self) {
        const ElfSection *note = ElfFindSection(self, ".note.gnu.build-id");
        if (note) {
            elf_decode_build_id(self, note);
            elf_decode_build_id(self, note);
        }
        const ElfSection *dl = ElfFindSection(self, ".gnu_debuglink");
        if (dl) {
            elf_decode_debug_link(self, dl);
    }
    
    const ElfSection *elf_find_section_zstr(const Elf *self, Zstr name) {
        if (!self || !name)
            return NULL;
            return NULL;
        for (u64 i = 0; i < VecLen(&self->sections); ++i) {
            const ElfSection *s = VecPtrAt(&self->sections, i);
            if (s->name && ZstrCompare(s->name, name) == 0) {
                return s;
    }
    
    const ElfSection *elf_find_section_str(const Elf *self, const Str *name) {
        if (!self || !name)
            return NULL;
        out->string_pool = StrInit(alloc);
    
        const ElfSection *line_section = ElfFindSection(elf, ".debug_line");
        if (!line_section || line_section->size == 0) {
            // No debug info — empty result is still success.
        }
    
        const ElfSection *text = ElfFindSection(&elf, ".text");
        bool              ok   = text != NULL && text->size > 0 && (text->flags & 0x4); // SHF_EXECINSTR = 0x4
        // Sections decode in order with correct names.
        ok                     = ok && VecLen(&elf.sections) == N_SECTIONS;
        const ElfSection *text = ElfFindSection(&elf, ".text");
        ok = ok && text != NULL && text->addr == TEXT_VADDR && text->offset == TEXT_OFF && text->size == TEXT_SIZE &&
             text->type == ELF_SECTION_TYPE_PROGBITS;
    
        // First section is the NULL section (name ""), last is .strtab.
        const ElfSection *first = VecPtrAt(&elf.sections, 0);
        const ElfSection *last  = VecPtrAt(&elf.sections, N_SECTIONS - 1);
        ok                      = ok && first->name && first->name[0] == '\0' && first->type == ELF_SECTION_TYPE_NULL;
        // First section is the NULL section (name ""), last is .strtab.
        const ElfSection *first = VecPtrAt(&elf.sections, 0);
        const ElfSection *last  = VecPtrAt(&elf.sections, N_SECTIONS - 1);
        ok                      = ok && first->name && first->name[0] == '\0' && first->type == ELF_SECTION_TYPE_NULL;
        ok = ok && last->name && ZstrCompare(last->name, ".strtab") == 0 && last->type == ELF_SECTION_TYPE_STRTAB &&
        }
    
        const ElfSection *t = ElfFindSection(&elf, ".text");
        bool ok = t != NULL && t->type == ELF_SECTION_TYPE_PROGBITS && t->addr == TEXT_VADDR && t->offset == TEXT_OFF &&
                  t->size == TEXT_SIZE && (t->flags & 0x4) != 0;
        }
    
        const ElfSection *sym = ElfFindSection(&elf, ".symtab");
        // .symtab carries the distinctive info; every other section's info is 0.
        const ElfSection *txt = ElfFindSection(&elf, ".text");
        const ElfSection *sym = ElfFindSection(&elf, ".symtab");
        // .symtab carries the distinctive info; every other section's info is 0.
        const ElfSection *txt = ElfFindSection(&elf, ".text");
        bool              ok  = sym != NULL && sym->info == SYMTAB_INFO && txt != NULL && txt->info == 0;
        // Section 1's name idx points at "AB" with no terminator inside the
        // declared strtab size => real decodes "".
        const ElfSection *s1 = VecPtrAt(&elf.sections, 1);
        bool              ok = VecLen(&elf.sections) == 2 && s1->name != NULL && s1->name[0] == '\0';
        }
    
        const ElfSection *s1 = VecPtrAt(&elf.sections, 1);
        bool              ok = VecLen(&elf.sections) == 2 && s1->name != NULL && s1->name[0] == '\0';
        }
    
        const ElfSection *s1 = VecPtrAt(&elf.sections, 1);
        bool              ok = VecLen(&elf.sections) == 2 && s1->name != NULL && ZstrCompare(s1->name, "XYZ") == 0;
        // ".strtab" lives at NAME_STRTAB (25) in the shstrtab, well past the
        // first string. It must decode exactly, not collapse to "" or ".shstrtab".
        const ElfSection *s   = ElfFindSection(&elf, ".strtab");
        const ElfSection *sym = ElfFindSection(&elf, ".symtab");
        bool              ok =
        // first string. It must decode exactly, not collapse to "" or ".shstrtab".
        const ElfSection *s   = ElfFindSection(&elf, ".strtab");
        const ElfSection *sym = ElfFindSection(&elf, ".symtab");
        bool              ok =
            s != NULL && ZstrCompare(s->name, ".strtab") == 0 && sym != NULL && ZstrCompare(sym->name, ".symtab") == 0;
    
        // .strtab is the final section in the table.
        const ElfSection *last     = ElfFindSection(&elf, ".strtab");
        const ElfSection *expected = VecPtrAt(&elf.sections, N_SECTIONS - 1);
        bool              ok       = last != NULL && last == expected;
        // .strtab is the final section in the table.
        const ElfSection *last     = ElfFindSection(&elf, ".strtab");
        const ElfSection *expected = VecPtrAt(&elf.sections, N_SECTIONS - 1);
        bool              ok       = last != NULL && last == expected;
Last updated on