structstd.debug.Dwarf.CommonInformationEntry[src]

Fields

length_offset: u64
version: u8
address_size: u8
format: Format
segment_selector_size: ?u8
code_alignment_factor: u32
data_alignment_factor: i32
return_address_register: u8
aug_str: []const u8
aug_data: []const u8
lsda_pointer_enc: u8
personality_enc: ?u8
personality_routine_pointer: ?u64
fde_pointer_enc: u8
initial_instructions: []const u8

Values

Constanteh_id[src]

Source Code

Source code
pub const eh_id = 0

Constantdwarf32_id[src]

Source Code

Source code
pub const dwarf32_id = maxInt(u32)

Constantdwarf64_id[src]

Source Code

Source code
pub const dwarf64_id = maxInt(u64)

Functions

FunctionisSignalFrame[src]

pub fn isSignalFrame(self: CommonInformationEntry) bool

Parameters

Source Code

Source code
pub fn isSignalFrame(self: CommonInformationEntry) bool {
    for (self.aug_str) |c| if (c == 'S') return true;
    return false;
}

FunctionaddressesSignedWithBKey[src]

pub fn addressesSignedWithBKey(self: CommonInformationEntry) bool

Parameters

Source Code

Source code
pub fn addressesSignedWithBKey(self: CommonInformationEntry) bool {
    for (self.aug_str) |c| if (c == 'B') return true;
    return false;
}

FunctionmteTaggedFrame[src]

pub fn mteTaggedFrame(self: CommonInformationEntry) bool

Parameters

Source Code

Source code
pub fn mteTaggedFrame(self: CommonInformationEntry) bool {
    for (self.aug_str) |c| if (c == 'G') return true;
    return false;
}

Functionparse[src]

pub fn parse( cie_bytes: []const u8, pc_rel_offset: i64, is_runtime: bool, format: Format, dwarf_section: Section.Id, length_offset: u64, addr_size_bytes: u8, endian: std.builtin.Endian, ) !CommonInformationEntry

This function expects to read the CIE starting with the version field. The returned struct references memory backed by cie_bytes.

See the FrameDescriptionEntry.parse documentation for the description of pc_rel_offset and is_runtime.

length_offset specifies the offset of this CIE's length field in the .eh_frame / .debug_frame section.

Parameters

cie_bytes: []const u8
pc_rel_offset: i64
is_runtime: bool
format: Format
dwarf_section: Section.Id
length_offset: u64
addr_size_bytes: u8

Source Code

