Skip to content
DwarfCfiBuildRow

DwarfCfiBuildRow

Description

Run the CIE’s initial instructions plus the FDE’s instructions up to (but not past) target_pc, producing the unwind row that applies at that PC.

Parameters

Name Direction Description
cfi in Parsed .eh_frame index.
fde in FDE covering target_pc (caller obtained via DwarfCfiFindFde).
target_pc in File-relative virtual address inside the FDE’s [pc_begin, pc_begin+pc_range) range.
out out Populated on success.

Success

Returns true. out->cfa.kind is set to a usable rule (typically REG_OFFSET on x86-64). out->regs[ra] tells the caller where to find the previous frame’s return address.

Failure

Returns false on malformed CFI bytecode, unsupported DW_CFA_*_expression instructions, or target_pc outside the FDE. out is left zeroed.

Usage example (Cross-references)

Usage examples (Cross-references)
    
            DwarfUnwindRow row;
            if (!DwarfCfiBuildRow(cfi, fde, file_relative, &row))
                break;
    }
    
    bool DwarfCfiBuildRow(const DwarfCfi *cfi, const DwarfFde *fde, u64 target_pc, DwarfUnwindRow *out) {
        if (!cfi || !fde || !out)
            return false;
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
        }
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
        }
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
        }
        if (ok) {
            const DwarfFde *fde = DwarfCfiFindFde(&cfi, target_pc);
            ok                  = fde != NULL && DwarfCfiBuildRow(&cfi, fde, target_pc, out_row);
            DwarfCfiDeinit(&cfi);
        }
                // eh_frame_addr must record the .debug_frame section's address (the
                // fallback branch), not a constant.
                ok = fde != NULL && DwarfCfiBuildRow(&cfi, fde, 0x5000, &row) && row.cfa.reg == 7 &&
                     cfi.eh_frame_addr == EH_SECTION_VADDR;
                DwarfCfiDeinit(&cfi);
                const DwarfFde *fde = DwarfCfiFindFde(&cfi, 0x1000);
                DwarfUnwindRow  row;
                ok = fde != NULL && DwarfCfiBuildRow(&cfi, fde, 0x1080, &row) // in range -> ok
                  && !DwarfCfiBuildRow(&cfi, fde, 0x1100, &row);              // == end -> rejected
                DwarfCfiDeinit(&cfi);
                DwarfUnwindRow  row;
                ok = fde != NULL && DwarfCfiBuildRow(&cfi, fde, 0x1080, &row) // in range -> ok
                  && !DwarfCfiBuildRow(&cfi, fde, 0x1100, &row);              // == end -> rejected
                DwarfCfiDeinit(&cfi);
            }
            // leaves it in x30 with no CFI rule yet (UNDEFINED).
            DwarfUnwindRow row;
            ok = ok && DwarfCfiBuildRow(&cfi, fde, file_relative, &row);
            ok = ok && row.cfa.kind == DWARF_CFA_RULE_REG_OFFSET;
        }
Last updated on