Skip to content
ElfResolveAddress

ElfResolveAddress

Description

Look up the symbol whose [value, value+size) range contains vaddr. Searches symbols first, then dynamic_symbols — so static (non-exported) functions resolve when .symtab is present.

vaddr is the file-relative virtual address — i.e. for a runtime pointer in a ET_DYN (PIE / shared object), the caller subtracts the load base first. For ET_EXEC it’s the address as-is.

Parameters

Name Direction Description
self in Parsed ELF file.
vaddr in Virtual address to resolve.

Success

Returns a pointer to the matching ElfSymbol. The pointer is valid until ElfDeinit.

Failure

Returns NULL if no symbol covers vaddr.

Usage example (Cross-references)

Usage examples (Cross-references)
    }
    
    const ElfSymbol *ElfResolveAddress(const Elf *self, u64 vaddr) {
        if (!self)
            return NULL;
    
        // Exactly at the symbol start.
        const ElfSymbol *s  = ElfResolveAddress(&elf, FUNC_VADDR);
        bool             ok = s && s->name && ZstrCompare(s->name, "my_func") == 0;
    
        // Inside the body.
        s  = ElfResolveAddress(&elf, FUNC_VADDR + FUNC_SIZE / 2);
        ok = ok && s && ZstrCompare(s->name, "my_func") == 0;
    
        // Last covered byte.
        s  = ElfResolveAddress(&elf, FUNC_VADDR + FUNC_SIZE - 1);
        ok = ok && s && ZstrCompare(s->name, "my_func") == 0;
    
        // Just past the end -> no match.
        s  = ElfResolveAddress(&elf, FUNC_VADDR + FUNC_SIZE);
        ok = ok && s == NULL;
    
        // Below the symbol -> no match.
        s  = ElfResolveAddress(&elf, FUNC_VADDR - 1);
        ok = ok && s == NULL;
        bool             ok = true;
    
        s  = ElfResolveAddress(&elf, SF_ALPHA_VADDR);                     // exact start
        ok = ok && s && s->name && ZstrCompare(s->name, "alpha") == 0;
        s  = ElfResolveAddress(&elf, SF_ALPHA_VADDR + SF_ALPHA_SIZE - 1); // last byte
        s  = ElfResolveAddress(&elf, SF_ALPHA_VADDR);                     // exact start
        ok = ok && s && s->name && ZstrCompare(s->name, "alpha") == 0;
        s  = ElfResolveAddress(&elf, SF_ALPHA_VADDR + SF_ALPHA_SIZE - 1); // last byte
        ok = ok && s && s->name && ZstrCompare(s->name, "alpha") == 0;
        s  = ElfResolveAddress(&elf, SF_ALPHA_VADDR + SF_ALPHA_SIZE);     // just past
        s  = ElfResolveAddress(&elf, SF_ALPHA_VADDR + SF_ALPHA_SIZE - 1); // last byte
        ok = ok && s && s->name && ZstrCompare(s->name, "alpha") == 0;
        s  = ElfResolveAddress(&elf, SF_ALPHA_VADDR + SF_ALPHA_SIZE);     // just past
        ok = ok && (s == NULL || ZstrCompare(s->name, "alpha") != 0);
            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;
        }
        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);
            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);
        // [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);
        // (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) {
Last updated on