Source code
pub fn parse(
    cie_bytes: []const u8,
    pc_rel_offset: i64,
    is_runtime: bool,
    format: Format,
    dwarf_section: Section.Id,
    length_offset: u64,
    addr_size_bytes: u8,
    endian: std.builtin.Endian,
) !CommonInformationEntry {
    if (addr_size_bytes > 8) return error.UnsupportedAddrSize;

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

    const version = try fbr.readByte();
    switch (dwarf_section) {
        .eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,
        .debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,
        else => return error.UnsupportedDwarfSection,
    }

    var has_eh_data = false;
    var has_aug_data = false;

    var aug_str_len: usize = 0;
    const aug_str_start = fbr.pos;
    var aug_byte = try fbr.readByte();
    while (aug_byte != 0) : (aug_byte = try fbr.readByte()) {
        switch (aug_byte) {
            'z' => {
                if (aug_str_len != 0) return bad();
                has_aug_data = true;
            },
            'e' => {
                if (has_aug_data or aug_str_len != 0) return bad();
                if (try fbr.readByte() != 'h') return bad();
                has_eh_data = true;
            },
            else => if (has_eh_data) return bad(),
        }

        aug_str_len += 1;
    }

    if (has_eh_data) {
        // legacy data created by older versions of gcc - unsupported here
        for (0..addr_size_bytes) |_| _ = try fbr.readByte();
    }

    const address_size = if (version == 4) try fbr.readByte() else addr_size_bytes;
    const segment_selector_size = if (version == 4) try fbr.readByte() else null;

    const code_alignment_factor = try fbr.readUleb128(u32);
    const data_alignment_factor = try fbr.readIleb128(i32);
    const return_address_register = if (version == 1) try fbr.readByte() else try fbr.readUleb128(u8);

    var lsda_pointer_enc: u8 = EH.PE.omit;
    var personality_enc: ?u8 = null;
    var personality_routine_pointer: ?u64 = null;
    var fde_pointer_enc: u8 = EH.PE.absptr;

    var aug_data: []const u8 = &[_]u8{};
    const aug_str = if (has_aug_data) blk: {
        const aug_data_len = try fbr.readUleb128(usize);
        const aug_data_start = fbr.pos;
        aug_data = cie_bytes[aug_data_start..][0..aug_data_len];

        const aug_str = cie_bytes[aug_str_start..][0..aug_str_len];
        for (aug_str[1..]) |byte| {
            switch (byte) {
                'L' => {
                    lsda_pointer_enc = try fbr.readByte();
                },
                'P' => {
                    personality_enc = try fbr.readByte();
                    personality_routine_pointer = try readEhPointer(&fbr, personality_enc.?, addr_size_bytes, .{
                        .pc_rel_base = try pcRelBase(@intFromPtr(&cie_bytes[fbr.pos]), pc_rel_offset),
                        .follow_indirect = is_runtime,
                    });
                },
                'R' => {
                    fde_pointer_enc = try fbr.readByte();
                },
                'S', 'B', 'G' => {},
                else => return bad(),
            }
        }

        // aug_data_len can include padding so the CIE ends on an address boundary
        fbr.pos = aug_data_start + aug_data_len;
        break :blk aug_str;
    } else &[_]u8{};

    const initial_instructions = cie_bytes[fbr.pos..];
    return .{
        .length_offset = length_offset,
        .version = version,
        .address_size = address_size,
        .format = format,
        .segment_selector_size = segment_selector_size,
        .code_alignment_factor = code_alignment_factor,
        .data_alignment_factor = data_alignment_factor,
        .return_address_register = return_address_register,
        .aug_str = aug_str,
        .aug_data = aug_data,
        .lsda_pointer_enc = lsda_pointer_enc,
        .personality_enc = personality_enc,
        .personality_routine_pointer = personality_routine_pointer,
        .fde_pointer_enc = fde_pointer_enc,
        .initial_instructions = initial_instructions,
    };
}

Source Code

