Skip to content

MachoSymbol

Description

Decoded nlist_64 entry. name is borrowed from the file’s symbol string table (LC_SYMTAB.stroff).

Usage example (Cross-references)

Usage examples (Cross-references)
        u8   type;          // n_type bitfield
        u8   section_index; // n_sect, 1-based (0 = NO_SECT)
    } MachoSymbol;
    
    typedef Vec(MachoSegment) MachoSegments;
    typedef Vec(MachoSegment) MachoSegments;
    typedef Vec(MachoSection) MachoSections;
    typedef Vec(MachoSymbol) MachoSymbols;
    
    ///
    /// TAGS: Parser, MachO, Symbol, Resolve
    ///
    const MachoSymbol *MachoResolveAddress(const Macho *self, u64 vaddr);
    
    #endif // MISRA_PARSERS_MACHO_H
    
        // (1) Main file's LC_SYMTAB.
        const MachoSymbol *s = MachoResolveAddress(&entry->main, file_relative);
        if (s && s->name && s->name[0]) {
            *out_name = s->name;
            if (!name_has_nul)
                continue;
            MachoSymbol sym;
            sym.name          = (Zstr)(str_base + n_strx);
            sym.value         = n_value;
    // same section (or the section end). N_STAB entries are skipped:
    // stab iff any of the high three bits of n_type is set.
    const MachoSymbol *MachoResolveAddress(const Macho *self, u64 vaddr) {
        if (!self || VecLen(&self->symbols) == 0)
            return NULL;
        };
    
        const MachoSymbol *best       = NULL;
        u64                best_value = 0;
        const MachoSymbol *next_above = NULL;
        const MachoSymbol *best       = NULL;
        u64                best_value = 0;
        const MachoSymbol *next_above = NULL;
        u64                next_value = (u64)-1;
    
        for (size i = 0; i < VecLen(&self->symbols); ++i) {
            const MachoSymbol *s = VecPtrAt(&self->symbols, i);
            if (s->type & N_STAB_MASK)
                continue; // any high bit set => STAB (debug) entry
    
        // Address at the function start.
        const MachoSymbol *s  = MachoResolveAddress(&m, 0x100000010ull);
        bool               ok = s && s->name && ZstrCompare(s->name, "my_function") == 0;
    
        // Inside the first symbol's span [0x10, 0x40): resolves to it.
        const MachoSymbol *s = MachoResolveAddress(&m, 0x100000010ull);
        ok                   = ok && s != NULL && s->value == 0x100000010ull;
        s                    = MachoResolveAddress(&m, 0x100000030ull);
        u64 vaddr        = runtime_addr - slide;
    
        const MachoSymbol *sym = MachoResolveAddress(&m, vaddr);
        bool               ok  = sym != NULL && sym->name != NULL &&
                  ZstrFindSubstring(sym->name, "test_macho_resolves_running_binary_symbol") != NULL;
        ok       = ok && VecLen(&m.symbols) == 2;
        if (VecLen(&m.symbols) == 2) {
            const MachoSymbol *s0 = VecPtrAt(&m.symbols, 0);
            const MachoSymbol *s1 = VecPtrAt(&m.symbols, 1);
            ok = ok && ZstrCompare(s0->name, "alpha") == 0 && s0->value == 0x100000010ull && s0->type == 0x0F &&
        if (VecLen(&m.symbols) == 2) {
            const MachoSymbol *s0 = VecPtrAt(&m.symbols, 0);
            const MachoSymbol *s1 = VecPtrAt(&m.symbols, 1);
            ok = ok && ZstrCompare(s0->name, "alpha") == 0 && s0->value == 0x100000010ull && s0->type == 0x0F &&
                 s0->section_index == 1;
    
        // Query above both; correct best is the 0x...40 symbol (max <= vaddr).
        const MachoSymbol *s = MachoResolveAddress(&m, 0x100000050ull);
        ok                   = ok && s != NULL && s->value == 0x100000040ull;
        bool ok = VecLen(&m.symbols) == 2;
    
        const MachoSymbol *s = MachoResolveAddress(&m, 0x100000020ull);
        // The later equal-valued symbol (n_sect 2) wins under `>=`.
        ok = ok && s != NULL && s->value == 0x100000010ull && s->section_index == 2;
Last updated on