| ... | @@ -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. |
| 1932 | | 1932 | |
| 1933 | pub const UNWIND_SECTION_VERSION = 1; | 1933 | pub const UNWIND_SECTION_VERSION = 1; |
| 1934 | pub const UNWIND_SECOND_LEVEL_REGULAR = 2; | | |
| 1935 | pub const UNWIND_SECOND_LEVEL_COMPRESSED = 3; | | |
| 1936 | | 1934 | |
| 1937 | pub const unwind_info_section_header = extern struct { | 1935 | pub const unwind_info_section_header = extern struct { |
| 1938 | /// UNWIND_SECTION_VERSION | 1936 | /// 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 | }; |
| 1976 | | 1974 | |
| | 1975 | pub const UNWIND_SECOND_LEVEL = enum(u32) { |
| | 1976 | REGULAR = 2, |
| | 1977 | COMPRESSED = 3, |
| | 1978 | _, |
| | 1979 | }; |
| | 1980 | |
| 1977 | pub const unwind_info_regular_second_level_page_header = extern struct { | 1981 | pub const unwind_info_regular_second_level_page_header = extern struct { |
| 1978 | /// UNWIND_SECOND_LEVEL_REGULAR | 1982 | /// UNWIND_SECOND_LEVEL_REGULAR |
| 1979 | kind: u32 = UNWIND_SECOND_LEVEL_REGULAR, | 1983 | kind: UNWIND_SECOND_LEVEL = .REGULAR, |
| 1980 | | 1984 | |
| 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 { |
| 1985 | | 1989 | |
| 1986 | pub const unwind_info_compressed_second_level_page_header = extern struct { | 1990 | pub const unwind_info_compressed_second_level_page_header = extern struct { |
| 1987 | /// UNWIND_SECOND_LEVEL_COMPRESSED | 1991 | /// UNWIND_SECOND_LEVEL_COMPRESSED |
| 1988 | kind: u32 = UNWIND_SECOND_LEVEL_COMPRESSED, | 1992 | kind: UNWIND_SECOND_LEVEL = .COMPRESSED, |
| 1989 | | 1993 | |
| 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 array | 1999 | // encodings array |
| 1996 | }; | 2000 | }; |
| 1997 | | 2001 | |
| 1998 | pub const UnwindInfoCompressedEntry = packed struct(u32) { | 2002 | pub 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 |
| | 2008 | pub 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 | }; |