ElfSymbol
Description
Decoded symbol-table entry. name is borrowed from the file’s .strtab (for symbols) or .dynstr (for dynamic_symbols).
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Dwarf.h:321:
typedef struct DwarfFunction {
u64 low_pc; // file-relative virtual address (same space as ElfSymbol.value)
u64 high_pc; // exclusive end
Zstr name; // borrowed from `string_pool`
- In
Elf.h:147:
u64 value; // virtual address for ET_EXEC / ET_DYN
u64 size;
} ElfSymbol;
///
- In
Elf.h:176:
typedef Vec(ElfSection) ElfSections;
typedef Vec(ElfSymbol) ElfSymbols;
typedef Vec(ElfSegment) ElfSegments;- In
Elf.h:364:
/// TAGS: Parser, ELF, Symbol
///
const ElfSymbol *ElfResolveAddress(const Elf *self, u64 vaddr);
///
// approach) so they don't shadow the real symbol. STT_NOTYPE is otherwise kept,
// since hand-written assembly functions legitimately carry no type.
static bool resolver_is_mapping_symbol(const Elf *elf, const ElfSymbol *s) {
if (elf->header.machine != ELF_MACHINE_AARCH64 || !s->name)
return false; // GLOBAL) and adds the mapping-symbol filter the parser deliberately stays out
// of -- address->function resolution is a SymbolResolver concern, not ELF's.
static const ElfSymbol *resolver_search_symbols(const Elf *elf, const ElfSymbols *syms, u64 vaddr) {
const ElfSymbol *best = NULL;
for (u64 i = 0; i < VecLen(syms); ++i) { // of -- address->function resolution is a SymbolResolver concern, not ELF's.
static const ElfSymbol *resolver_search_symbols(const Elf *elf, const ElfSymbols *syms, u64 vaddr) {
const ElfSymbol *best = NULL;
for (u64 i = 0; i < VecLen(syms); ++i) {
const ElfSymbol *s = VecPtrAt(syms, i); const ElfSymbol *best = NULL;
for (u64 i = 0; i < VecLen(syms); ++i) {
const ElfSymbol *s = VecPtrAt(syms, i);
// Consider only real address symbols. Like llvm-symbolizer, keep
// NOTYPE/FUNC/OBJECT (NOTYPE covers hand-written asm) and drop
}
static const ElfSymbol *resolver_resolve_addr(const Elf *elf, u64 vaddr) {
const ElfSymbol *hit = resolver_search_symbols(elf, &elf->symbols, vaddr);
return hit ? hit : resolver_search_symbols(elf, &elf->dynamic_symbols, vaddr);
static const ElfSymbol *resolver_resolve_addr(const Elf *elf, u64 vaddr) {
const ElfSymbol *hit = resolver_search_symbols(elf, &elf->symbols, vaddr);
return hit ? hit : resolver_search_symbols(elf, &elf->dynamic_symbols, vaddr);
} // sidecar (full `.symtab` for stripped binaries) if nothing
// matches.
const ElfSymbol *sym = resolver_resolve_addr(&cache_entry->elf, file_relative);
if (!(sym && sym->name && sym->name[0]) && cache_entry->has_sidecar) {
sym = resolver_resolve_addr(&cache_entry->sidecar, file_relative);- In
Elf.c:350:
BufReadFmt(&iter, FMT_SYM64_LE, name, info, other, shndx, value, size_);
ElfSymbol s;
s.name = elf_str_at(self, strtab->offset, strtab->size, name);
s.bind = (ElfSymbolBind)(info >> 4);- In
Elf.c:558:
// ---------------------------------------------------------------------------
static const ElfSymbol *elf_search_symbols(const ElfSymbols *syms, u64 vaddr) {
const ElfSymbol *best = NULL;
for (u64 i = 0; i < VecLen(syms); ++i) {- In
Elf.c:559:
static const ElfSymbol *elf_search_symbols(const ElfSymbols *syms, u64 vaddr) {
const ElfSymbol *best = NULL;
for (u64 i = 0; i < VecLen(syms); ++i) {
const ElfSymbol *s = VecPtrAt(syms, i);- In
Elf.c:561:
const ElfSymbol *best = NULL;
for (u64 i = 0; i < VecLen(syms); ++i) {
const ElfSymbol *s = VecPtrAt(syms, i);
if (s->size == 0) {
// Some symbols (e.g. labels) have zero size — only match
- In
Elf.c:581:
}
const ElfSymbol *ElfResolveAddress(const Elf *self, u64 vaddr) {
if (!self)
return NULL;- In
Elf.c:584:
if (!self)
return NULL;
const ElfSymbol *hit = elf_search_symbols(&self->symbols, vaddr);
if (hit)
return hit; // (3) Symbol lookup against .symtab/.dynsym should miss for our
// static helpers (they're not exported, and .symtab is gone).
const ElfSymbol *sym = ElfResolveAddress(&stripped, file_relative);
bool sym_missing_or_unnamed = (!sym) || (sym && (!sym->name || !sym->name[0]));
if (!sym_missing_or_unnamed) {- In
Elf.c:324:
bool ok = false;
for (u64 i = 0; i < VecLen(&elf.symbols); ++i) {
const ElfSymbol *s = VecPtrAt(&elf.symbols, i);
if (s->type == ELF_SYMBOL_TYPE_FUNC && s->size > 0 && s->name && s->name[0] != '\0') {
ok = true;- In
Elf.c:371:
bool found_func = false;
for (u64 i = 0; i < VecLen(&elf.symbols); ++i) {
const ElfSymbol *s = VecPtrAt(&elf.symbols, i);
if (s->name && ZstrCompare(s->name, "my_func") == 0) {
found_func = s->value == FUNC_VADDR && s->size == FUNC_SIZE && s->type == ELF_SYMBOL_TYPE_FUNC &&- In
Elf.c:426:
// Exactly at the symbol start.
const ElfSymbol *s = ElfResolveAddress(&elf, FUNC_VADDR);
bool ok = s && s->name && ZstrCompare(s->name, "my_func") == 0;- In
Elf.c:1704:
return false;
}
const ElfSymbol *a = VecPtrAt(&elf.symbols, 1);
const ElfSymbol *b = VecPtrAt(&elf.symbols, 3);
const ElfSymbol *l = VecPtrAt(&elf.symbols, 4);- In
Elf.c:1705:
}
const ElfSymbol *a = VecPtrAt(&elf.symbols, 1);
const ElfSymbol *b = VecPtrAt(&elf.symbols, 3);
const ElfSymbol *l = VecPtrAt(&elf.symbols, 4);
bool ok = a->name && ZstrCompare(a->name, "alpha") == 0 && b->name && ZstrCompare(b->name, "beta") == 0 &&- In
Elf.c:1706:
const ElfSymbol *a = VecPtrAt(&elf.symbols, 1);
const ElfSymbol *b = VecPtrAt(&elf.symbols, 3);
const ElfSymbol *l = VecPtrAt(&elf.symbols, 4);
bool ok = a->name && ZstrCompare(a->name, "alpha") == 0 && b->name && ZstrCompare(b->name, "beta") == 0 &&
l->name && ZstrCompare(l->name, "local") == 0;- In
Elf.c:1722:
return false;
}
const ElfSymbol *a = VecPtrAt(&elf.symbols, 1);
bool ok = a->value == SF_ALPHA_VADDR && a->size == SF_ALPHA_SIZE && a->type == ELF_SYMBOL_TYPE_FUNC &&
a->bind == ELF_SYMBOL_BIND_GLOBAL && a->section_index == SF_SEC_TEXT;- In
Elf.c:1742:
bool ok = VecLen(&elf.dynamic_symbols) == 2;
if (ok) {
const ElfSymbol *d = VecPtrAt(&elf.dynamic_symbols, 1);
ok = d->name && ZstrCompare(d->name, "dyn_sym") == 0 && d->value == SF_DYN_VADDR;
}- In
Elf.c:1778:
return false;
}
const ElfSymbol *s;
bool ok = true;- In
Elf.c:1802:
return false;
}
const ElfSymbol *hit = ElfResolveAddress(&elf, SF_BETA_VADDR);
const ElfSymbol *miss = ElfResolveAddress(&elf, SF_BETA_VADDR + 1);
bool ok = hit && hit->name && ZstrCompare(hit->name, "beta") == 0 && miss == NULL;- In
Elf.c:1803:
}
const ElfSymbol *hit = ElfResolveAddress(&elf, SF_BETA_VADDR);
const ElfSymbol *miss = ElfResolveAddress(&elf, SF_BETA_VADDR + 1);
bool ok = hit && hit->name && ZstrCompare(hit->name, "beta") == 0 && miss == NULL;
ElfDeinit(&elf);- In
Elf.c:1821:
return false;
}
const ElfSymbol *s = ElfResolveAddress(&elf, SF_BETA_VADDR);
bool ok = s && s->name && ZstrCompare(s->name, "beta") == 0 && s->bind == ELF_SYMBOL_BIND_GLOBAL;
ElfDeinit(&elf);- In
Elf.c:1842:
// [0x1000, 0x1040). best starts at alpha; local is seen later and must
// NOT displace it because local is not GLOBAL.
const ElfSymbol *s = ElfResolveAddress(&elf, SF_ALPHA_VADDR + 4);
bool ok = s && s->name && ZstrCompare(s->name, "alpha") == 0 && s->bind == ELF_SYMBOL_BIND_GLOBAL;
ElfDeinit(&elf);
Last updated on