diff --git a/libunwind/include/mach-o/compact_unwind_encoding.h b/libunwind/include/mach-o/compact_unwind_encoding.h --- a/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/libunwind/include/mach-o/compact_unwind_encoding.h @@ -9,7 +9,6 @@ // //===----------------------------------------------------------------------===// - #ifndef __COMPACT_UNWIND_ENCODING__ #define __COMPACT_UNWIND_ENCODING__ @@ -31,7 +30,6 @@ // Note: Previously, the linker would transform some DWARF unwind infos into // compact unwind info. But that is fragile and no longer done. - // // The compact unwind encoding is a 32-bit value which encoded in an // architecture specific way, which registers to restore from where, and how @@ -39,17 +37,13 @@ // typedef uint32_t compact_unwind_encoding_t; - // architecture independent bits enum { - UNWIND_IS_NOT_FUNCTION_START = 0x80000000, - UNWIND_HAS_LSDA = 0x40000000, - UNWIND_PERSONALITY_MASK = 0x30000000, + UNWIND_IS_NOT_FUNCTION_START = 0x80000000, + UNWIND_HAS_LSDA = 0x40000000, + UNWIND_PERSONALITY_MASK = 0x30000000, }; - - - // // x86 // @@ -68,67 +62,68 @@ // 10-bits register permutation // enum { - UNWIND_X86_MODE_MASK = 0x0F000000, - UNWIND_X86_MODE_EBP_FRAME = 0x01000000, - UNWIND_X86_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_MODE_STACK_IND = 0x03000000, - UNWIND_X86_MODE_DWARF = 0x04000000, + UNWIND_X86_MODE_MASK = 0x0F000000, + UNWIND_X86_MODE_EBP_FRAME = 0x01000000, + UNWIND_X86_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_MODE_STACK_IND = 0x03000000, + UNWIND_X86_MODE_DWARF = 0x04000000, - UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, + UNWIND_X86_EBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_EBP_FRAME_OFFSET = 0x00FF0000, - UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + UNWIND_X86_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, + UNWIND_X86_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; enum { - UNWIND_X86_REG_NONE = 0, - UNWIND_X86_REG_EBX = 1, - UNWIND_X86_REG_ECX = 2, - UNWIND_X86_REG_EDX = 3, - UNWIND_X86_REG_EDI = 4, - UNWIND_X86_REG_ESI = 5, - UNWIND_X86_REG_EBP = 6, + UNWIND_X86_REG_NONE = 0, + UNWIND_X86_REG_EBX = 1, + UNWIND_X86_REG_ECX = 2, + UNWIND_X86_REG_EDX = 3, + UNWIND_X86_REG_EDI = 4, + UNWIND_X86_REG_ESI = 5, + UNWIND_X86_REG_EBP = 6, }; // // For x86 there are four modes for the compact unwind encoding: // UNWIND_X86_MODE_EBP_FRAME: -// EBP based frame where EBP is push on stack immediately after return address, -// then ESP is moved to EBP. Thus, to unwind ESP is restored with the current -// EPB value, then EBP is restored by popping off the stack, and the return -// is done by popping the stack once more into the pc. -// All non-volatile registers that need to be restored must have been saved -// in a small range in the stack that starts EBP-4 to EBP-1020. The offset/4 -// is encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved -// are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries. +// EBP based frame where EBP is push on stack immediately after return +// address, then ESP is moved to EBP. Thus, to unwind ESP is restored with +// the current EPB value, then EBP is restored by popping off the stack, and +// the return is done by popping the stack once more into the pc. All +// non-volatile registers that need to be restored must have been saved in a +// small range in the stack that starts EBP-4 to EBP-1020. The offset/4 is +// encoded in the UNWIND_X86_EBP_FRAME_OFFSET bits. The registers saved are +// encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries. // Each entry contains which register to restore. // UNWIND_X86_MODE_STACK_IMMD: -// A "frameless" (EBP not used as frame pointer) function with a small +// A "frameless" (EBP not used as frame pointer) function with a small // constant stack size. To return, a constant (encoded in the compact // unwind encoding) is added to the ESP. Then the return is done by // popping the stack into the pc. // All non-volatile registers that need to be restored must have been saved // on the stack immediately after the return address. The stack_size/4 is // encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024). -// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT. +// The number of registers saved is encoded in +// UNWIND_X86_FRAMELESS_STACK_REG_COUNT. // UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were // saved and their order. // UNWIND_X86_MODE_STACK_IND: -// A "frameless" (EBP not used as frame pointer) function large constant +// A "frameless" (EBP not used as frame pointer) function large constant // stack size. This case is like the previous, except the stack size is too -// large to encode in the compact unwind encoding. Instead it requires that -// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact +// large to encode in the compact unwind encoding. Instead it requires that +// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact // encoding contains the offset to the nnnnnnnn value in the function in -// UNWIND_X86_FRAMELESS_STACK_SIZE. +// UNWIND_X86_FRAMELESS_STACK_SIZE. // UNWIND_X86_MODE_DWARF: // No compact unwind encoding is available. Instead the low 24-bits of the // compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the +// This mode is never used in object files. It is only generated by the // linker in final linked images which have only DWARF unwind info for a // function. // @@ -140,7 +135,7 @@ // with frameless stacks. It is passed the number of registers to be saved and // an array of the register numbers saved. // -//uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6]) +// uint32_t permute_encode(uint32_t registerCount, const uint32_t registers[6]) //{ // uint32_t renumregs[6]; // for (int i=6-registerCount; i < 6; ++i) { @@ -182,9 +177,6 @@ //} // - - - // // x86_64 // @@ -203,71 +195,71 @@ // 10-bits register permutation // enum { - UNWIND_X86_64_MODE_MASK = 0x0F000000, - UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, - UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, - UNWIND_X86_64_MODE_STACK_IND = 0x03000000, - UNWIND_X86_64_MODE_DWARF = 0x04000000, + UNWIND_X86_64_MODE_MASK = 0x0F000000, + UNWIND_X86_64_MODE_RBP_FRAME = 0x01000000, + UNWIND_X86_64_MODE_STACK_IMMD = 0x02000000, + UNWIND_X86_64_MODE_STACK_IND = 0x03000000, + UNWIND_X86_64_MODE_DWARF = 0x04000000, - UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, - UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, + UNWIND_X86_64_RBP_FRAME_REGISTERS = 0x00007FFF, + UNWIND_X86_64_RBP_FRAME_OFFSET = 0x00FF0000, - UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, - UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, - UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, - UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, + UNWIND_X86_64_FRAMELESS_STACK_SIZE = 0x00FF0000, + UNWIND_X86_64_FRAMELESS_STACK_ADJUST = 0x0000E000, + UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT = 0x00001C00, + UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION = 0x000003FF, - UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + UNWIND_X86_64_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; enum { - UNWIND_X86_64_REG_NONE = 0, - UNWIND_X86_64_REG_RBX = 1, - UNWIND_X86_64_REG_R12 = 2, - UNWIND_X86_64_REG_R13 = 3, - UNWIND_X86_64_REG_R14 = 4, - UNWIND_X86_64_REG_R15 = 5, - UNWIND_X86_64_REG_RBP = 6, + UNWIND_X86_64_REG_NONE = 0, + UNWIND_X86_64_REG_RBX = 1, + UNWIND_X86_64_REG_R12 = 2, + UNWIND_X86_64_REG_R13 = 3, + UNWIND_X86_64_REG_R14 = 4, + UNWIND_X86_64_REG_R15 = 5, + UNWIND_X86_64_REG_RBP = 6, }; // // For x86_64 there are four modes for the compact unwind encoding: // UNWIND_X86_64_MODE_RBP_FRAME: -// RBP based frame where RBP is push on stack immediately after return address, -// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current -// EPB value, then RBP is restored by popping off the stack, and the return -// is done by popping the stack once more into the pc. -// All non-volatile registers that need to be restored must have been saved -// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8 -// is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved -// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries. -// Each entry contains which register to restore. +// RBP based frame where RBP is push on stack immediately after return +// address, then RSP is moved to RBP. Thus, to unwind RSP is restored with +// the current EPB value, then RBP is restored by popping off the stack, and +// the return is done by popping the stack once more into the pc. All +// non-volatile registers that need to be restored must have been saved in a +// small range in the stack that starts RBP-8 to RBP-2040. The offset/8 is +// encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved +// are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit +// entries. Each entry contains which register to restore. // UNWIND_X86_64_MODE_STACK_IMMD: -// A "frameless" (RBP not used as frame pointer) function with a small -// constant stack size. To return, a constant (encoded in the compact -// unwind encoding) is added to the RSP. Then the return is done by +// A "frameless" (RBP not used as frame pointer) function with a small +// constant stack size. To return, a constant (encoded in the compact +// unwind encoding) is added to the RSP. Then the return is done by // popping the stack into the pc. // All non-volatile registers that need to be restored must have been saved // on the stack immediately after the return address. The stack_size/8 is -// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048). -// The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT. -// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were -// saved and their order. +// encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is +// 2048). The number of registers saved is encoded in +// UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT. +// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers +// were saved and their order. // UNWIND_X86_64_MODE_STACK_IND: -// A "frameless" (RBP not used as frame pointer) function large constant +// A "frameless" (RBP not used as frame pointer) function large constant // stack size. This case is like the previous, except the stack size is too -// large to encode in the compact unwind encoding. Instead it requires that -// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact +// large to encode in the compact unwind encoding. Instead it requires that +// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact // encoding contains the offset to the nnnnnnnn value in the function in -// UNWIND_X86_64_FRAMELESS_STACK_SIZE. +// UNWIND_X86_64_FRAMELESS_STACK_SIZE. // UNWIND_X86_64_MODE_DWARF: // No compact unwind encoding is available. Instead the low 24-bits of the // compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the +// This mode is never used in object files. It is only generated by the // linker in final linked images which have only DWARF unwind info for a // function. // - // ARM64 // // 1-bit: start @@ -284,51 +276,47 @@ // 24-bits offset of DWARF FDE in __eh_frame section // enum { - UNWIND_ARM64_MODE_MASK = 0x0F000000, - UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, - UNWIND_ARM64_MODE_DWARF = 0x03000000, - UNWIND_ARM64_MODE_FRAME = 0x04000000, - - UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, - UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, - UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, - UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, - UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, - UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, - UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, - UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, - UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, - - UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, - UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, + UNWIND_ARM64_MODE_MASK = 0x0F000000, + UNWIND_ARM64_MODE_FRAMELESS = 0x02000000, + UNWIND_ARM64_MODE_DWARF = 0x03000000, + UNWIND_ARM64_MODE_FRAME = 0x04000000, + + UNWIND_ARM64_FRAME_X19_X20_PAIR = 0x00000001, + UNWIND_ARM64_FRAME_X21_X22_PAIR = 0x00000002, + UNWIND_ARM64_FRAME_X23_X24_PAIR = 0x00000004, + UNWIND_ARM64_FRAME_X25_X26_PAIR = 0x00000008, + UNWIND_ARM64_FRAME_X27_X28_PAIR = 0x00000010, + UNWIND_ARM64_FRAME_D8_D9_PAIR = 0x00000100, + UNWIND_ARM64_FRAME_D10_D11_PAIR = 0x00000200, + UNWIND_ARM64_FRAME_D12_D13_PAIR = 0x00000400, + UNWIND_ARM64_FRAME_D14_D15_PAIR = 0x00000800, + + UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK = 0x00FFF000, + UNWIND_ARM64_DWARF_SECTION_OFFSET = 0x00FFFFFF, }; // For arm64 there are three modes for the compact unwind encoding: // UNWIND_ARM64_MODE_FRAME: // This is a standard arm64 prolog where FP/LR are immediately pushed on the // stack, then SP is copied to FP. If there are any non-volatile registers // saved, then are copied into the stack frame in pairs in a contiguous -// range right below the saved FP/LR pair. Any subset of the five X pairs +// range right below the saved FP/LR pair. Any subset of the five X pairs // and four D pairs can be saved, but the memory layout must be in register -// number order. +// number order. // UNWIND_ARM64_MODE_FRAMELESS: -// A "frameless" leaf function, where FP/LR are not saved. The return address +// A "frameless" leaf function, where FP/LR are not saved. The return address // remains in LR throughout the function. If any non-volatile registers // are saved, they must be pushed onto the stack before any stack space is // allocated for local variables. The stack sized (including any saved -// non-volatile registers) divided by 16 is encoded in the bits +// non-volatile registers) divided by 16 is encoded in the bits // UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK. // UNWIND_ARM64_MODE_DWARF: // No compact unwind encoding is available. Instead the low 24-bits of the // compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the +// This mode is never used in object files. It is only generated by the // linker in final linked images which have only DWARF unwind info for a // function. // - - - - //////////////////////////////////////////////////////////////////////////////// // // Relocatable Object Files: __LD,__compact_unwind @@ -337,19 +325,19 @@ // // A compiler can generated compact unwind information for a function by adding -// a "row" to the __LD,__compact_unwind section. This section has the -// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. -// It is removed by the new linker, so never ends up in final executables. -// This section is a table, initially with one row per function (that needs +// a "row" to the __LD,__compact_unwind section. This section has the +// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. +// It is removed by the new linker, so never ends up in final executables. +// This section is a table, initially with one row per function (that needs // unwind info). The table columns and some conceptual entries are: // // range-start pointer to start of function/range -// range-length -// compact-unwind-encoding 32-bit encoding +// range-length +// compact-unwind-encoding 32-bit encoding // personality-function or zero if no personality function // lsda or zero if no LSDA data // -// The length and encoding fields are 32-bits. The other are all pointer sized. +// The length and encoding fields are 32-bits. The other are all pointer sized. // // In x86_64 assembly, these entry would look like: // @@ -372,26 +360,23 @@ // .quad except_tab1 // // -// Notes: There is no need for any labels in the the __compact_unwind section. -// The use of the .set directive is to force the evaluation of the +// Notes: There is no need for any labels in the __compact_unwind section. +// The use of the .set directive is to force the evaluation of the // range-length at assembly time, instead of generating relocations. // -// To support future compiler optimizations where which non-volatile registers +// To support future compiler optimizations where which non-volatile registers // are saved changes within a function (e.g. delay saving non-volatiles until // necessary), there can by multiple lines in the __compact_unwind table for one -// function, each with a different (non-overlapping) range and each with -// different compact unwind encodings that correspond to the non-volatiles +// function, each with a different (non-overlapping) range and each with +// different compact unwind encodings that correspond to the non-volatiles // saved at that range of the function. // // If a particular function is so wacky that there is no compact unwind way -// to encode it, then the compiler can emit traditional DWARF unwind info. +// to encode it, then the compiler can emit traditional DWARF unwind info. // The runtime will use which ever is available. // -// Runtime support for compact unwind encodings are only available on 10.6 -// and later. So, the compiler should not generate it when targeting pre-10.6. - - - +// Runtime support for compact unwind encodings are only available on 10.6 +// and later. So, the compiler should not generate it when targeting pre-10.6. //////////////////////////////////////////////////////////////////////////////// // @@ -400,38 +385,38 @@ //////////////////////////////////////////////////////////////////////////////// // -// The __TEXT,__unwind_info section is laid out for an efficient two level lookup. -// The header of the section contains a coarse index that maps function address -// to the page (4096 byte block) containing the unwind info for that function. +// The __TEXT,__unwind_info section is laid out for an efficient two level +// lookup. The header of the section contains a coarse index that maps function +// address to the page (4096 byte block) containing the unwind info for that +// function. // #define UNWIND_SECTION_VERSION 1 -struct unwind_info_section_header -{ - uint32_t version; // UNWIND_SECTION_VERSION - uint32_t commonEncodingsArraySectionOffset; - uint32_t commonEncodingsArrayCount; - uint32_t personalityArraySectionOffset; - uint32_t personalityArrayCount; - uint32_t indexSectionOffset; - uint32_t indexCount; - // compact_unwind_encoding_t[] - // uint32_t personalities[] - // unwind_info_section_header_index_entry[] - // unwind_info_section_header_lsda_index_entry[] +struct unwind_info_section_header { + uint32_t version; // UNWIND_SECTION_VERSION + uint32_t commonEncodingsArraySectionOffset; + uint32_t commonEncodingsArrayCount; + uint32_t personalityArraySectionOffset; + uint32_t personalityArrayCount; + uint32_t indexSectionOffset; + uint32_t indexCount; + // compact_unwind_encoding_t[] + // uint32_t personalities[] + // unwind_info_section_header_index_entry[] + // unwind_info_section_header_lsda_index_entry[] }; -struct unwind_info_section_header_index_entry -{ - uint32_t functionOffset; - uint32_t secondLevelPagesSectionOffset; // section offset to start of regular or compress page - uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index array for this range +struct unwind_info_section_header_index_entry { + uint32_t functionOffset; + uint32_t secondLevelPagesSectionOffset; // section offset to start of regular + // or compress page + uint32_t lsdaIndexArraySectionOffset; // section offset to start of lsda_index + // array for this range }; -struct unwind_info_section_header_lsda_index_entry -{ - uint32_t functionOffset; - uint32_t lsdaOffset; +struct unwind_info_section_header_lsda_index_entry { + uint32_t functionOffset; + uint32_t lsdaOffset; }; // @@ -441,37 +426,32 @@ // 511 entries. // -struct unwind_info_regular_second_level_entry -{ - uint32_t functionOffset; - compact_unwind_encoding_t encoding; +struct unwind_info_regular_second_level_entry { + uint32_t functionOffset; + compact_unwind_encoding_t encoding; }; #define UNWIND_SECOND_LEVEL_REGULAR 2 -struct unwind_info_regular_second_level_page_header -{ - uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR - uint16_t entryPageOffset; - uint16_t entryCount; - // entry array +struct unwind_info_regular_second_level_page_header { + uint32_t kind; // UNWIND_SECOND_LEVEL_REGULAR + uint16_t entryPageOffset; + uint16_t entryCount; + // entry array }; #define UNWIND_SECOND_LEVEL_COMPRESSED 3 -struct unwind_info_compressed_second_level_page_header -{ - uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED - uint16_t entryPageOffset; - uint16_t entryCount; - uint16_t encodingsPageOffset; - uint16_t encodingsCount; - // 32-bit entry array - // encodings array +struct unwind_info_compressed_second_level_page_header { + uint32_t kind; // UNWIND_SECOND_LEVEL_COMPRESSED + uint16_t entryPageOffset; + uint16_t entryCount; + uint16_t encodingsPageOffset; + uint16_t encodingsCount; + // 32-bit entry array + // encodings array }; -#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) -#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) ((entry >> 24) & 0xFF) - - +#define UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) (entry & 0x00FFFFFF) +#define UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry) \ + ((entry >> 24) & 0xFF) #endif -