xref: /freebsd/contrib/llvm-project/libunwind/include/mach-o/compact_unwind_encoding.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric // Darwin's alternative to DWARF based unwind encodings.
90b57cec5SDimitry Andric //
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef __COMPACT_UNWIND_ENCODING__
140b57cec5SDimitry Andric #define __COMPACT_UNWIND_ENCODING__
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include <stdint.h>
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric //
190b57cec5SDimitry Andric // Compilers can emit standard DWARF FDEs in the __TEXT,__eh_frame section
200b57cec5SDimitry Andric // of object files. Or compilers can emit compact unwind information in
210b57cec5SDimitry Andric // the __LD,__compact_unwind section.
220b57cec5SDimitry Andric //
230b57cec5SDimitry Andric // When the linker creates a final linked image, it will create a
240b57cec5SDimitry Andric // __TEXT,__unwind_info section.  This section is a small and fast way for the
250b57cec5SDimitry Andric // runtime to access unwind info for any given function.  If the compiler
260b57cec5SDimitry Andric // emitted compact unwind info for the function, that compact unwind info will
270b57cec5SDimitry Andric // be encoded in the __TEXT,__unwind_info section. If the compiler emitted
280b57cec5SDimitry Andric // DWARF unwind info, the __TEXT,__unwind_info section will contain the offset
290b57cec5SDimitry Andric // of the FDE in the __TEXT,__eh_frame section in the final linked image.
300b57cec5SDimitry Andric //
310b57cec5SDimitry Andric // Note: Previously, the linker would transform some DWARF unwind infos into
320b57cec5SDimitry Andric //       compact unwind info.  But that is fragile and no longer done.
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric //
36bdd1243dSDimitry Andric // The compact unwind encoding is a 32-bit value which encoded in an
370b57cec5SDimitry Andric // architecture specific way, which registers to restore from where, and how
380b57cec5SDimitry Andric // to unwind out of the function.
390b57cec5SDimitry Andric //
400b57cec5SDimitry Andric typedef uint32_t compact_unwind_encoding_t;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric // architecture independent bits
440b57cec5SDimitry Andric enum {
450b57cec5SDimitry Andric     UNWIND_IS_NOT_FUNCTION_START           = 0x80000000,
460b57cec5SDimitry Andric     UNWIND_HAS_LSDA                        = 0x40000000,
470b57cec5SDimitry Andric     UNWIND_PERSONALITY_MASK                = 0x30000000,
480b57cec5SDimitry Andric };
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric //
540b57cec5SDimitry Andric // x86
550b57cec5SDimitry Andric //
560b57cec5SDimitry Andric // 1-bit: start
570b57cec5SDimitry Andric // 1-bit: has lsda
580b57cec5SDimitry Andric // 2-bit: personality index
590b57cec5SDimitry Andric //
600b57cec5SDimitry Andric // 4-bits: 0=old, 1=ebp based, 2=stack-imm, 3=stack-ind, 4=DWARF
610b57cec5SDimitry Andric //  ebp based:
620b57cec5SDimitry Andric //        15-bits (5*3-bits per reg) register permutation
630b57cec5SDimitry Andric //        8-bits for stack offset
640b57cec5SDimitry Andric //  frameless:
650b57cec5SDimitry Andric //        8-bits stack size
660b57cec5SDimitry Andric //        3-bits stack adjust
670b57cec5SDimitry Andric //        3-bits register count
680b57cec5SDimitry Andric //        10-bits register permutation
690b57cec5SDimitry Andric //
700b57cec5SDimitry Andric enum {
710b57cec5SDimitry Andric     UNWIND_X86_MODE_MASK                         = 0x0F000000,
720b57cec5SDimitry Andric     UNWIND_X86_MODE_EBP_FRAME                    = 0x01000000,
730b57cec5SDimitry Andric     UNWIND_X86_MODE_STACK_IMMD                   = 0x02000000,
740b57cec5SDimitry Andric     UNWIND_X86_MODE_STACK_IND                    = 0x03000000,
750b57cec5SDimitry Andric     UNWIND_X86_MODE_DWARF                        = 0x04000000,
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric     UNWIND_X86_EBP_FRAME_REGISTERS               = 0x00007FFF,
780b57cec5SDimitry Andric     UNWIND_X86_EBP_FRAME_OFFSET                  = 0x00FF0000,
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric     UNWIND_X86_FRAMELESS_STACK_SIZE              = 0x00FF0000,
810b57cec5SDimitry Andric     UNWIND_X86_FRAMELESS_STACK_ADJUST            = 0x0000E000,
820b57cec5SDimitry Andric     UNWIND_X86_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
830b57cec5SDimitry Andric     UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric     UNWIND_X86_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
860b57cec5SDimitry Andric };
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric enum {
890b57cec5SDimitry Andric     UNWIND_X86_REG_NONE     = 0,
900b57cec5SDimitry Andric     UNWIND_X86_REG_EBX      = 1,
910b57cec5SDimitry Andric     UNWIND_X86_REG_ECX      = 2,
920b57cec5SDimitry Andric     UNWIND_X86_REG_EDX      = 3,
930b57cec5SDimitry Andric     UNWIND_X86_REG_EDI      = 4,
940b57cec5SDimitry Andric     UNWIND_X86_REG_ESI      = 5,
950b57cec5SDimitry Andric     UNWIND_X86_REG_EBP      = 6,
960b57cec5SDimitry Andric };
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric //
990b57cec5SDimitry Andric // For x86 there are four modes for the compact unwind encoding:
1000b57cec5SDimitry Andric // UNWIND_X86_MODE_EBP_FRAME:
1010b57cec5SDimitry Andric //    EBP based frame where EBP is push on stack immediately after return address,
1020b57cec5SDimitry Andric //    then ESP is moved to EBP. Thus, to unwind ESP is restored with the current
1030b57cec5SDimitry Andric //    EPB value, then EBP is restored by popping off the stack, and the return
1040b57cec5SDimitry Andric //    is done by popping the stack once more into the pc.
1050b57cec5SDimitry Andric //    All non-volatile registers that need to be restored must have been saved
1060b57cec5SDimitry Andric //    in a small range in the stack that starts EBP-4 to EBP-1020.  The offset/4
1070b57cec5SDimitry Andric //    is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits.  The registers saved
1080b57cec5SDimitry Andric //    are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries.
1090b57cec5SDimitry Andric //    Each entry contains which register to restore.
1100b57cec5SDimitry Andric // UNWIND_X86_MODE_STACK_IMMD:
1110b57cec5SDimitry Andric //    A "frameless" (EBP not used as frame pointer) function with a small
1120b57cec5SDimitry Andric //    constant stack size.  To return, a constant (encoded in the compact
1130b57cec5SDimitry Andric //    unwind encoding) is added to the ESP. Then the return is done by
1140b57cec5SDimitry Andric //    popping the stack into the pc.
1150b57cec5SDimitry Andric //    All non-volatile registers that need to be restored must have been saved
1160b57cec5SDimitry Andric //    on the stack immediately after the return address.  The stack_size/4 is
1170b57cec5SDimitry Andric //    encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
1180b57cec5SDimitry Andric //    The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
119bdd1243dSDimitry Andric //    UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
1200b57cec5SDimitry Andric //    saved and their order.
1210b57cec5SDimitry Andric // UNWIND_X86_MODE_STACK_IND:
1220b57cec5SDimitry Andric //    A "frameless" (EBP not used as frame pointer) function large constant
1230b57cec5SDimitry Andric //    stack size.  This case is like the previous, except the stack size is too
1240b57cec5SDimitry Andric //    large to encode in the compact unwind encoding.  Instead it requires that
1250b57cec5SDimitry Andric //    the function contains "subl $nnnnnnnn,ESP" in its prolog.  The compact
1260b57cec5SDimitry Andric //    encoding contains the offset to the nnnnnnnn value in the function in
1270b57cec5SDimitry Andric //    UNWIND_X86_FRAMELESS_STACK_SIZE.
1280b57cec5SDimitry Andric // UNWIND_X86_MODE_DWARF:
1290b57cec5SDimitry Andric //    No compact unwind encoding is available.  Instead the low 24-bits of the
1300b57cec5SDimitry Andric //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
1310b57cec5SDimitry Andric //    This mode is never used in object files.  It is only generated by the
1320b57cec5SDimitry Andric //    linker in final linked images which have only DWARF unwind info for a
1330b57cec5SDimitry Andric //    function.
1340b57cec5SDimitry Andric //
1350b57cec5SDimitry Andric // The permutation encoding is a Lehmer code sequence encoded into a
1360b57cec5SDimitry Andric // single variable-base number so we can encode the ordering of up to
1370b57cec5SDimitry Andric // six registers in a 10-bit space.
1380b57cec5SDimitry Andric //
1390b57cec5SDimitry Andric // The following is the algorithm used to create the permutation encoding used
1400b57cec5SDimitry Andric // with frameless stacks.  It is passed the number of registers to be saved and
1410b57cec5SDimitry Andric // an array of the register numbers saved.
1420b57cec5SDimitry Andric //
1430b57cec5SDimitry Andric //uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6])
1440b57cec5SDimitry Andric //{
1450b57cec5SDimitry Andric //    uint32_t renumregs[6];
1460b57cec5SDimitry Andric //    for (int i=6-registerCount; i < 6; ++i) {
1470b57cec5SDimitry Andric //        int countless = 0;
1480b57cec5SDimitry Andric //        for (int j=6-registerCount; j < i; ++j) {
1490b57cec5SDimitry Andric //            if ( registers[j] < registers[i] )
1500b57cec5SDimitry Andric //                ++countless;
1510b57cec5SDimitry Andric //        }
1520b57cec5SDimitry Andric //        renumregs[i] = registers[i] - countless -1;
1530b57cec5SDimitry Andric //    }
1540b57cec5SDimitry Andric //    uint32_t permutationEncoding = 0;
1550b57cec5SDimitry Andric //    switch ( registerCount ) {
1560b57cec5SDimitry Andric //        case 6:
1570b57cec5SDimitry Andric //            permutationEncoding |= (120*renumregs[0] + 24*renumregs[1]
1580b57cec5SDimitry Andric //                                    + 6*renumregs[2] + 2*renumregs[3]
1590b57cec5SDimitry Andric //                                      + renumregs[4]);
1600b57cec5SDimitry Andric //            break;
1610b57cec5SDimitry Andric //        case 5:
1620b57cec5SDimitry Andric //            permutationEncoding |= (120*renumregs[1] + 24*renumregs[2]
1630b57cec5SDimitry Andric //                                    + 6*renumregs[3] + 2*renumregs[4]
1640b57cec5SDimitry Andric //                                      + renumregs[5]);
1650b57cec5SDimitry Andric //            break;
1660b57cec5SDimitry Andric //        case 4:
1670b57cec5SDimitry Andric //            permutationEncoding |= (60*renumregs[2] + 12*renumregs[3]
1680b57cec5SDimitry Andric //                                   + 3*renumregs[4] + renumregs[5]);
1690b57cec5SDimitry Andric //            break;
1700b57cec5SDimitry Andric //        case 3:
1710b57cec5SDimitry Andric //            permutationEncoding |= (20*renumregs[3] + 4*renumregs[4]
1720b57cec5SDimitry Andric //                                     + renumregs[5]);
1730b57cec5SDimitry Andric //            break;
1740b57cec5SDimitry Andric //        case 2:
1750b57cec5SDimitry Andric //            permutationEncoding |= (5*renumregs[4] + renumregs[5]);
1760b57cec5SDimitry Andric //            break;
1770b57cec5SDimitry Andric //        case 1:
1780b57cec5SDimitry Andric //            permutationEncoding |= (renumregs[5]);
1790b57cec5SDimitry Andric //            break;
1800b57cec5SDimitry Andric //    }
1810b57cec5SDimitry Andric //    return permutationEncoding;
1820b57cec5SDimitry Andric //}
1830b57cec5SDimitry Andric //
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric //
1890b57cec5SDimitry Andric // x86_64
1900b57cec5SDimitry Andric //
1910b57cec5SDimitry Andric // 1-bit: start
1920b57cec5SDimitry Andric // 1-bit: has lsda
1930b57cec5SDimitry Andric // 2-bit: personality index
1940b57cec5SDimitry Andric //
1950b57cec5SDimitry Andric // 4-bits: 0=old, 1=rbp based, 2=stack-imm, 3=stack-ind, 4=DWARF
1960b57cec5SDimitry Andric //  rbp based:
1970b57cec5SDimitry Andric //        15-bits (5*3-bits per reg) register permutation
1980b57cec5SDimitry Andric //        8-bits for stack offset
1990b57cec5SDimitry Andric //  frameless:
2000b57cec5SDimitry Andric //        8-bits stack size
2010b57cec5SDimitry Andric //        3-bits stack adjust
2020b57cec5SDimitry Andric //        3-bits register count
2030b57cec5SDimitry Andric //        10-bits register permutation
2040b57cec5SDimitry Andric //
2050b57cec5SDimitry Andric enum {
2060b57cec5SDimitry Andric     UNWIND_X86_64_MODE_MASK                         = 0x0F000000,
2070b57cec5SDimitry Andric     UNWIND_X86_64_MODE_RBP_FRAME                    = 0x01000000,
2080b57cec5SDimitry Andric     UNWIND_X86_64_MODE_STACK_IMMD                   = 0x02000000,
2090b57cec5SDimitry Andric     UNWIND_X86_64_MODE_STACK_IND                    = 0x03000000,
2100b57cec5SDimitry Andric     UNWIND_X86_64_MODE_DWARF                        = 0x04000000,
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric     UNWIND_X86_64_RBP_FRAME_REGISTERS               = 0x00007FFF,
2130b57cec5SDimitry Andric     UNWIND_X86_64_RBP_FRAME_OFFSET                  = 0x00FF0000,
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric     UNWIND_X86_64_FRAMELESS_STACK_SIZE              = 0x00FF0000,
2160b57cec5SDimitry Andric     UNWIND_X86_64_FRAMELESS_STACK_ADJUST            = 0x0000E000,
2170b57cec5SDimitry Andric     UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT         = 0x00001C00,
2180b57cec5SDimitry Andric     UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION   = 0x000003FF,
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric     UNWIND_X86_64_DWARF_SECTION_OFFSET              = 0x00FFFFFF,
2210b57cec5SDimitry Andric };
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric enum {
2240b57cec5SDimitry Andric     UNWIND_X86_64_REG_NONE       = 0,
2250b57cec5SDimitry Andric     UNWIND_X86_64_REG_RBX        = 1,
2260b57cec5SDimitry Andric     UNWIND_X86_64_REG_R12        = 2,
2270b57cec5SDimitry Andric     UNWIND_X86_64_REG_R13        = 3,
2280b57cec5SDimitry Andric     UNWIND_X86_64_REG_R14        = 4,
2290b57cec5SDimitry Andric     UNWIND_X86_64_REG_R15        = 5,
2300b57cec5SDimitry Andric     UNWIND_X86_64_REG_RBP        = 6,
2310b57cec5SDimitry Andric };
2320b57cec5SDimitry Andric //
2330b57cec5SDimitry Andric // For x86_64 there are four modes for the compact unwind encoding:
2340b57cec5SDimitry Andric // UNWIND_X86_64_MODE_RBP_FRAME:
2350b57cec5SDimitry Andric //    RBP based frame where RBP is push on stack immediately after return address,
2360b57cec5SDimitry Andric //    then RSP is moved to RBP. Thus, to unwind RSP is restored with the current
2370b57cec5SDimitry Andric //    EPB value, then RBP is restored by popping off the stack, and the return
2380b57cec5SDimitry Andric //    is done by popping the stack once more into the pc.
2390b57cec5SDimitry Andric //    All non-volatile registers that need to be restored must have been saved
2400b57cec5SDimitry Andric //    in a small range in the stack that starts RBP-8 to RBP-2040.  The offset/8
2410b57cec5SDimitry Andric //    is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits.  The registers saved
2420b57cec5SDimitry Andric //    are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries.
2430b57cec5SDimitry Andric //    Each entry contains which register to restore.
2440b57cec5SDimitry Andric // UNWIND_X86_64_MODE_STACK_IMMD:
2450b57cec5SDimitry Andric //    A "frameless" (RBP not used as frame pointer) function with a small
2460b57cec5SDimitry Andric //    constant stack size.  To return, a constant (encoded in the compact
2470b57cec5SDimitry Andric //    unwind encoding) is added to the RSP. Then the return is done by
2480b57cec5SDimitry Andric //    popping the stack into the pc.
2490b57cec5SDimitry Andric //    All non-volatile registers that need to be restored must have been saved
2500b57cec5SDimitry Andric //    on the stack immediately after the return address.  The stack_size/8 is
2510b57cec5SDimitry Andric //    encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048).
2520b57cec5SDimitry Andric //    The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT.
253bdd1243dSDimitry Andric //    UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
2540b57cec5SDimitry Andric //    saved and their order.
2550b57cec5SDimitry Andric // UNWIND_X86_64_MODE_STACK_IND:
2560b57cec5SDimitry Andric //    A "frameless" (RBP not used as frame pointer) function large constant
2570b57cec5SDimitry Andric //    stack size.  This case is like the previous, except the stack size is too
2580b57cec5SDimitry Andric //    large to encode in the compact unwind encoding.  Instead it requires that
2590b57cec5SDimitry Andric //    the function contains "subq $nnnnnnnn,RSP" in its prolog.  The compact
2600b57cec5SDimitry Andric //    encoding contains the offset to the nnnnnnnn value in the function in
2610b57cec5SDimitry Andric //    UNWIND_X86_64_FRAMELESS_STACK_SIZE.
2620b57cec5SDimitry Andric // UNWIND_X86_64_MODE_DWARF:
2630b57cec5SDimitry Andric //    No compact unwind encoding is available.  Instead the low 24-bits of the
2640b57cec5SDimitry Andric //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
2650b57cec5SDimitry Andric //    This mode is never used in object files.  It is only generated by the
2660b57cec5SDimitry Andric //    linker in final linked images which have only DWARF unwind info for a
2670b57cec5SDimitry Andric //    function.
2680b57cec5SDimitry Andric //
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric // ARM64
2720b57cec5SDimitry Andric //
2730b57cec5SDimitry Andric // 1-bit: start
2740b57cec5SDimitry Andric // 1-bit: has lsda
2750b57cec5SDimitry Andric // 2-bit: personality index
2760b57cec5SDimitry Andric //
2770b57cec5SDimitry Andric // 4-bits: 4=frame-based, 3=DWARF, 2=frameless
2780b57cec5SDimitry Andric //  frameless:
2790b57cec5SDimitry Andric //        12-bits of stack size
2800b57cec5SDimitry Andric //  frame-based:
2810b57cec5SDimitry Andric //        4-bits D reg pairs saved
2820b57cec5SDimitry Andric //        5-bits X reg pairs saved
2830b57cec5SDimitry Andric //  DWARF:
2840b57cec5SDimitry Andric //        24-bits offset of DWARF FDE in __eh_frame section
2850b57cec5SDimitry Andric //
2860b57cec5SDimitry Andric enum {
2870b57cec5SDimitry Andric     UNWIND_ARM64_MODE_MASK                     = 0x0F000000,
2880b57cec5SDimitry Andric     UNWIND_ARM64_MODE_FRAMELESS                = 0x02000000,
2890b57cec5SDimitry Andric     UNWIND_ARM64_MODE_DWARF                    = 0x03000000,
2900b57cec5SDimitry Andric     UNWIND_ARM64_MODE_FRAME                    = 0x04000000,
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_X19_X20_PAIR            = 0x00000001,
2930b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_X21_X22_PAIR            = 0x00000002,
2940b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_X23_X24_PAIR            = 0x00000004,
2950b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_X25_X26_PAIR            = 0x00000008,
2960b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_X27_X28_PAIR            = 0x00000010,
2970b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_D8_D9_PAIR              = 0x00000100,
2980b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_D10_D11_PAIR            = 0x00000200,
2990b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_D12_D13_PAIR            = 0x00000400,
3000b57cec5SDimitry Andric     UNWIND_ARM64_FRAME_D14_D15_PAIR            = 0x00000800,
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric     UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK     = 0x00FFF000,
3030b57cec5SDimitry Andric     UNWIND_ARM64_DWARF_SECTION_OFFSET          = 0x00FFFFFF,
3040b57cec5SDimitry Andric };
3050b57cec5SDimitry Andric // For arm64 there are three modes for the compact unwind encoding:
3060b57cec5SDimitry Andric // UNWIND_ARM64_MODE_FRAME:
3070b57cec5SDimitry Andric //    This is a standard arm64 prolog where FP/LR are immediately pushed on the
3080b57cec5SDimitry Andric //    stack, then SP is copied to FP. If there are any non-volatile registers
3090b57cec5SDimitry Andric //    saved, then are copied into the stack frame in pairs in a contiguous
3100b57cec5SDimitry Andric //    range right below the saved FP/LR pair.  Any subset of the five X pairs
3110b57cec5SDimitry Andric //    and four D pairs can be saved, but the memory layout must be in register
3120b57cec5SDimitry Andric //    number order.
3130b57cec5SDimitry Andric // UNWIND_ARM64_MODE_FRAMELESS:
3140b57cec5SDimitry Andric //    A "frameless" leaf function, where FP/LR are not saved. The return address
3150b57cec5SDimitry Andric //    remains in LR throughout the function. If any non-volatile registers
3160b57cec5SDimitry Andric //    are saved, they must be pushed onto the stack before any stack space is
3170b57cec5SDimitry Andric //    allocated for local variables.  The stack sized (including any saved
3180b57cec5SDimitry Andric //    non-volatile registers) divided by 16 is encoded in the bits
3190b57cec5SDimitry Andric //    UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK.
3200b57cec5SDimitry Andric // UNWIND_ARM64_MODE_DWARF:
3210b57cec5SDimitry Andric //    No compact unwind encoding is available.  Instead the low 24-bits of the
3220b57cec5SDimitry Andric //    compact encoding is the offset of the DWARF FDE in the __eh_frame section.
3230b57cec5SDimitry Andric //    This mode is never used in object files.  It is only generated by the
3240b57cec5SDimitry Andric //    linker in final linked images which have only DWARF unwind info for a
3250b57cec5SDimitry Andric //    function.
3260b57cec5SDimitry Andric //
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric ////////////////////////////////////////////////////////////////////////////////
3330b57cec5SDimitry Andric //
3340b57cec5SDimitry Andric //  Relocatable Object Files: __LD,__compact_unwind
3350b57cec5SDimitry Andric //
3360b57cec5SDimitry Andric ////////////////////////////////////////////////////////////////////////////////
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric //
3390b57cec5SDimitry Andric // A compiler can generated compact unwind information for a function by adding
3400b57cec5SDimitry Andric // a "row" to the __LD,__compact_unwind section.  This section has the
3410b57cec5SDimitry Andric // S_ATTR_DEBUG bit set, so the section will be ignored by older linkers.
3420b57cec5SDimitry Andric // It is removed by the new linker, so never ends up in final executables.
3430b57cec5SDimitry Andric // This section is a table, initially with one row per function (that needs
3440b57cec5SDimitry Andric // unwind info).  The table columns and some conceptual entries are:
3450b57cec5SDimitry Andric //
3460b57cec5SDimitry Andric //     range-start               pointer to start of function/range
3470b57cec5SDimitry Andric //     range-length
3480b57cec5SDimitry Andric //     compact-unwind-encoding   32-bit encoding
3490b57cec5SDimitry Andric //     personality-function      or zero if no personality function
3500b57cec5SDimitry Andric //     lsda                      or zero if no LSDA data
3510b57cec5SDimitry Andric //
3520b57cec5SDimitry Andric // The length and encoding fields are 32-bits.  The other are all pointer sized.
3530b57cec5SDimitry Andric //
3540b57cec5SDimitry Andric // In x86_64 assembly, these entry would look like:
3550b57cec5SDimitry Andric //
3560b57cec5SDimitry Andric //     .section __LD,__compact_unwind,regular,debug
3570b57cec5SDimitry Andric //
3580b57cec5SDimitry Andric //     #compact unwind for _foo
3590b57cec5SDimitry Andric //     .quad    _foo
3600b57cec5SDimitry Andric //     .set     L1,LfooEnd-_foo
3610b57cec5SDimitry Andric //     .long    L1
3620b57cec5SDimitry Andric //     .long    0x01010001
3630b57cec5SDimitry Andric //     .quad    0
3640b57cec5SDimitry Andric //     .quad    0
3650b57cec5SDimitry Andric //
3660b57cec5SDimitry Andric //     #compact unwind for _bar
3670b57cec5SDimitry Andric //     .quad    _bar
3680b57cec5SDimitry Andric //     .set     L2,LbarEnd-_bar
3690b57cec5SDimitry Andric //     .long    L2
3700b57cec5SDimitry Andric //     .long    0x01020011
3710b57cec5SDimitry Andric //     .quad    __gxx_personality
3720b57cec5SDimitry Andric //     .quad    except_tab1
3730b57cec5SDimitry Andric //
3740b57cec5SDimitry Andric //
375*5f757f3fSDimitry Andric // Notes: There is no need for any labels in the __compact_unwind section.
3760b57cec5SDimitry Andric //        The use of the .set directive is to force the evaluation of the
3770b57cec5SDimitry Andric //        range-length at assembly time, instead of generating relocations.
3780b57cec5SDimitry Andric //
3790b57cec5SDimitry Andric // To support future compiler optimizations where which non-volatile registers
3800b57cec5SDimitry Andric // are saved changes within a function (e.g. delay saving non-volatiles until
3810b57cec5SDimitry Andric // necessary), there can by multiple lines in the __compact_unwind table for one
3820b57cec5SDimitry Andric // function, each with a different (non-overlapping) range and each with
3830b57cec5SDimitry Andric // different compact unwind encodings that correspond to the non-volatiles
3840b57cec5SDimitry Andric // saved at that range of the function.
3850b57cec5SDimitry Andric //
3860b57cec5SDimitry Andric // If a particular function is so wacky that there is no compact unwind way
3870b57cec5SDimitry Andric // to encode it, then the compiler can emit traditional DWARF unwind info.
3880b57cec5SDimitry Andric // The runtime will use which ever is available.
3890b57cec5SDimitry Andric //
3900b57cec5SDimitry Andric // Runtime support for compact unwind encodings are only available on 10.6
3910b57cec5SDimitry Andric // and later.  So, the compiler should not generate it when targeting pre-10.6.
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric ////////////////////////////////////////////////////////////////////////////////
3970b57cec5SDimitry Andric //
3980b57cec5SDimitry Andric //  Final Linked Images: __TEXT,__unwind_info
3990b57cec5SDimitry Andric //
4000b57cec5SDimitry Andric ////////////////////////////////////////////////////////////////////////////////
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric //
4030b57cec5SDimitry Andric // The __TEXT,__unwind_info section is laid out for an efficient two level lookup.
4040b57cec5SDimitry Andric // The header of the section contains a coarse index that maps function address
4050b57cec5SDimitry Andric // to the page (4096 byte block) containing the unwind info for that function.
4060b57cec5SDimitry Andric //
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric #define UNWIND_SECTION_VERSION 1
4090b57cec5SDimitry Andric struct unwind_info_section_header
4100b57cec5SDimitry Andric {
4110b57cec5SDimitry Andric     uint32_t    version;            // UNWIND_SECTION_VERSION
4120b57cec5SDimitry Andric     uint32_t    commonEncodingsArraySectionOffset;
4130b57cec5SDimitry Andric     uint32_t    commonEncodingsArrayCount;
4140b57cec5SDimitry Andric     uint32_t    personalityArraySectionOffset;
4150b57cec5SDimitry Andric     uint32_t    personalityArrayCount;
4160b57cec5SDimitry Andric     uint32_t    indexSectionOffset;
4170b57cec5SDimitry Andric     uint32_t    indexCount;
4180b57cec5SDimitry Andric     // compact_unwind_encoding_t[]
4190b57cec5SDimitry Andric     // uint32_t personalities[]
4200b57cec5SDimitry Andric     // unwind_info_section_header_index_entry[]
4210b57cec5SDimitry Andric     // unwind_info_section_header_lsda_index_entry[]
4220b57cec5SDimitry Andric };
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric struct unwind_info_section_header_index_entry
4250b57cec5SDimitry Andric {
4260b57cec5SDimitry Andric     uint32_t        functionOffset;
4270b57cec5SDimitry Andric     uint32_t        secondLevelPagesSectionOffset;  // section offset to start of regular or compress page
4280b57cec5SDimitry Andric     uint32_t        lsdaIndexArraySectionOffset;    // section offset to start of lsda_index array for this range
4290b57cec5SDimitry Andric };
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric struct unwind_info_section_header_lsda_index_entry
4320b57cec5SDimitry Andric {
4330b57cec5SDimitry Andric     uint32_t        functionOffset;
4340b57cec5SDimitry Andric     uint32_t        lsdaOffset;
4350b57cec5SDimitry Andric };
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric //
4380b57cec5SDimitry Andric // There are two kinds of second level index pages: regular and compressed.
4390b57cec5SDimitry Andric // A compressed page can hold up to 1021 entries, but it cannot be used
4400b57cec5SDimitry Andric // if too many different encoding types are used.  The regular page holds
4410b57cec5SDimitry Andric // 511 entries.
4420b57cec5SDimitry Andric //
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric struct unwind_info_regular_second_level_entry
4450b57cec5SDimitry Andric {
4460b57cec5SDimitry Andric     uint32_t                    functionOffset;
4470b57cec5SDimitry Andric     compact_unwind_encoding_t    encoding;
4480b57cec5SDimitry Andric };
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric #define UNWIND_SECOND_LEVEL_REGULAR 2
4510b57cec5SDimitry Andric struct unwind_info_regular_second_level_page_header
4520b57cec5SDimitry Andric {
4530b57cec5SDimitry Andric     uint32_t    kind;    // UNWIND_SECOND_LEVEL_REGULAR
4540b57cec5SDimitry Andric     uint16_t    entryPageOffset;
4550b57cec5SDimitry Andric     uint16_t    entryCount;
4560b57cec5SDimitry Andric     // entry array
4570b57cec5SDimitry Andric };
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric #define UNWIND_SECOND_LEVEL_COMPRESSED 3
4600b57cec5SDimitry Andric struct unwind_info_compressed_second_level_page_header
4610b57cec5SDimitry Andric {
4620b57cec5SDimitry Andric     uint32_t    kind;    // UNWIND_SECOND_LEVEL_COMPRESSED
4630b57cec5SDimitry Andric     uint16_t    entryPageOffset;
4640b57cec5SDimitry Andric     uint16_t    entryCount;
4650b57cec5SDimitry Andric     uint16_t    encodingsPageOffset;
4660b57cec5SDimitry Andric     uint16_t    encodingsCount;
4670b57cec5SDimitry Andric     // 32-bit entry array
4680b57cec5SDimitry Andric     // encodings array
4690b57cec5SDimitry Andric };
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric #define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry)            (entry & 0x00FFFFFF)
4720b57cec5SDimitry Andric #define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry)        ((entry >> 24) & 0xFF)
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric #endif
4770b57cec5SDimitry Andric 
478