structstd.debug.Dwarf.FrameDescriptionEntry[src]

Fields

cie_length_offset: u64
pc_begin: u64
pc_range: u64
lsda_pointer: ?u64
aug_data: []const u8
instructions: []const u8

Functions

Functionparse[src]

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

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.

Parameters

fde_bytes: []const u8
pc_rel_offset: i64
is_runtime: bool
addr_size_bytes: u8

Source Code

Source code
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,
    };
}

Source Code

Source code
pub const FrameDescriptionEntry = struct {
    // Offset into eh_frame where the CIE for this FDE is stored
    cie_length_offset: u64,

    pc_begin: u64,
    pc_range: u64,
    lsda_pointer: ?u64,
    aug_data: []const u8,
    instructions: []const u8,

    /// 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.
    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,
        };
    }
}