authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-27 10:49:41+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-27 15:36:28+01:00
loga70cbe779adb11faeb88ceffad0cfa729d2eec6e
treecae766015244a655915bb0cde09ece4ed4c20945
parentaf9a9a13747b1e7007e29ff4f76e700f5bd7f7cf

macho: add Zig wrapper for compact unwind encoding on arm64


1 files changed, 103 insertions(+), 5 deletions(-)

lib/std/macho.zig+103-5
...@@ -1931,8 +1931,6 @@ pub const compact_unwind_entry = extern struct {...@@ -1931,8 +1931,6 @@ pub const compact_unwind_entry = extern struct {
1931// to the page (4096 byte block) containing the unwind info for that function.1931// to the page (4096 byte block) containing the unwind info for that function.
19321932
1933pub const UNWIND_SECTION_VERSION = 1;1933pub const UNWIND_SECTION_VERSION = 1;
1934pub const UNWIND_SECOND_LEVEL_REGULAR = 2;
1935pub const UNWIND_SECOND_LEVEL_COMPRESSED = 3;
19361934
1937pub const unwind_info_section_header = extern struct {1935pub const unwind_info_section_header = extern struct {
1938 /// UNWIND_SECTION_VERSION1936 /// UNWIND_SECTION_VERSION
...@@ -1974,9 +1972,15 @@ pub const unwind_info_regular_second_level_entry = extern struct {...@@ -1974,9 +1972,15 @@ pub const unwind_info_regular_second_level_entry = extern struct {
1974 encoding: compact_unwind_encoding_t,1972 encoding: compact_unwind_encoding_t,
1975};1973};
19761974
1975pub const UNWIND_SECOND_LEVEL = enum(u32) {
1976 REGULAR = 2,
1977 COMPRESSED = 3,
1978 _,
1979};
1980
1977pub const unwind_info_regular_second_level_page_header = extern struct {1981pub const unwind_info_regular_second_level_page_header = extern struct {
1978 /// UNWIND_SECOND_LEVEL_REGULAR1982 /// UNWIND_SECOND_LEVEL_REGULAR
1979 kind: u32 = UNWIND_SECOND_LEVEL_REGULAR,1983 kind: UNWIND_SECOND_LEVEL = .REGULAR,
19801984
1981 entryPageOffset: u16,1985 entryPageOffset: u16,
1982 entryCount: u16,1986 entryCount: u16,
...@@ -1985,7 +1989,7 @@ pub const unwind_info_regular_second_level_page_header = extern struct {...@@ -1985,7 +1989,7 @@ pub const unwind_info_regular_second_level_page_header = extern struct {
19851989
1986pub const unwind_info_compressed_second_level_page_header = extern struct {1990pub const unwind_info_compressed_second_level_page_header = extern struct {
1987 /// UNWIND_SECOND_LEVEL_COMPRESSED1991 /// UNWIND_SECOND_LEVEL_COMPRESSED
1988 kind: u32 = UNWIND_SECOND_LEVEL_COMPRESSED,1992 kind: UNWIND_SECOND_LEVEL = .COMPRESSED,
19891993
1990 entryPageOffset: u16,1994 entryPageOffset: u16,
1991 entryCount: u16,1995 entryCount: u16,
...@@ -1995,7 +1999,101 @@ pub const unwind_info_compressed_second_level_page_header = extern struct {...@@ -1995,7 +1999,101 @@ pub const unwind_info_compressed_second_level_page_header = extern struct {
1995 // encodings array1999 // encodings array
1996};2000};
19972001
1998pub const UnwindInfoCompressedEntry = packed struct(u32) {2002pub const UnwindInfoCompressedEntry = packed struct {
1999 funcOffset: u24,2003 funcOffset: u24,
2000 encodingIndex: u8,2004 encodingIndex: u8,
2001};2005};
2006
2007// TODO add corresponding x86_64 tagged union
2008pub const UnwindEncodingArm64 = union(enum) {
2009 frame: Frame,
2010 frameless: Frameless,
2011 dwarf: Dwarf,
2012
2013 pub const Frame = packed struct {
2014 x_reg_pairs: packed struct {
2015 x19_x20: u1,
2016 x21_x22: u1,
2017 x23_x24: u1,
2018 x25_x26: u1,
2019 x27_x28: u1,
2020 },
2021 d_reg_pairs: packed struct {
2022 d8_d9: u1,
2023 d10_d11: u1,
2024 d12_d13: u1,
2025 d14_d15: u1,
2026 },
2027 unused: u15,
2028 mode: Mode = .frame,
2029 personality_index: u2,
2030 has_lsda: u1,
2031 start: u1,
2032 };
2033
2034 pub const Frameless = packed struct {
2035 unused: u12 = 0,
2036 stack_size: u12,
2037 mode: Mode = .frameless,
2038 personality_index: u2,
2039 has_lsda: u1,
2040 start: u1,
2041 };
2042
2043 pub const Dwarf = packed struct {
2044 section_offset: u24,
2045 mode: Mode = .dwarf,
2046 personality_index: u2,
2047 has_lsda: u1,
2048 start: u1,
2049 };
2050
2051 pub const Mode = enum(u4) {
2052 frameless = 0x2,
2053 dwarf = 0x3,
2054 frame = 0x4,
2055 _,
2056 };
2057
2058 pub const mode_mask: u32 = 0x0F000000;
2059
2060 pub fn fromU32(enc: u32) !UnwindEncodingArm64 {
2061 const m = (enc & mode_mask) >> 24;
2062 return switch (@intToEnum(Mode, m)) {
2063 .frame => .{ .frame = @bitCast(Frame, enc) },
2064 .frameless => .{ .frameless = @bitCast(Frameless, enc) },
2065 .dwarf => .{ .dwarf = @bitCast(Dwarf, enc) },
2066 else => return error.UnknownEncoding,
2067 };
2068 }
2069
2070 pub fn toU32(enc: UnwindEncodingArm64) u32 {
2071 return switch (enc) {
2072 inline else => |x| @bitCast(u32, x),
2073 };
2074 }
2075
2076 pub fn start(enc: UnwindEncodingArm64) bool {
2077 return switch (enc) {
2078 inline else => |x| x.start == 0b1,
2079 };
2080 }
2081
2082 pub fn hasLsda(enc: UnwindEncodingArm64) bool {
2083 return switch (enc) {
2084 inline else => |x| x.has_lsda == 0b1,
2085 };
2086 }
2087
2088 pub fn personalityIndex(enc: UnwindEncodingArm64) u2 {
2089 return switch (enc) {
2090 inline else => |x| x.personality_index,
2091 };
2092 }
2093
2094 pub fn mode(enc: UnwindEncodingArm64) Mode {
2095 return switch (enc) {
2096 inline else => |x| x.mode,
2097 };
2098 }
2099};