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