feature. See also
. The project being documented here (as the example) is the Zig library itself.
Unwind.CommonInformationEntry
pub const CommonInformationEntry = struct
File
Code
pub const CommonInformationEntry = struct {
version: u8,
format: Format,
addr_size_bytes: u8,
segment_selector_size: u8,
code_alignment_factor: u32,
data_alignment_factor: i32,
return_address_register: u8,
fde_pointer_enc: EH.PE,
is_signal_frame: bool,
augmentation_kind: AugmentationKind,
initial_instructions: []const u8,
last_row: ?struct {
offset: u64,
cfa: VirtualMachine.CfaRule,
cols: []VirtualMachine.Column,
},
pub const AugmentationKind = enum { none, gcc_eh, lsb_z };
fn parse(
format: Format,
cie_bytes: []const u8,
section: Section,
default_addr_size_bytes: u8,
) !CommonInformationEntry {
var r: Reader = .fixed(cie_bytes);
const version = try r.takeByte();
switch (section) {
.eh_frame => if (version != 1 and version != 3) return error.UnsupportedDwarfVersion,
.debug_frame => if (version != 4) return error.UnsupportedDwarfVersion,
}
const aug_str = try r.takeSentinel(0);
const aug_kind: AugmentationKind = aug: {
if (aug_str.len == 0) break :aug .none;
if (aug_str[0] == 'z') break :aug .lsb_z;
if (std.mem.eql(u8, aug_str, "eh")) break :aug .gcc_eh;
return bad();
};
switch (aug_kind) {
.none => {},
.lsb_z => {},
.gcc_eh => try r.discardAll(default_addr_size_bytes),
}
const addr_size_bytes = if (version == 4) try r.takeByte() else default_addr_size_bytes;
const segment_selector_size: u8 = if (version == 4) try r.takeByte() else 0;
const code_alignment_factor = try r.takeLeb128(u32);
const data_alignment_factor = try r.takeLeb128(i32);
const return_address_register = if (version == 1) try r.takeByte() else try r.takeLeb128(u8);
const fde_pointer_enc: EH.PE, const is_signal_frame: bool = aug: {
const default_fde_pointer_enc: EH.PE = .{ .type = .absptr, .rel = .abs };
if (aug_kind != .lsb_z) break :aug .{ default_fde_pointer_enc, false };
const aug_data_len = try r.takeLeb128(u32);
var aug_data: Reader = .fixed(try r.take(aug_data_len));
var fde_pointer_enc: EH.PE = default_fde_pointer_enc;
var is_signal_frame = false;
for (aug_str[1..]) |byte| switch (byte) {
'L' => _ = try aug_data.takeByte(),
'P' => {
const enc: EH.PE = @bitCast(try aug_data.takeByte());
const endian: Endian = .little;
_ = try readEhPointerAbs(&aug_data, enc.type, addr_size_bytes, endian);
},
'R' => fde_pointer_enc = @bitCast(try aug_data.takeByte()),
'S' => is_signal_frame = true,
'B', 'G' => {},
else => return bad(),
};
break :aug .{ fde_pointer_enc, is_signal_frame };
};
return .{
.format = format,
.version = version,
.addr_size_bytes = addr_size_bytes,
.segment_selector_size = segment_selector_size,
.code_alignment_factor = code_alignment_factor,
.data_alignment_factor = data_alignment_factor,
.return_address_register = return_address_register,
.fde_pointer_enc = fde_pointer_enc,
.is_signal_frame = is_signal_frame,
.augmentation_kind = aug_kind,
.initial_instructions = r.buffered(),
.last_row = null,
};
}
}