DoxigAlpha

scanAllUnwindInfo

If .eh_frame_hdr is present, then only the header needs to be parsed. Otherwise, .eh_frame and .debug_frame are scanned and a sorted list of FDEs is built for binary searching during unwinding. Even if .eh_frame_hdr is used, we may find during unwinding that it's incomplete, in which case we build the sorted list of FDEs at that point.

See also scanCieFdeInfo.

Function parameters

Parameters

#
di:*Dwarf
base_address:usize

Type definitions in this namespace

Types

#
ExceptionFrameHeader
This represents the decoded .eh_frame_hdr header

Initialize DWARF info.

Functions

#
open
Initialize DWARF info.
findCompileUnit
TODO: change this to binary searching the sorted compile unit list
scanAllUnwindInfo
If `.eh_frame_hdr` is present, then only the header needs to be parsed.
scanCieFdeInfo
Scan `.eh_frame` and `.debug_frame` and build a sorted list of FDEs for binary searching during
compactUnwindToDwarfRegNumber
Returns the DWARF register number for an x86_64 register number found in compact unwind info
bad
This function is to make it handy to comment out the return and make it

Error sets in this namespace

Error Sets

#

= [_]?Section{null} ** num_sections

Values

#
null_section_array
= [_]?Section{null} ** num_sections

Source

Implementation

#
pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void {
    if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: {
        var fbr: FixedBufferReader = .{ .buf = eh_frame_hdr, .endian = native_endian };

        const version = try fbr.readByte();
        if (version != 1) break :blk;

        const eh_frame_ptr_enc = try fbr.readByte();
        if (eh_frame_ptr_enc == EH.PE.omit) break :blk;
        const fde_count_enc = try fbr.readByte();
        if (fde_count_enc == EH.PE.omit) break :blk;
        const table_enc = try fbr.readByte();
        if (table_enc == EH.PE.omit) break :blk;

        const eh_frame_ptr = cast(usize, try readEhPointer(&fbr, eh_frame_ptr_enc, @sizeOf(usize), .{
            .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
            .follow_indirect = true,
        }) orelse return bad()) orelse return bad();

        const fde_count = cast(usize, try readEhPointer(&fbr, fde_count_enc, @sizeOf(usize), .{
            .pc_rel_base = @intFromPtr(&eh_frame_hdr[fbr.pos]),
            .follow_indirect = true,
        }) orelse return bad()) orelse return bad();

        const entry_size = try ExceptionFrameHeader.entrySize(table_enc);
        const entries_len = fde_count * entry_size;
        if (entries_len > eh_frame_hdr.len - fbr.pos) return bad();

        di.eh_frame_hdr = .{
            .eh_frame_ptr = eh_frame_ptr,
            .table_enc = table_enc,
            .fde_count = fde_count,
            .entries = eh_frame_hdr[fbr.pos..][0..entries_len],
        };

        // No need to scan .eh_frame, we have a binary search table already
        return;
    }

    try di.scanCieFdeInfo(allocator, base_address);
}