ElfFile
Description
Parsed ELF file. Holds the raw bytes plus decoded indices into them. Two construction paths:
ElfFileOpen — reads a file from disk; the ElfFile owns the byte buffer and frees it on ElfFileDeinit. ElfFileOpenFromMemory — borrows a caller-supplied buffer; the caller is responsible for keeping the buffer alive until ElfFileDeinit.
Fields
| Name | Description |
|---|---|
allocator |
Allocator used for the owned buffer (if any) and for the section / symbol vectors. |
data |
Pointer to the raw file bytes. |
data_size |
Length of data in bytes. |
owns_data |
True if data was allocated via allocator. |
header |
Decoded ELF header. |
sections |
All section headers, in original order. |
symbols |
Entries from .symtab (may be empty if stripped). |
dynamic_symbols |
Entries from .dynsym (always present for dynamic objects). |
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Dwarf.c:21:
DefaultAllocator alloc = DefaultAllocatorInit();
ElfFile elf;
if (!ElfFileOpen(&elf, "/proc/self/exe", ALLOCATOR_OF(&alloc))) {
DefaultAllocatorDeinit(&alloc);- In
Dwarf.c:60:
u64 file_relative = (u64)(uintptr_t)&dwarf_marker_helper - r.module_base;
ElfFile elf;
if (!ElfFileOpen(&elf, r.module_path, base)) {
SymbolResolverDeinit(&res);- In
Elf.c:12:
bool test_elf_self_exe_parse(void) {
DefaultAllocator alloc = DefaultAllocatorInit();
ElfFile elf;
bool opened = ElfFileOpen(&elf, "/proc/self/exe", ALLOCATOR_OF(&alloc));- In
Elf.c:35:
bool test_elf_find_text_section(void) {
DefaultAllocator alloc = DefaultAllocatorInit();
ElfFile elf;
if (!ElfFileOpen(&elf, "/proc/self/exe", ALLOCATOR_OF(&alloc))) {- In
Elf.c:55:
bool test_elf_some_function_symbol(void) {
DefaultAllocator alloc = DefaultAllocatorInit();
ElfFile elf;
if (!ElfFileOpen(&elf, "/proc/self/exe", ALLOCATOR_OF(&alloc))) {- In
Dwarf.c:586:
// ---------------------------------------------------------------------------
bool DwarfLinesBuildFromElf(DwarfLines *out, const ElfFile *elf, Allocator *alloc) {
if (!out || !elf || !alloc) {
LOG_ERROR("DwarfLinesBuildFromElf: NULL argument");- In
Elf.c:92:
// ---------------------------------------------------------------------------
static const char *elf_str_at(const ElfFile *self, u64 strtab_offset, u64 strtab_size, u32 idx) {
if ((u64)idx >= strtab_size) {
return "";- In
Elf.c:99:
}
static bool elf_range_ok(const ElfFile *self, u64 offset, u64 size) {
if (offset > self->data_size)
return false;- In
Elf.c:113:
// ---------------------------------------------------------------------------
static bool elf_decode_header(ElfFile *self) {
if (self->data_size < EI_NIDENT + EHDR64_SIZE_AFTER_IDENT) {
LOG_ERROR("ElfFile: file too small for ELF64 header ({} bytes)", (u64)self->data_size);- In
Elf.c:115:
static bool elf_decode_header(ElfFile *self) {
if (self->data_size < EI_NIDENT + EHDR64_SIZE_AFTER_IDENT) {
LOG_ERROR("ElfFile: file too small for ELF64 header ({} bytes)", (u64)self->data_size);
return false;
}- In
Elf.c:121:
const u8 *id = self->data;
if (id[EI_MAG0] != ELF_MAG0 || id[EI_MAG1] != ELF_MAG1 || id[EI_MAG2] != ELF_MAG2 || id[EI_MAG3] != ELF_MAG3) {
LOG_ERROR("ElfFile: bad magic");
return false;
}- In
Elf.c:126:
if (id[EI_CLASS] != (u8)ELF_CLASS_64) {
LOG_ERROR("ElfFile: only ELF64 supported in v1 (got class {})", (u32)id[EI_CLASS]);
return false;
}- In
Elf.c:130:
}
if (id[EI_DATA] != (u8)ELF_DATA_LSB) {
LOG_ERROR("ElfFile: only little-endian supported in v1 (got data {})", (u32)id[EI_DATA]);
return false;
}- In
Elf.c:171:
if (shentsize != SHDR64_SIZE && shnum > 0) {
LOG_ERROR("ElfFile: unexpected e_shentsize ({} vs {})", (u32)shentsize, (u32)SHDR64_SIZE);
return false;
}- In
Elf.c:178:
}
static bool elf_decode_sections(ElfFile *self) {
u16 n = self->header.shnum;
u64 shoff = self->header.shoff;- In
Elf.c:183:
u64 needed = (u64)n * SHDR64_SIZE;
if (!elf_range_ok(self, shoff, needed)) {
LOG_ERROR("ElfFile: section header table out of range");
return false;
}- In
Elf.c:188:
if (self->header.shstrndx >= n) {
LOG_ERROR("ElfFile: shstrndx {} out of range (shnum={})", (u32)self->header.shstrndx, (u32)n);
return false;
}- In
Elf.c:204:
}
if (!elf_range_ok(self, shstr_off, shstr_size)) {
LOG_ERROR("ElfFile: shstrtab out of range");
return false;
}- In
Elf.c:236:
// ---------------------------------------------------------------------------
static bool elf_decode_symbol_table(ElfFile *self, const ElfSection *symtab, ElfSymbols *out) {
if (!symtab || symtab->size == 0) {
return true;- In
Elf.c:241:
}
if (symtab->entry_size != SYM64_SIZE) {
LOG_ERROR("ElfFile: unexpected symbol entry size {}", (u64)symtab->entry_size);
return false;
}- In
Elf.c:245:
}
if (!elf_range_ok(self, symtab->offset, symtab->size)) {
LOG_ERROR("ElfFile: symbol table out of range");
return false;
}- In
Elf.c:253:
u32 strtab_idx = symtab->link;
if (strtab_idx >= self->sections.length) {
LOG_ERROR("ElfFile: symtab link {} out of range", (u32)strtab_idx);
return false;
}- In
Elf.c:258:
const ElfSection *strtab = &self->sections.data[strtab_idx];
if (!elf_range_ok(self, strtab->offset, strtab->size)) {
LOG_ERROR("ElfFile: strtab out of range");
return false;
}- In
Elf.c:287:
}
static bool elf_decode_symbols(ElfFile *self) {
const ElfSection *symtab = NULL;
const ElfSection *dynsymtab = NULL;- In
Elf.c:313:
// ---------------------------------------------------------------------------
bool ElfFileOpenFromMemory(ElfFile *out, u8 *data, size data_size, Allocator *alloc) {
if (!out || !data || !alloc) {
LOG_ERROR("ElfFileOpenFromMemory: NULL argument");- In
Elf.c:340:
}
bool ElfFileOpen(ElfFile *out, const char *path, Allocator *alloc) {
if (!out || !path || !alloc) {
LOG_ERROR("ElfFileOpen: NULL argument");- In
Elf.c:365:
}
void ElfFileDeinit(ElfFile *self) {
if (!self)
return;- In
Elf.c:404:
}
const ElfSymbol *ElfFileResolveAddress(const ElfFile *self, u64 vaddr) {
if (!self)
return NULL;- In
Elf.c:413:
}
const ElfSection *ElfFileFindSection(const ElfFile *self, const char *name) {
if (!self || !name)
return NULL; const char *path; // borrowed from ProcMaps.raw
u64 load_base;
ElfFile elf;
#if MISRA_HAVE_PARSER_DWARF
DwarfLines dwarf;- In
Dwarf.h:96:
/// TAGS: Parser, DWARF, Lines
///
bool DwarfLinesBuildFromElf(DwarfLines *out, const ElfFile *elf, Allocator *alloc);
///
- In
Elf.h:166:
ElfSymbols symbols;
ElfSymbols dynamic_symbols;
} ElfFile;
///
- In
Elf.h:183:
/// TAGS: Parser, ELF, File
///
bool ElfFileOpen(ElfFile *out, const char *path, Allocator *alloc);
///
- In
Elf.h:200:
/// TAGS: Parser, ELF, Memory
///
bool ElfFileOpenFromMemory(ElfFile *out, u8 *data, size data_size, Allocator *alloc);
///
- In
Elf.h:206:
/// `owns_data` was true. Safe to call on a zeroed struct.
///
void ElfFileDeinit(ElfFile *self);
///
- In
Elf.h:226:
/// TAGS: Parser, ELF, Symbol
///
const ElfSymbol *ElfFileResolveAddress(const ElfFile *self, u64 vaddr);
///
- In
Elf.h:231:
/// Find a section by name (first match). Returns NULL if absent.
///
const ElfSection *ElfFileFindSection(const ElfFile *self, const char *name);
#endif // MISRA_PARSERS_ELF_H
Last updated on