DoxigAlpha

parse

This function expects to read the FDE starting at the PC Begin field. The returned struct references memory backed by fde_bytes.

pc_rel_offset specifies an offset to be applied to pc_rel_base values used when decoding pointers. This should be set to zero if fde_bytes is backed by the memory of a .eh_frame / .debug_frame section in the running executable. Otherwise, it should be the relative offset to translate addresses from where the section is currently stored in memory, to where it would be stored at runtime: section base addr - backing data base ptr.

Similarly, is_runtime specifies this function is being called on a runtime section, and so indirect pointers can be followed.

Function parameters

Parameters

#
fde_bytes:[]const u8
pc_rel_offset:i64
is_runtime:bool
addr_size_bytes:u8
endian:std.builtin.Endian

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 parse(
    fde_bytes: []const u8,
    pc_rel_offset: i64,
    is_runtime: bool,
    cie: CommonInformationEntry,
    addr_size_bytes: u8,
    endian: std.builtin.Endian,
) !FrameDescriptionEntry {
    if (addr_size_bytes > 8) return error.InvalidAddrSize;

    var fbr: FixedBufferReader = .{ .buf = fde_bytes, .endian = endian };

    const pc_begin = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{
        .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.pos]), pc_rel_offset),
        .follow_indirect = is_runtime,
    }) orelse return bad();

    const pc_range = try readEhPointer(&fbr, cie.fde_pointer_enc, addr_size_bytes, .{
        .pc_rel_base = 0,
        .follow_indirect = false,
    }) orelse return bad();

    var aug_data: []const u8 = &[_]u8{};
    const lsda_pointer = if (cie.aug_str.len > 0) blk: {
        const aug_data_len = try fbr.readUleb128(usize);
        const aug_data_start = fbr.pos;
        aug_data = fde_bytes[aug_data_start..][0..aug_data_len];

        const lsda_pointer = if (cie.lsda_pointer_enc != EH.PE.omit)
            try readEhPointer(&fbr, cie.lsda_pointer_enc, addr_size_bytes, .{
                .pc_rel_base = try pcRelBase(@intFromPtr(&fde_bytes[fbr.pos]), pc_rel_offset),
                .follow_indirect = is_runtime,
            })
        else
            null;

        fbr.pos = aug_data_start + aug_data_len;
        break :blk lsda_pointer;
    } else null;

    const instructions = fde_bytes[fbr.pos..];
    return .{
        .cie_length_offset = cie.length_offset,
        .pc_begin = pc_begin,
        .pc_range = pc_range,
        .lsda_pointer = lsda_pointer,
        .aug_data = aug_data,
        .instructions = instructions,
    };
}