Skip to content

DwarfFde

Description

Decoded FDE record. pc_begin and pc_range are file-relative virtual addresses (the same address-space ElfSymbol.value uses). instructions is the per-FDE CFI bytecode that runs after the CIE’s initial instructions.

Usage example (Cross-references)

Usage examples (Cross-references)
        void            *runtime_addr,
        const DwarfCfi **out_cfi,
        const DwarfFde **out_fde,
        u64             *out_module_base
    );
        const u8 *instructions;
        u64       instructions_size;
    } DwarfFde;
    
    typedef Vec(DwarfCie) DwarfCies;
    
    typedef Vec(DwarfCie) DwarfCies;
    typedef Vec(DwarfFde) DwarfFdes;
    
    ///
    /// TAGS: Parser, DWARF, CFI, Lookup
    ///
    const DwarfFde *DwarfCfiFindFde(const DwarfCfi *self, u64 vaddr);
    
    ///
    /// TAGS: Parser, DWARF, CFI, Unwind
    ///
    bool DwarfCfiBuildRow(const DwarfCfi *cfi, const DwarfFde *fde, u64 target_pc, DwarfUnwindRow *out);
    
    // ===========================================================================
        void            *runtime_addr,
        const DwarfCfi **out_cfi,
        const DwarfFde **out_fde,
        u64             *out_module_base
    ) {
    
        u64             file_relative = addr - load_base;
        const DwarfFde *fde           = DwarfCfiFindFde(&cache_entry->cfi, file_relative);
        if (!fde)
            return false;
    
            const DwarfCfi *cfi         = NULL;
            const DwarfFde *fde         = NULL;
            u64             module_base = 0;
            if (!SymbolResolverFindFde(resolver, (void *)(u64)rip, &cfi, &fde, &module_base))
        const u8       *section_data,
        u64             section_addr,
        DwarfFde       *out
    ) {
        MemSet(out, 0, sizeof(*out));
                    cie_offset = id_field_off - (u64)id;
                }
                DwarfFde fde;
                BufIter  body = BufIterFromMemory(IterDataAt(&section_cur, IterIndex(&section_cur)), length32 - 4);
                if (parse_fde(&body, rec_start, cie_offset, out, section_data, section_addr, &fde)) {
    }
    
    const DwarfFde *DwarfCfiFindFde(const DwarfCfi *self, u64 vaddr) {
        if (!self)
            return NULL;
        // Linear scan -- fine up to a few thousand FDEs.
        for (u64 i = 0; i < VecLen(&self->fdes); ++i) {
            const DwarfFde *f = VecPtrAt(&self->fdes, i);
            if (vaddr >= f->pc_begin && vaddr < f->pc_begin + f->pc_range) {
                return f;
    }
    
    bool DwarfCfiBuildRow(const DwarfCfi *cfi, const DwarfFde *fde, u64 target_pc, DwarfUnwindRow *out) {
        if (!cfi || !fde || !out)
            return false;
        bool     ok = DwarfCfiBuildFromElf(&cfi, &elf, base);
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
        bool     ok = DwarfCfiBuildFromElf(&cfi, &elf, base);
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
        bool     ok = DwarfCfiBuildFromElf(&cfi, &elf, base);
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
        bool     ok = DwarfCfiBuildFromElf(&cfi, &elf, base);
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
            DwarfCfi cfi;
            if (DwarfCfiBuildFromElf(&cfi, &elf, base)) {
                const DwarfFde *fde = DwarfCfiFindFde(&cfi, 0x5000);
                DwarfUnwindRow  row;
                // eh_frame_addr must record the .debug_frame section's address (the
            DwarfCfi cfi;
            if (DwarfCfiBuildFromElf(&cfi, &elf, base)) {
                const DwarfFde *fde = DwarfCfiFindFde(&cfi, 0x1000);
                DwarfUnwindRow  row;
                ok = fde != NULL && DwarfCfiBuildRow(&cfi, fde, 0x1080, &row) // in range -> ok
            DwarfCfi cfi;
            if (DwarfCfiBuildFromElf(&cfi, &elf, base)) {
                const DwarfFde *fde = DwarfCfiFindFde(&cfi, 0x1000);
                ok                  = fde != NULL && fde->offset == fde_off;
                DwarfCfiDeinit(&cfi);
        // parsed now, so a "no FDE" outcome means the unwinder is broken on this
        // toolchain (the historic clang .debug_frame gap), not correct behaviour.
        const DwarfFde *fde = built ? DwarfCfiFindFde(&cfi, file_relative) : NULL;
        bool            ok  = built && fde != NULL;
        if (ok) {
Last updated on