xref: /openbsd-src/gnu/llvm/libunwind/include/mach-o/compact_unwind_encoding.h (revision 0faf1914bfa030ea6c1d961758e08514a79ff73a)
1*0faf1914Srobert //===----------------------------------------------------------------------===//
2f6c50668Spatrick //
3f6c50668Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f6c50668Spatrick // See https://llvm.org/LICENSE.txt for license information.
5f6c50668Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f6c50668Spatrick //
7f6c50668Spatrick //
8f6c50668Spatrick // Darwin's alternative to DWARF based unwind encodings.
9f6c50668Spatrick //
10f6c50668Spatrick //===----------------------------------------------------------------------===//
11f6c50668Spatrick 
12f6c50668Spatrick 
13f6c50668Spatrick #ifndef __COMPACT_UNWIND_ENCODING__
14f6c50668Spatrick #define __COMPACT_UNWIND_ENCODING__
15f6c50668Spatrick 
16f6c50668Spatrick #include <stdint.h>
17f6c50668Spatrick 
18f6c50668Spatrick //
19f6c50668Spatrick // Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section
20f6c50668Spatrick // of object files. Or compilers can emit compact unwind information in
21f6c50668Spatrick // the __LD,__compact_unwind section.
22f6c50668Spatrick //
23f6c50668Spatrick // When the linker creates a final linked image, it will create a
24f6c50668Spatrick // __TEXT,__unwind_info section.  This section is a small and fast way for the
25f6c50668Spatrick // runtime to access unwind info for any given function.  If the compiler
26f6c50668Spatrick // emitted compact unwind info for the function, that compact unwind info will
27f6c50668Spatrick // be encoded in the __TEXT,__unwind_info section. If the compiler emitted
28f6c50668Spatrick // DWARF unwind info, the __TEXT,__unwind_info section will contain the offset
29f6c50668Spatrick // of the FDE in the __TEXT,__eh_frame section in the final linked image.
30f6c50668Spatrick //
31f6c50668Spatrick // Note: Previously, the linker would transform some DWARF unwind infos into
32f6c50668Spatrick //       compact unwind info.  But that is fragile and no longer done.
33f6c50668Spatrick 
34f6c50668Spatrick 
35f6c50668Spatrick //
36*0faf1914Srobert // The compact unwind encoding is a 32-bit value which encoded in an
37f6c50668Spatrick // architecture specific way, which registers to restore from where, and how
38f6c50668Spatrick // to unwind out of the function.
39f6c50668Spatrick //
40f6c50668Spatrick typedef uint32_t compact_unwind_encoding_t;
41f6c50668Spatrick 
42f6c50668Spatrick 
43f6c50668Spatrick // architecture independent bits
44f6c50668Spatrick enum {
45f6c50668Spatrick     UNWIND_IS_NOT_FUNCTION_START           = 0x80000000,
46f6c50668Spatrick     UNWIND_HAS_LSDA                        = 0x40000000,
47f6c50668Spatrick     UNWIND_PERSONALITY_MASK                = 0x30000000,
48f6c50668Spatrick };
49f6c50668Spatrick 
50f6c50668Spatrick 
51f6c50668Spatrick 
52f6c50668Spatrick 
53f6c50668Spatrick //
54f6c50668Spatrick // x86
55f6c50668Spatrick //
56f6c50668Spatrick // 1-bit: start
57f6c50668Spatrick // 1-bit: has lsda
58f6c50668Spatrick // 2-bit: personality index
59f6c50668Spatrick //
60f6c50668Spatrick // 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF
61f6c50668Spatrick //  ebp based:
62f6c50668Spatrick //        15-bits (5*3-bits per reg) register permutation
63f6c50668Spatrick //        8-bits for stack offset
64f6c50668Spatrick //  frameless:
65f6c50668Spatrick //        8-bits stack size
66f6c50668Spatrick //        3-bits stack adjust
67f6c50668Spatrick //        3-bits register count
68f6c50668Spatrick //        10-bits register permutation
69f6c50668Spatrick //
70f6c50668Spatrick enum {
71f6c50668Spatrick     UNWIND_X86_MODE_MASK                         = 0x0F000000,
72f6c50668Spatrick     UNWIND_X86_MODE_EBP_FRAME                    = 0x01000000,
73f6c50668Spatrick     UNWIND_X86_MODE_STACK_IMMD                   = 0x02000000,
74f6c50668Spatrick     UNWIND_X86_MODE_STACK_IND                    = 0x03000000,
75f6c50668Spatrick     UNWIND_X86_MODE_DWARF                        = 0x04000000,
76f6c50668Spatrick 
77f6c50668Spatrick     UNWIND_X86_EBP_FRAME_REGISTERS               = 0x00007FFF,
78f6c50668Spatrick     UNWIND_X86_EBP_FRAME_OFFSET                  = 0x00FF0000,
79f6c50668Spatrick 
80f6c50668Spatrick     UNWIND_X86_FRAMELESS_STACK_SIZE              = 0x00FF0000,
81f6c50668Spatrick     UNWIND_X86_FRAMELESS_STACK_ADJUST            = 0x0000E000,
82f6c50668Spatrick     UNWIND_X86_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
83f6c50668Spatrick     UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
84f6c50668Spatrick 
85f6c50668Spatrick     UNWIND_X86_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
86f6c50668Spatrick };
87f6c50668Spatrick 
88f6c50668Spatrick enum {
89f6c50668Spatrick     UNWIND_X86_REG_NONE     = 0,
90f6c50668Spatrick     UNWIND_X86_REG_EBX      = 1,
91f6c50668Spatrick     UNWIND_X86_REG_ECX      = 2,
92f6c50668Spatrick     UNWIND_X86_REG_EDX      = 3,
93f6c50668Spatrick     UNWIND_X86_REG_EDI      = 4,
94f6c50668Spatrick     UNWIND_X86_REG_ESI      = 5,
95f6c50668Spatrick     UNWIND_X86_REG_EBP      = 6,
96f6c50668Spatrick };
97f6c50668Spatrick 
98f6c50668Spatrick //
99f6c50668Spatrick // For x86 there are four modes for the compact unwind encoding:
100f6c50668Spatrick // UNWIND_X86_MODE_EBP_FRAME:
101f6c50668Spatrick //    EBP based frame where EBP is push on stack immediately after return address,
102f6c50668Spatrick //    then ESP is moved to EBP. Thus, to unwind ESP is restored with the current
103f6c50668Spatrick //    EPB value, then EBP is restored by popping off the stack, and the return
104f6c50668Spatrick //    is done by popping the stack once more into the pc.
105f6c50668Spatrick //    All non-volatile registers that need to be restored must have been saved
106f6c50668Spatrick //    in a small range in the stack that starts EBP-4 to EBP-1020.  The offset/4
107f6c50668Spatrick //    is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits.  The registers saved
108f6c50668Spatrick //    are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
109f6c50668Spatrick //    Each entry contains which register to restore.
110f6c50668Spatrick // UNWIND_X86_MODE_STACK_IMMD:
111f6c50668Spatrick //    A "frameless" (EBP not used as frame pointer) function with a small
112f6c50668Spatrick //    constant stack size.  To return, a constant (encoded in the compact
113f6c50668Spatrick //    unwind encoding) is added to the ESP. Then the return is done by
114f6c50668Spatrick //    popping the stack into the pc.
115f6c50668Spatrick //    All non-volatile registers that need to be restored must have been saved
116f6c50668Spatrick //    on the stack immediately after the return address.  The stack_size/4 is
117f6c50668Spatrick //    encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
118f6c50668Spatrick //    The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
119*0faf1914Srobert //    UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
120f6c50668Spatrick //    saved and their order.
121f6c50668Spatrick // UNWIND_X86_MODE_STACK_IND:
122f6c50668Spatrick //    A "frameless" (EBP not used as frame pointer) function large constant
123f6c50668Spatrick //    stack size.  This case is like the previous, except the stack size is too
124f6c50668Spatrick //    large to encode in the compact unwind encoding.  Instead it requires that
125f6c50668Spatrick //    the function contains "subl $nnnnnnnn,ESP" in its prolog.  The compact
126f6c50668Spatrick //    encoding contains the offset to the nnnnnnnn value in the function in
127f6c50668Spatrick //    UNWIND_X86_FRAMELESS_STACK_SIZE.
128f6c50668Spatrick // UNWIND_X86_MODE_DWARF:
129f6c50668Spatrick //    No compact unwind encoding is available.  Instead the low 24-bits of the
130f6c50668Spatrick //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
131f6c50668Spatrick //    This mode is never used in object files.  It is only generated by the
132f6c50668Spatrick //    linker in final linked images which have only DWARF unwind info for a
133f6c50668Spatrick //    function.
134f6c50668Spatrick //
135f6c50668Spatrick // The permutation encoding is a Lehmer code sequence encoded into a
136f6c50668Spatrick // single variable-base number so we can encode the ordering of up to
137f6c50668Spatrick // six registers in a 10-bit space.
138f6c50668Spatrick //
139f6c50668Spatrick // The following is the algorithm used to create the permutation encoding used
140f6c50668Spatrick // with frameless stacks.  It is passed the number of registers to be saved and
141f6c50668Spatrick // an array of the register numbers saved.
142f6c50668Spatrick //
143f6c50668Spatrick //uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6])
144f6c50668Spatrick //{
145f6c50668Spatrick //    uint32_t renumregs[6];
146f6c50668Spatrick //    for (int i=6-registerCount; i < 6; ++i) {
147f6c50668Spatrick //        int countless = 0;
148f6c50668Spatrick //        for (int j=6-registerCount; j < i; ++j) {
149f6c50668Spatrick //            if ( registers[j] < registers[i] )
150f6c50668Spatrick //                ++countless;
151f6c50668Spatrick //        }
152f6c50668Spatrick //        renumregs[i] = registers[i] - countless -1;
153f6c50668Spatrick //    }
154f6c50668Spatrick //    uint32_t permutationEncoding = 0;
155f6c50668Spatrick //    switch ( registerCount ) {
156f6c50668Spatrick //        case 6:
157f6c50668Spatrick //            permutationEncoding |= (120*renumregs[0] + 24*renumregs[1]
158f6c50668Spatrick //                                    + 6*renumregs[2] + 2*renumregs[3]
159f6c50668Spatrick //                                      + renumregs[4]);
160f6c50668Spatrick //            break;
161f6c50668Spatrick //        case 5:
162f6c50668Spatrick //            permutationEncoding |= (120*renumregs[1] + 24*renumregs[2]
163f6c50668Spatrick //                                    + 6*renumregs[3] + 2*renumregs[4]
164f6c50668Spatrick //                                      + renumregs[5]);
165f6c50668Spatrick //            break;
166f6c50668Spatrick //        case 4:
167f6c50668Spatrick //            permutationEncoding |= (60*renumregs[2] + 12*renumregs[3]
168f6c50668Spatrick //                                   + 3*renumregs[4] + renumregs[5]);
169f6c50668Spatrick //            break;
170f6c50668Spatrick //        case 3:
171f6c50668Spatrick //            permutationEncoding |= (20*renumregs[3] + 4*renumregs[4]
172f6c50668Spatrick //                                     + renumregs[5]);
173f6c50668Spatrick //            break;
174f6c50668Spatrick //        case 2:
175f6c50668Spatrick //            permutationEncoding |= (5*renumregs[4] + renumregs[5]);
176f6c50668Spatrick //            break;
177f6c50668Spatrick //        case 1:
178f6c50668Spatrick //            permutationEncoding |= (renumregs[5]);
179f6c50668Spatrick //            break;
180f6c50668Spatrick //    }
181f6c50668Spatrick //    return permutationEncoding;
182f6c50668Spatrick //}
183f6c50668Spatrick //
184f6c50668Spatrick 
185f6c50668Spatrick 
186f6c50668Spatrick 
187f6c50668Spatrick 
188f6c50668Spatrick //
189f6c50668Spatrick // x86_64
190f6c50668Spatrick //
191f6c50668Spatrick // 1-bit: start
192f6c50668Spatrick // 1-bit: has lsda
193f6c50668Spatrick // 2-bit: personality index
194f6c50668Spatrick //
195f6c50668Spatrick // 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF
196f6c50668Spatrick //  rbp based:
197f6c50668Spatrick //        15-bits (5*3-bits per reg) register permutation
198f6c50668Spatrick //        8-bits for stack offset
199f6c50668Spatrick //  frameless:
200f6c50668Spatrick //        8-bits stack size
201f6c50668Spatrick //        3-bits stack adjust
202f6c50668Spatrick //        3-bits register count
203f6c50668Spatrick //        10-bits register permutation
204f6c50668Spatrick //
205f6c50668Spatrick enum {
206f6c50668Spatrick     UNWIND_X86_64_MODE_MASK                         = 0x0F000000,
207f6c50668Spatrick     UNWIND_X86_64_MODE_RBP_FRAME                    = 0x01000000,
208f6c50668Spatrick     UNWIND_X86_64_MODE_STACK_IMMD                   = 0x02000000,
209f6c50668Spatrick     UNWIND_X86_64_MODE_STACK_IND                    = 0x03000000,
210f6c50668Spatrick     UNWIND_X86_64_MODE_DWARF                        = 0x04000000,
211f6c50668Spatrick 
212f6c50668Spatrick     UNWIND_X86_64_RBP_FRAME_REGISTERS               = 0x00007FFF,
213f6c50668Spatrick     UNWIND_X86_64_RBP_FRAME_OFFSET                  = 0x00FF0000,
214f6c50668Spatrick 
215f6c50668Spatrick     UNWIND_X86_64_FRAMELESS_STACK_SIZE              = 0x00FF0000,
216f6c50668Spatrick     UNWIND_X86_64_FRAMELESS_STACK_ADJUST            = 0x0000E000,
217f6c50668Spatrick     UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
218f6c50668Spatrick     UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
219f6c50668Spatrick 
220f6c50668Spatrick     UNWIND_X86_64_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
221f6c50668Spatrick };
222f6c50668Spatrick 
223f6c50668Spatrick enum {
224f6c50668Spatrick     UNWIND_X86_64_REG_NONE       = 0,
225f6c50668Spatrick     UNWIND_X86_64_REG_RBX        = 1,
226f6c50668Spatrick     UNWIND_X86_64_REG_R12        = 2,
227f6c50668Spatrick     UNWIND_X86_64_REG_R13        = 3,
228f6c50668Spatrick     UNWIND_X86_64_REG_R14        = 4,
229f6c50668Spatrick     UNWIND_X86_64_REG_R15        = 5,
230f6c50668Spatrick     UNWIND_X86_64_REG_RBP        = 6,
231f6c50668Spatrick };
232f6c50668Spatrick //
233f6c50668Spatrick // For x86_64 there are four modes for the compact unwind encoding:
234f6c50668Spatrick // UNWIND_X86_64_MODE_RBP_FRAME:
235f6c50668Spatrick //    RBP based frame where RBP is push on stack immediately after return address,
236f6c50668Spatrick //    then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
237f6c50668Spatrick //    EPB value, then RBP is restored by popping off the stack, and the return
238f6c50668Spatrick //    is done by popping the stack once more into the pc.
239f6c50668Spatrick //    All non-volatile registers that need to be restored must have been saved
240f6c50668Spatrick //    in a small range in the stack that starts RBP-8 to RBP-2040.  The offset/8
241f6c50668Spatrick //    is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits.  The registers saved
242f6c50668Spatrick //    are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
243f6c50668Spatrick //    Each entry contains which register to restore.
244f6c50668Spatrick // UNWIND_X86_64_MODE_STACK_IMMD:
245f6c50668Spatrick //    A "frameless" (RBP not used as frame pointer) function with a small
246f6c50668Spatrick //    constant stack size.  To return, a constant (encoded in the compact
247f6c50668Spatrick //    unwind encoding) is added to the RSP. Then the return is done by
248f6c50668Spatrick //    popping the stack into the pc.
249f6c50668Spatrick //    All non-volatile registers that need to be restored must have been saved
250f6c50668Spatrick //    on the stack immediately after the return address.  The stack_size/8 is
251f6c50668Spatrick //    encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
252f6c50668Spatrick //    The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
253*0faf1914Srobert //    UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
254f6c50668Spatrick //    saved and their order.
255f6c50668Spatrick // UNWIND_X86_64_MODE_STACK_IND:
256f6c50668Spatrick //    A "frameless" (RBP not used as frame pointer) function large constant
257f6c50668Spatrick //    stack size.  This case is like the previous, except the stack size is too
258f6c50668Spatrick //    large to encode in the compact unwind encoding.  Instead it requires that
259f6c50668Spatrick //    the function contains "subq $nnnnnnnn,RSP" in its prolog.  The compact
260f6c50668Spatrick //    encoding contains the offset to the nnnnnnnn value in the function in
261f6c50668Spatrick //    UNWIND_X86_64_FRAMELESS_STACK_SIZE.
262f6c50668Spatrick // UNWIND_X86_64_MODE_DWARF:
263f6c50668Spatrick //    No compact unwind encoding is available.  Instead the low 24-bits of the
264f6c50668Spatrick //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
265f6c50668Spatrick //    This mode is never used in object files.  It is only generated by the
266f6c50668Spatrick //    linker in final linked images which have only DWARF unwind info for a
267f6c50668Spatrick //    function.
268f6c50668Spatrick //
269f6c50668Spatrick 
270f6c50668Spatrick 
271f6c50668Spatrick // ARM64
272f6c50668Spatrick //
273f6c50668Spatrick // 1-bit: start
274f6c50668Spatrick // 1-bit: has lsda
275f6c50668Spatrick // 2-bit: personality index
276f6c50668Spatrick //
277f6c50668Spatrick // 4-bits: 4=frame-based, 3=DWARF, 2=frameless
278f6c50668Spatrick //  frameless:
279f6c50668Spatrick //        12-bits of stack size
280f6c50668Spatrick //  frame-based:
281f6c50668Spatrick //        4-bits D reg pairs saved
282f6c50668Spatrick //        5-bits X reg pairs saved
283f6c50668Spatrick //  DWARF:
284f6c50668Spatrick //        24-bits offset of DWARF FDE in __eh_frame section
285f6c50668Spatrick //
286f6c50668Spatrick enum {
287f6c50668Spatrick     UNWIND_ARM64_MODE_MASK                     = 0x0F000000,
288f6c50668Spatrick     UNWIND_ARM64_MODE_FRAMELESS                = 0x02000000,
289f6c50668Spatrick     UNWIND_ARM64_MODE_DWARF                    = 0x03000000,
290f6c50668Spatrick     UNWIND_ARM64_MODE_FRAME                    = 0x04000000,
291f6c50668Spatrick 
292f6c50668Spatrick     UNWIND_ARM64_FRAME_X19_X20_PAIR            = 0x00000001,
293f6c50668Spatrick     UNWIND_ARM64_FRAME_X21_X22_PAIR            = 0x00000002,
294f6c50668Spatrick     UNWIND_ARM64_FRAME_X23_X24_PAIR            = 0x00000004,
295f6c50668Spatrick     UNWIND_ARM64_FRAME_X25_X26_PAIR            = 0x00000008,
296f6c50668Spatrick     UNWIND_ARM64_FRAME_X27_X28_PAIR            = 0x00000010,
297f6c50668Spatrick     UNWIND_ARM64_FRAME_D8_D9_PAIR              = 0x00000100,
298f6c50668Spatrick     UNWIND_ARM64_FRAME_D10_D11_PAIR            = 0x00000200,
299f6c50668Spatrick     UNWIND_ARM64_FRAME_D12_D13_PAIR            = 0x00000400,
300f6c50668Spatrick     UNWIND_ARM64_FRAME_D14_D15_PAIR            = 0x00000800,
301f6c50668Spatrick 
302f6c50668Spatrick     UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK     = 0x00FFF000,
303f6c50668Spatrick     UNWIND_ARM64_DWARF_SECTION_OFFSET          = 0x00FFFFFF,
304f6c50668Spatrick };
305f6c50668Spatrick // For arm64 there are three modes for the compact unwind encoding:
306f6c50668Spatrick // UNWIND_ARM64_MODE_FRAME:
307f6c50668Spatrick //    This is a standard arm64 prolog where FP/LR are immediately pushed on the
308f6c50668Spatrick //    stack, then SP is copied to FP. If there are any non-volatile registers
309f6c50668Spatrick //    saved, then are copied into the stack frame in pairs in a contiguous
310f6c50668Spatrick //    range right below the saved FP/LR pair.  Any subset of the five X pairs
311f6c50668Spatrick //    and four D pairs can be saved, but the memory layout must be in register
312f6c50668Spatrick //    number order.
313f6c50668Spatrick // UNWIND_ARM64_MODE_FRAMELESS:
314f6c50668Spatrick //    A "frameless" leaf function, where FP/LR are not saved. The return address
315f6c50668Spatrick //    remains in LR throughout the function. If any non-volatile registers
316f6c50668Spatrick //    are saved, they must be pushed onto the stack before any stack space is
317f6c50668Spatrick //    allocated for local variables.  The stack sized (including any saved
318f6c50668Spatrick //    non-volatile registers) divided by 16 is encoded in the bits
319f6c50668Spatrick //    UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
320f6c50668Spatrick // UNWIND_ARM64_MODE_DWARF:
321f6c50668Spatrick //    No compact unwind encoding is available.  Instead the low 24-bits of the
322f6c50668Spatrick //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
323f6c50668Spatrick //    This mode is never used in object files.  It is only generated by the
324f6c50668Spatrick //    linker in final linked images which have only DWARF unwind info for a
325f6c50668Spatrick //    function.
326f6c50668Spatrick //
327f6c50668Spatrick 
328f6c50668Spatrick 
329f6c50668Spatrick 
330f6c50668Spatrick 
331f6c50668Spatrick 
332f6c50668Spatrick ////////////////////////////////////////////////////////////////////////////////
333f6c50668Spatrick //
334f6c50668Spatrick //  Relocatable Object Files: __LD,__compact_unwind
335f6c50668Spatrick //
336f6c50668Spatrick ////////////////////////////////////////////////////////////////////////////////
337f6c50668Spatrick 
338f6c50668Spatrick //
339f6c50668Spatrick // A compiler can generated compact unwind information for a function by adding
340f6c50668Spatrick // a "row" to the __LD,__compact_unwind section.  This section has the
341f6c50668Spatrick // S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
342f6c50668Spatrick // It is removed by the new linker, so never ends up in final executables.
343f6c50668Spatrick // This section is a table, initially with one row per function (that needs
344f6c50668Spatrick // unwind info).  The table columns and some conceptual entries are:
345f6c50668Spatrick //
346f6c50668Spatrick //     range-start               pointer to start of function/range
347f6c50668Spatrick //     range-length
348f6c50668Spatrick //     compact-unwind-encoding   32-bit encoding
349f6c50668Spatrick //     personality-function      or zero if no personality function
350f6c50668Spatrick //     lsda                      or zero if no LSDA data
351f6c50668Spatrick //
352f6c50668Spatrick // The length and encoding fields are 32-bits.  The other are all pointer sized.
353f6c50668Spatrick //
354f6c50668Spatrick // In x86_64 assembly, these entry would look like:
355f6c50668Spatrick //
356f6c50668Spatrick //     .section __LD,__compact_unwind,regular,debug
357f6c50668Spatrick //
358f6c50668Spatrick //     #compact unwind for _foo
359f6c50668Spatrick //     .quad    _foo
360f6c50668Spatrick //     .set     L1,LfooEnd-_foo
361f6c50668Spatrick //     .long    L1
362f6c50668Spatrick //     .long    0x01010001
363f6c50668Spatrick //     .quad    0
364f6c50668Spatrick //     .quad    0
365f6c50668Spatrick //
366f6c50668Spatrick //     #compact unwind for _bar
367f6c50668Spatrick //     .quad    _bar
368f6c50668Spatrick //     .set     L2,LbarEnd-_bar
369f6c50668Spatrick //     .long    L2
370f6c50668Spatrick //     .long    0x01020011
371f6c50668Spatrick //     .quad    __gxx_personality
372f6c50668Spatrick //     .quad    except_tab1
373f6c50668Spatrick //
374f6c50668Spatrick //
375f6c50668Spatrick // Notes: There is no need for any labels in the the __compact_unwind section.
376f6c50668Spatrick //        The use of the .set directive is to force the evaluation of the
377f6c50668Spatrick //        range-length at assembly time, instead of generating relocations.
378f6c50668Spatrick //
379f6c50668Spatrick // To support future compiler optimizations where which non-volatile registers
380f6c50668Spatrick // are saved changes within a function (e.g. delay saving non-volatiles until
381f6c50668Spatrick // necessary), there can by multiple lines in the __compact_unwind table for one
382f6c50668Spatrick // function, each with a different (non-overlapping) range and each with
383f6c50668Spatrick // different compact unwind encodings that correspond to the non-volatiles
384f6c50668Spatrick // saved at that range of the function.
385f6c50668Spatrick //
386f6c50668Spatrick // If a particular function is so wacky that there is no compact unwind way
387f6c50668Spatrick // to encode it, then the compiler can emit traditional DWARF unwind info.
388f6c50668Spatrick // The runtime will use which ever is available.
389f6c50668Spatrick //
390f6c50668Spatrick // Runtime support for compact unwind encodings are only available on 10.6
391f6c50668Spatrick // and later.  So, the compiler should not generate it when targeting pre-10.6.
392f6c50668Spatrick 
393f6c50668Spatrick 
394f6c50668Spatrick 
395f6c50668Spatrick 
396f6c50668Spatrick ////////////////////////////////////////////////////////////////////////////////
397f6c50668Spatrick //
398f6c50668Spatrick //  Final Linked Images: __TEXT,__unwind_info
399f6c50668Spatrick //
400f6c50668Spatrick ////////////////////////////////////////////////////////////////////////////////
401f6c50668Spatrick 
402f6c50668Spatrick //
403f6c50668Spatrick // The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
404f6c50668Spatrick // The header of the section contains a coarse index that maps function address
405f6c50668Spatrick // to the page (4096 byte block) containing the unwind info for that function.
406f6c50668Spatrick //
407f6c50668Spatrick 
408f6c50668Spatrick #define UNWIND_SECTION_VERSION 1
409f6c50668Spatrick struct unwind_info_section_header
410f6c50668Spatrick {
411f6c50668Spatrick     uint32_t    version;            // UNWIND_SECTION_VERSION
412f6c50668Spatrick     uint32_t    commonEncodingsArraySectionOffset;
413f6c50668Spatrick     uint32_t    commonEncodingsArrayCount;
414f6c50668Spatrick     uint32_t    personalityArraySectionOffset;
415f6c50668Spatrick     uint32_t    personalityArrayCount;
416f6c50668Spatrick     uint32_t    indexSectionOffset;
417f6c50668Spatrick     uint32_t    indexCount;
418f6c50668Spatrick     // compact_unwind_encoding_t[]
419f6c50668Spatrick     // uint32_t personalities[]
420f6c50668Spatrick     // unwind_info_section_header_index_entry[]
421f6c50668Spatrick     // unwind_info_section_header_lsda_index_entry[]
422f6c50668Spatrick };
423f6c50668Spatrick 
424f6c50668Spatrick struct unwind_info_section_header_index_entry
425f6c50668Spatrick {
426f6c50668Spatrick     uint32_t        functionOffset;
427f6c50668Spatrick     uint32_t        secondLevelPagesSectionOffset;  // section offset to start of regular or compress page
428f6c50668Spatrick     uint32_t        lsdaIndexArraySectionOffset;    // section offset to start of lsda_index array for this range
429f6c50668Spatrick };
430f6c50668Spatrick 
431f6c50668Spatrick struct unwind_info_section_header_lsda_index_entry
432f6c50668Spatrick {
433f6c50668Spatrick     uint32_t        functionOffset;
434f6c50668Spatrick     uint32_t        lsdaOffset;
435f6c50668Spatrick };
436f6c50668Spatrick 
437f6c50668Spatrick //
438f6c50668Spatrick // There are two kinds of second level index pages: regular and compressed.
439f6c50668Spatrick // A compressed page can hold up to 1021 entries, but it cannot be used
440f6c50668Spatrick // if too many different encoding types are used.  The regular page holds
441f6c50668Spatrick // 511 entries.
442f6c50668Spatrick //
443f6c50668Spatrick 
444f6c50668Spatrick struct unwind_info_regular_second_level_entry
445f6c50668Spatrick {
446f6c50668Spatrick     uint32_t                    functionOffset;
447f6c50668Spatrick     compact_unwind_encoding_t    encoding;
448f6c50668Spatrick };
449f6c50668Spatrick 
450f6c50668Spatrick #define UNWIND_SECOND_LEVEL_REGULAR 2
451f6c50668Spatrick struct unwind_info_regular_second_level_page_header
452f6c50668Spatrick {
453f6c50668Spatrick     uint32_t    kind;    // UNWIND_SECOND_LEVEL_REGULAR
454f6c50668Spatrick     uint16_t    entryPageOffset;
455f6c50668Spatrick     uint16_t    entryCount;
456f6c50668Spatrick     // entry array
457f6c50668Spatrick };
458f6c50668Spatrick 
459f6c50668Spatrick #define UNWIND_SECOND_LEVEL_COMPRESSED 3
460f6c50668Spatrick struct unwind_info_compressed_second_level_page_header
461f6c50668Spatrick {
462f6c50668Spatrick     uint32_t    kind;    // UNWIND_SECOND_LEVEL_COMPRESSED
463f6c50668Spatrick     uint16_t    entryPageOffset;
464f6c50668Spatrick     uint16_t    entryCount;
465f6c50668Spatrick     uint16_t    encodingsPageOffset;
466f6c50668Spatrick     uint16_t    encodingsCount;
467f6c50668Spatrick     // 32-bit entry array
468f6c50668Spatrick     // encodings array
469f6c50668Spatrick };
470f6c50668Spatrick 
471f6c50668Spatrick #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry)            (entry & 0x00FFFFFF)
472f6c50668Spatrick #define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry)        ((entry >> 24) & 0xFF)
473f6c50668Spatrick 
474f6c50668Spatrick 
475f6c50668Spatrick 
476f6c50668Spatrick #endif
477f6c50668Spatrick 
478