macho: add Zig wrapper for compact unwind encoding on arm64

This commit is contained in:
Jakub Konka 2022-12-27 10:49:41 +01:00
parent af9a9a1374
commit a70cbe779a

View file

@ -1931,8 +1931,6 @@ pub const compact_unwind_entry = extern struct {
// to the page (4096 byte block) containing the unwind info for that function. // to the page (4096 byte block) containing the unwind info for that function.
pub const UNWIND_SECTION_VERSION = 1; pub const UNWIND_SECTION_VERSION = 1;
pub const UNWIND_SECOND_LEVEL_REGULAR = 2;
pub const UNWIND_SECOND_LEVEL_COMPRESSED = 3;
pub const unwind_info_section_header = extern struct { pub const unwind_info_section_header = extern struct {
/// UNWIND_SECTION_VERSION /// UNWIND_SECTION_VERSION
@ -1974,9 +1972,15 @@ pub const unwind_info_regular_second_level_entry = extern struct {
encoding: compact_unwind_encoding_t, encoding: compact_unwind_encoding_t,
}; };
pub const UNWIND_SECOND_LEVEL = enum(u32) {
REGULAR = 2,
COMPRESSED = 3,
_,
};
pub const unwind_info_regular_second_level_page_header = extern struct { pub const unwind_info_regular_second_level_page_header = extern struct {
/// UNWIND_SECOND_LEVEL_REGULAR /// UNWIND_SECOND_LEVEL_REGULAR
kind: u32 = UNWIND_SECOND_LEVEL_REGULAR, kind: UNWIND_SECOND_LEVEL = .REGULAR,
entryPageOffset: u16, entryPageOffset: u16,
entryCount: u16, entryCount: u16,
@ -1985,7 +1989,7 @@ pub const unwind_info_regular_second_level_page_header = extern struct {
pub const unwind_info_compressed_second_level_page_header = extern struct { pub const unwind_info_compressed_second_level_page_header = extern struct {
/// UNWIND_SECOND_LEVEL_COMPRESSED /// UNWIND_SECOND_LEVEL_COMPRESSED
kind: u32 = UNWIND_SECOND_LEVEL_COMPRESSED, kind: UNWIND_SECOND_LEVEL = .COMPRESSED,
entryPageOffset: u16, entryPageOffset: u16,
entryCount: u16, entryCount: u16,
@ -1995,7 +1999,101 @@ pub const unwind_info_compressed_second_level_page_header = extern struct {
// encodings array // encodings array
}; };
pub const UnwindInfoCompressedEntry = packed struct(u32) { pub const UnwindInfoCompressedEntry = packed struct {
funcOffset: u24, funcOffset: u24,
encodingIndex: u8, encodingIndex: u8,
}; };
// TODO add corresponding x86_64 tagged union
pub const UnwindEncodingArm64 = union(enum) {
frame: Frame,
frameless: Frameless,
dwarf: Dwarf,
pub const Frame = packed struct {
x_reg_pairs: packed struct {
x19_x20: u1,
x21_x22: u1,
x23_x24: u1,
x25_x26: u1,
x27_x28: u1,
},
d_reg_pairs: packed struct {
d8_d9: u1,
d10_d11: u1,
d12_d13: u1,
d14_d15: u1,
},
unused: u15,
mode: Mode = .frame,
personality_index: u2,
has_lsda: u1,
start: u1,
};
pub const Frameless = packed struct {
unused: u12 = 0,
stack_size: u12,
mode: Mode = .frameless,
personality_index: u2,
has_lsda: u1,
start: u1,
};
pub const Dwarf = packed struct {
section_offset: u24,
mode: Mode = .dwarf,
personality_index: u2,
has_lsda: u1,
start: u1,
};
pub const Mode = enum(u4) {
frameless = 0x2,
dwarf = 0x3,
frame = 0x4,
_,
};
pub const mode_mask: u32 = 0x0F000000;
pub fn fromU32(enc: u32) !UnwindEncodingArm64 {
const m = (enc & mode_mask) >> 24;
return switch (@intToEnum(Mode, m)) {
.frame => .{ .frame = @bitCast(Frame, enc) },
.frameless => .{ .frameless = @bitCast(Frameless, enc) },
.dwarf => .{ .dwarf = @bitCast(Dwarf, enc) },
else => return error.UnknownEncoding,
};
}
pub fn toU32(enc: UnwindEncodingArm64) u32 {
return switch (enc) {
inline else => |x| @bitCast(u32, x),
};
}
pub fn start(enc: UnwindEncodingArm64) bool {
return switch (enc) {
inline else => |x| x.start == 0b1,
};
}
pub fn hasLsda(enc: UnwindEncodingArm64) bool {
return switch (enc) {
inline else => |x| x.has_lsda == 0b1,
};
}
pub fn personalityIndex(enc: UnwindEncodingArm64) u2 {
return switch (enc) {
inline else => |x| x.personality_index,
};
}
pub fn mode(enc: UnwindEncodingArm64) Mode {
return switch (enc) {
inline else => |x| x.mode,
};
}
};