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