Source code
pub const CommonInformationEntry = struct {
    // Used in .eh_frame
    pub const eh_id = 0;

    // Used in .debug_frame (DWARF32)
    pub const dwarf32_id = maxInt(u32);

    // Used in .debug_frame (DWARF64)
    pub const dwarf64_id = maxInt(u64);

    // Offset of the length field of this entry in the eh_frame section.
    // This is the key that FDEs use to reference CIEs.
    length_offset: u64,
    version: u8,
    address_size: u8,
    format: Format,

    // Only present in version 4
    segment_selector_size: ?u8,

    code_alignment_factor: u32,
    data_alignment_factor: i32,
    return_address_register: u8,

    aug_str: []const u8,
    aug_data: []const u8,
    lsda_pointer_enc: u8,
    personality_enc: ?u8,
    personality_routine_pointer: ?u64,
    fde_pointer_enc: u8,
    initial_instructions: []const u8,

    pub fn isSignalFrame(self: CommonInformationEntry) bool {
        for (self.aug_str) |c| if (c == 'S') return true;
        return false;
    }

    pub fn addressesSignedWithBKey(self: CommonInformationEntry) bool {
        for (self.aug_str) |c| if (c == 'B') return true;
        return false;
    }

    pub fn mteTaggedFrame(self: CommonInformationEntry) bool {
        for (self.aug_str) |c| if (c == 'G') return true;
        return false;
    }

    /// This function expects to read the CIE starting with the version field.
    /// The returned struct references memory backed by cie_bytes.
    ///
    /// See the FrameDescriptionEntry.parse documentation for the description
    /// of `pc_rel_offset` and `is_runtime`.
    ///
    /// `length_offset` specifies the offset of this CIE's length field in the
    /// .eh_frame / .debug_frame section.
    pub fn parse(
        cie_bytes: []const u8,
        pc_rel_offset: i64,
        is_runtime: bool,
        format: Format,
        dwarf_section: Section.Id,
        length_offset: u64,
        addr_size_bytes: u8,
        endian: std.builtin.Endian,
    ) !CommonInformationEntry {
        if (addr_size_bytes > 8) return error.UnsupportedAddrSize;

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

        const version = try fbr.readByte();
        switch (dwarf_section) {
            .eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,
            .debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,
            else => return error.UnsupportedDwarfSection,
        }

        var has_eh_data = false;
        var has_aug_data = false;

        var aug_str_len: usize = 0;
        const aug_str_start = fbr.pos;
        var aug_byte = try fbr.readByte();
        while (aug_byte != 0) : (aug_byte = try fbr.readByte()) {
            switch (aug_byte) {
                'z' => {
                    if (aug_str_len != 0) return bad();
                    has_aug_data = true;
                },
                'e' => {
                    if (has_aug_data or aug_str_len != 0) return bad();
                    if (try fbr.readByte() != 'h') return bad();
                    has_eh_data = true;
                },
                else => if (has_eh_data) return bad(),
            }

            aug_str_len += 1;
        }

        if (has_eh_data) {
            // legacy data created by older versions of gcc - unsupported here
            for (0..addr_size_bytes) |_| _ = try fbr.readByte();
        }

        const address_size = if (version == 4) try fbr.readByte() else addr_size_bytes;
        const segment_selector_size = if (version == 4) try fbr.readByte() else null;

        const code_alignment_factor = try fbr.readUleb128(u32);
        const data_alignment_factor = try fbr.readIleb128(i32);
        const return_address_register = if (version == 1) try fbr.readByte() else try fbr.readUleb128(u8);

        var lsda_pointer_enc: u8 = EH.PE.omit;
        var personality_enc: ?u8 = null;
        var personality_routine_pointer: ?u64 = null;
        var fde_pointer_enc: u8 = EH.PE.absptr;

        var aug_data: []const u8 = &[_]u8{};
        const aug_str = if (has_aug_data) blk: {
            const aug_data_len = try fbr.readUleb128(usize);
            const aug_data_start = fbr.pos;
            aug_data = cie_bytes[aug_data_start..][0..aug_data_len];

            const aug_str = cie_bytes[aug_str_start..][0..aug_str_len];
            for (aug_str[1..]) |byte| {
                switch (byte) {
                    'L' => {
                        lsda_pointer_enc = try fbr.readByte();
                    },
                    'P' => {
                        personality_enc = try fbr.readByte();
                        personality_routine_pointer = try readEhPointer(&fbr, personality_enc.?, addr_size_bytes, .{
                            .pc_rel_base = try pcRelBase(@intFromPtr(&cie_bytes[fbr.pos]), pc_rel_offset),
                            .follow_indirect = is_runtime,
                        });
                    },
                    'R' => {
                        fde_pointer_enc = try fbr.readByte();
                    },
                    'S', 'B', 'G' => {},
                    else => return bad(),
                }
            }

            // aug_data_len can include padding so the CIE ends on an address boundary
            fbr.pos = aug_data_start + aug_data_len;
            break :blk aug_str;
        } else &[_]u8{};

        const initial_instructions = cie_bytes[fbr.pos..];
        return .{
            .length_offset = length_offset,
            .version = version,
            .address_size = address_size,
            .format = format,
            .segment_selector_size = segment_selector_size,
            .code_alignment_factor = code_alignment_factor,
            .data_alignment_factor = data_alignment_factor,
            .return_address_register = return_address_register,
            .aug_str = aug_str,
            .aug_data = aug_data,
            .lsda_pointer_enc = lsda_pointer_enc,
            .personality_enc = personality_enc,
            .personality_routine_pointer = personality_routine_pointer,
            .fde_pointer_enc = fde_pointer_enc,
            .initial_instructions = initial_instructions,
        };
    }
}