struct 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

Members

Source

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