| author | |
| committer | |
| log | 20f08ad09c515099b316e3624e0986cdcb8d2b93 |
| tree | 6ca62bc7a1870443f4f9df285411ebe7261debe9 |
| parent | 78591e1d988b8983d811d573fbbf6de5a93baa07 |
| signature |
21 files changed, 1069 insertions(+), 200 deletions(-)
lib/libunwind/include/__libunwind_config.h+11-2| ... | @@ -73,11 +73,11 @@ | ... | @@ -73,11 +73,11 @@ |
| 73 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC | 73 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC |
| 74 | # elif defined(__aarch64__) | 74 | # elif defined(__aarch64__) |
| 75 | # define _LIBUNWIND_TARGET_AARCH64 1 | 75 | # define _LIBUNWIND_TARGET_AARCH64 1 |
| 76 | # define _LIBUNWIND_CONTEXT_SIZE 66 | 76 | #define _LIBUNWIND_CONTEXT_SIZE 67 |
| 77 | # if defined(__SEH__) | 77 | # if defined(__SEH__) |
| 78 | # define _LIBUNWIND_CURSOR_SIZE 164 | 78 | # define _LIBUNWIND_CURSOR_SIZE 164 |
| 79 | # else | 79 | # else |
| 80 | # define _LIBUNWIND_CURSOR_SIZE 78 | 80 | #define _LIBUNWIND_CURSOR_SIZE 79 |
| 81 | # endif | 81 | # endif |
| 82 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 | 82 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 |
| 83 | # elif defined(__arm__) | 83 | # elif defined(__arm__) |
| ... | @@ -212,4 +212,13 @@ | ... | @@ -212,4 +212,13 @@ |
| 212 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 | 212 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 |
| 213 | #endif // _LIBUNWIND_IS_NATIVE_ONLY | 213 | #endif // _LIBUNWIND_IS_NATIVE_ONLY |
| 214 | 214 | ||
| 215 | #if defined(__has_feature) | ||
| 216 | # if __has_feature(ptrauth_calls) && __has_feature(ptrauth_returns) | ||
| 217 | # define _LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING 1 | ||
| 218 | # elif __has_feature(ptrauth_calls) != __has_feature(ptrauth_returns) | ||
| 219 | # error "Either both or none of ptrauth_calls and ptrauth_returns "\ | ||
| 220 | "is allowed to be enabled" | ||
| 221 | # endif | ||
| 222 | #endif | ||
| 223 | |||
| 215 | #endif // ____LIBUNWIND_CONFIG_H__ | 224 | #endif // ____LIBUNWIND_CONFIG_H__ |
lib/libunwind/include/libunwind.h+117-11| ... | @@ -43,6 +43,109 @@ | ... | @@ -43,6 +43,109 @@ |
| 43 | #define LIBUNWIND_AVAIL | 43 | #define LIBUNWIND_AVAIL |
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 47 | |||
| 48 | #include <ptrauth.h> | ||
| 49 | |||
| 50 | // `__ptrauth_restricted_intptr` is a feature of apple clang that predates | ||
| 51 | // support for direct application of `__ptrauth` to integer types. This | ||
| 52 | // guard is necessary to support compilation with those compiler. | ||
| 53 | #if __has_extension(ptrauth_restricted_intptr_qualifier) | ||
| 54 | #define __unwind_ptrauth_restricted_intptr(...) \ | ||
| 55 | __ptrauth_restricted_intptr(__VA_ARGS__) | ||
| 56 | #else | ||
| 57 | #define __unwind_ptrauth_restricted_intptr(...) \ | ||
| 58 | __ptrauth(__VA_ARGS__) | ||
| 59 | #endif | ||
| 60 | |||
| 61 | // ptrauth_string_discriminator("unw_proc_info_t::handler") == 0x7405 | ||
| 62 | #define __ptrauth_unwind_upi_handler_disc 0x7405 | ||
| 63 | |||
| 64 | #define __ptrauth_unwind_upi_handler \ | ||
| 65 | __ptrauth(ptrauth_key_function_pointer, 1, __ptrauth_unwind_upi_handler_disc) | ||
| 66 | |||
| 67 | #define __ptrauth_unwind_upi_handler_intptr \ | ||
| 68 | __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1,\ | ||
| 69 | __ptrauth_unwind_upi_handler_disc) | ||
| 70 | |||
| 71 | // ptrauth_string_discriminator("unw_proc_info_t::start_ip") == 0xCA2C | ||
| 72 | #define __ptrauth_unwind_upi_startip \ | ||
| 73 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xCA2C) | ||
| 74 | |||
| 75 | // ptrauth_string_discriminator("unw_proc_info_t::end_ip") == 0xE183 | ||
| 76 | #define __ptrauth_unwind_upi_endip \ | ||
| 77 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_independent_code, 1, 0xE183) | ||
| 78 | |||
| 79 | // ptrauth_string_discriminator("unw_proc_info_t::lsda") == 0x83DE | ||
| 80 | #define __ptrauth_unwind_upi_lsda \ | ||
| 81 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x83DE) | ||
| 82 | |||
| 83 | // ptrauth_string_discriminator("unw_proc_info_t::flags") == 0x79A1 | ||
| 84 | #define __ptrauth_unwind_upi_flags \ | ||
| 85 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x79A1) | ||
| 86 | |||
| 87 | // ptrauth_string_discriminator("unw_proc_info_t::unwind_info") == 0xC20C | ||
| 88 | #define __ptrauth_unwind_upi_info \ | ||
| 89 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xC20C) | ||
| 90 | |||
| 91 | // ptrauth_string_discriminator("unw_proc_info_t::extra") == 0x03DF | ||
| 92 | #define __ptrauth_unwind_upi_extra \ | ||
| 93 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x03DF) | ||
| 94 | |||
| 95 | // ptrauth_string_discriminator("Registers_arm64::link_reg_t") == 0x8301 | ||
| 96 | #define __ptrauth_unwind_registers_arm64_link_reg \ | ||
| 97 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_code, 1, 0x8301) | ||
| 98 | |||
| 99 | // ptrauth_string_discriminator("UnwindInfoSections::dso_base") == 0x4FF5 | ||
| 100 | #define __ptrauth_unwind_uis_dso_base \ | ||
| 101 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4FF5) | ||
| 102 | |||
| 103 | // ptrauth_string_discriminator("UnwindInfoSections::dwarf_section") == 0x4974 | ||
| 104 | #define __ptrauth_unwind_uis_dwarf_section \ | ||
| 105 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x4974) | ||
| 106 | |||
| 107 | // ptrauth_string_discriminator("UnwindInfoSections::dwarf_section_length") == 0x2A9A | ||
| 108 | #define __ptrauth_unwind_uis_dwarf_section_length \ | ||
| 109 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x2A9A) | ||
| 110 | |||
| 111 | // ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section") == 0xA27B | ||
| 112 | #define __ptrauth_unwind_uis_compact_unwind_section \ | ||
| 113 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0xA27B) | ||
| 114 | |||
| 115 | // ptrauth_string_discriminator("UnwindInfoSections::compact_unwind_section_length") == 0x5D0A | ||
| 116 | #define __ptrauth_unwind_uis_compact_unwind_section_length \ | ||
| 117 | __unwind_ptrauth_restricted_intptr(ptrauth_key_process_dependent_data, 1, 0x5D0A) | ||
| 118 | |||
| 119 | // ptrauth_string_discriminator("CIE_Info::personality") == 0x6A40 | ||
| 120 | #define __ptrauth_unwind_cie_info_personality_disc 0x6A40 | ||
| 121 | #define __ptrauth_unwind_cie_info_personality \ | ||
| 122 | __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1, \ | ||
| 123 | __ptrauth_unwind_cie_info_personality_disc) | ||
| 124 | |||
| 125 | // ptrauth_string_discriminator("personality") == 0x7EAD) | ||
| 126 | #define __ptrauth_unwind_pauthtest_personality_disc 0x7EAD | ||
| 127 | |||
| 128 | #else | ||
| 129 | |||
| 130 | #define __unwind_ptrauth_restricted_intptr(...) | ||
| 131 | #define __ptrauth_unwind_upi_handler | ||
| 132 | #define __ptrauth_unwind_upi_handler_intptr | ||
| 133 | #define __ptrauth_unwind_upi_startip | ||
| 134 | #define __ptrauth_unwind_upi_endip | ||
| 135 | #define __ptrauth_unwind_upi_lsda | ||
| 136 | #define __ptrauth_unwind_upi_flags | ||
| 137 | #define __ptrauth_unwind_upi_info | ||
| 138 | #define __ptrauth_unwind_upi_extra | ||
| 139 | #define __ptrauth_unwind_registers_arm64_link_reg | ||
| 140 | #define __ptrauth_unwind_uis_dso_base | ||
| 141 | #define __ptrauth_unwind_uis_dwarf_section | ||
| 142 | #define __ptrauth_unwind_uis_dwarf_section_length | ||
| 143 | #define __ptrauth_unwind_uis_compact_unwind_section | ||
| 144 | #define __ptrauth_unwind_uis_compact_unwind_section_length | ||
| 145 | #define __ptrauth_unwind_cie_info_personality | ||
| 146 | |||
| 147 | #endif | ||
| 148 | |||
| 46 | #if defined(_WIN32) && defined(__SEH__) | 149 | #if defined(_WIN32) && defined(__SEH__) |
| 47 | #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16))) | 150 | #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16))) |
| 48 | #else | 151 | #else |
| ... | @@ -88,17 +191,18 @@ typedef double unw_fpreg_t; | ... | @@ -88,17 +191,18 @@ typedef double unw_fpreg_t; |
| 88 | #endif | 191 | #endif |
| 89 | 192 | ||
| 90 | struct unw_proc_info_t { | 193 | struct unw_proc_info_t { |
| 91 | unw_word_t start_ip; /* start address of function */ | 194 | unw_word_t __ptrauth_unwind_upi_startip start_ip; /* start address of function */ |
| 92 | unw_word_t end_ip; /* address after end of function */ | 195 | unw_word_t __ptrauth_unwind_upi_endip end_ip; /* address after end of function */ |
| 93 | unw_word_t lsda; /* address of language specific data area, */ | 196 | unw_word_t __ptrauth_unwind_upi_lsda lsda; /* address of language specific data area, */ |
| 94 | /* or zero if not used */ | 197 | /* or zero if not used */ |
| 95 | unw_word_t handler; /* personality routine, or zero if not used */ | 198 | |
| 96 | unw_word_t gp; /* not used */ | 199 | unw_word_t __ptrauth_unwind_upi_handler_intptr handler; |
| 97 | unw_word_t flags; /* not used */ | 200 | unw_word_t gp; /* not used */ |
| 98 | uint32_t format; /* compact unwind encoding, or zero if none */ | 201 | unw_word_t __ptrauth_unwind_upi_flags flags; /* not used */ |
| 99 | uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */ | 202 | uint32_t format; /* compact unwind encoding, or zero if none */ |
| 100 | unw_word_t unwind_info; /* address of DWARF unwind info, or zero */ | 203 | uint32_t unwind_info_size; /* size of DWARF unwind info, or zero if none */ |
| 101 | unw_word_t extra; /* mach_header of mach-o image containing func */ | 204 | unw_word_t __ptrauth_unwind_upi_info unwind_info; /* address of DWARF unwind info, or zero */ |
| 205 | unw_word_t __ptrauth_unwind_upi_extra extra; /* mach_header of mach-o image containing func */ | ||
| 102 | }; | 206 | }; |
| 103 | typedef struct unw_proc_info_t unw_proc_info_t; | 207 | typedef struct unw_proc_info_t unw_proc_info_t; |
| 104 | 208 | ||
| ... | @@ -130,6 +234,7 @@ extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; | ... | @@ -130,6 +234,7 @@ extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; |
| 130 | extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL; | 234 | extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL; |
| 131 | extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL; | 235 | extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL; |
| 132 | //extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); | 236 | //extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); |
| 237 | extern const char *unw_strerror(int) LIBUNWIND_AVAIL; | ||
| 133 | 238 | ||
| 134 | extern unw_addr_space_t unw_local_addr_space; | 239 | extern unw_addr_space_t unw_local_addr_space; |
| 135 | 240 | ||
| ... | @@ -532,6 +637,7 @@ enum { | ... | @@ -532,6 +637,7 @@ enum { |
| 532 | UNW_AARCH64_X31 = 31, | 637 | UNW_AARCH64_X31 = 31, |
| 533 | UNW_AARCH64_SP = 31, | 638 | UNW_AARCH64_SP = 31, |
| 534 | UNW_AARCH64_PC = 32, | 639 | UNW_AARCH64_PC = 32, |
| 640 | UNW_AARCH64_VG = 46, | ||
| 535 | 641 | ||
| 536 | // reserved block | 642 | // reserved block |
| 537 | UNW_AARCH64_RA_SIGN_STATE = 34, | 643 | UNW_AARCH64_RA_SIGN_STATE = 34, |
lib/libunwind/include/unwind_arm_ehabi.h+4-1| ... | @@ -125,8 +125,11 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, | ... | @@ -125,8 +125,11 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, |
| 125 | uint32_t discriminator, | 125 | uint32_t discriminator, |
| 126 | _Unwind_VRS_DataRepresentation representation); | 126 | _Unwind_VRS_DataRepresentation representation); |
| 127 | 127 | ||
| 128 | extern _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception *, | ||
| 129 | _Unwind_Context *); | ||
| 130 | |||
| 128 | #if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) | 131 | #if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) |
| 129 | #define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern | 132 | #define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern __inline__ |
| 130 | #else | 133 | #else |
| 131 | #define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ | 134 | #define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ |
| 132 | #endif | 135 | #endif |
lib/libunwind/src/AddressSpace.hpp+40-19| ... | @@ -129,22 +129,27 @@ struct UnwindInfoSections { | ... | @@ -129,22 +129,27 @@ struct UnwindInfoSections { |
| 129 | defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \ | 129 | defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \ |
| 130 | defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | 130 | defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 131 | // No dso_base for SEH. | 131 | // No dso_base for SEH. |
| 132 | uintptr_t dso_base; | 132 | uintptr_t __ptrauth_unwind_uis_dso_base |
| 133 | dso_base = 0; | ||
| 133 | #endif | 134 | #endif |
| 134 | #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | 135 | #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 135 | size_t text_segment_length; | 136 | size_t text_segment_length; |
| 136 | #endif | 137 | #endif |
| 137 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 138 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 138 | uintptr_t dwarf_section; | 139 | uintptr_t __ptrauth_unwind_uis_dwarf_section |
| 139 | size_t dwarf_section_length; | 140 | dwarf_section = 0; |
| 141 | size_t __ptrauth_unwind_uis_dwarf_section_length | ||
| 142 | dwarf_section_length = 0; | ||
| 140 | #endif | 143 | #endif |
| 141 | #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | 144 | #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) |
| 142 | uintptr_t dwarf_index_section; | 145 | uintptr_t dwarf_index_section; |
| 143 | size_t dwarf_index_section_length; | 146 | size_t dwarf_index_section_length; |
| 144 | #endif | 147 | #endif |
| 145 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) | 148 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
| 146 | uintptr_t compact_unwind_section; | 149 | uintptr_t __ptrauth_unwind_uis_compact_unwind_section |
| 147 | size_t compact_unwind_section_length; | 150 | compact_unwind_section = 0; |
| 151 | size_t __ptrauth_unwind_uis_compact_unwind_section_length | ||
| 152 | compact_unwind_section_length = 0; | ||
| 148 | #endif | 153 | #endif |
| 149 | #if defined(_LIBUNWIND_ARM_EHABI) | 154 | #if defined(_LIBUNWIND_ARM_EHABI) |
| 150 | uintptr_t arm_section; | 155 | uintptr_t arm_section; |
| ... | @@ -196,11 +201,16 @@ public: | ... | @@ -196,11 +201,16 @@ public: |
| 196 | static int64_t getSLEB128(pint_t &addr, pint_t end); | 201 | static int64_t getSLEB128(pint_t &addr, pint_t end); |
| 197 | 202 | ||
| 198 | pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, | 203 | pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, |
| 199 | pint_t datarelBase = 0); | 204 | pint_t datarelBase = 0, pint_t *resultAddr = nullptr); |
| 200 | bool findFunctionName(pint_t addr, char *buf, size_t bufLen, | 205 | template <typename R> |
| 201 | unw_word_t *offset); | 206 | bool findFunctionName(typename R::link_hardened_reg_arg_t addr, char *buf, |
| 202 | bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); | 207 | size_t bufLen, unw_word_t *offset); |
| 203 | bool findOtherFDE(pint_t targetAddr, pint_t &fde); | 208 | template <typename R> |
| 209 | bool findUnwindSections(typename R::link_hardened_reg_arg_t targetAddr, | ||
| 210 | UnwindInfoSections &info); | ||
| 211 | template <typename R> | ||
| 212 | bool findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr, | ||
| 213 | pint_t &fde); | ||
| 204 | 214 | ||
| 205 | static LocalAddressSpace sThisAddressSpace; | 215 | static LocalAddressSpace sThisAddressSpace; |
| 206 | }; | 216 | }; |
| ... | @@ -269,7 +279,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { | ... | @@ -269,7 +279,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { |
| 269 | 279 | ||
| 270 | inline LocalAddressSpace::pint_t | 280 | inline LocalAddressSpace::pint_t |
| 271 | LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, | 281 | LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, |
| 272 | pint_t datarelBase) { | 282 | pint_t datarelBase, pint_t *resultAddr) { |
| 273 | pint_t startAddr = addr; | 283 | pint_t startAddr = addr; |
| 274 | const uint8_t *p = (uint8_t *)addr; | 284 | const uint8_t *p = (uint8_t *)addr; |
| 275 | pint_t result; | 285 | pint_t result; |
| ... | @@ -353,8 +363,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, | ... | @@ -353,8 +363,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, |
| 353 | break; | 363 | break; |
| 354 | } | 364 | } |
| 355 | 365 | ||
| 356 | if (encoding & DW_EH_PE_indirect) | 366 | if (encoding & DW_EH_PE_indirect) { |
| 367 | if (resultAddr) | ||
| 368 | *resultAddr = result; | ||
| 357 | result = getP(result); | 369 | result = getP(result); |
| 370 | } else { | ||
| 371 | if (resultAddr) | ||
| 372 | *resultAddr = startAddr; | ||
| 373 | } | ||
| 358 | 374 | ||
| 359 | return result; | 375 | return result; |
| 360 | } | 376 | } |
| ... | @@ -486,9 +502,9 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, | ... | @@ -486,9 +502,9 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, |
| 486 | 502 | ||
| 487 | #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | 503 | #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 488 | 504 | ||
| 489 | 505 | template <typename R> | |
| 490 | inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | 506 | inline bool LocalAddressSpace::findUnwindSections( |
| 491 | UnwindInfoSections &info) { | 507 | typename R::link_hardened_reg_arg_t targetAddr, UnwindInfoSections &info) { |
| 492 | #ifdef __APPLE__ | 508 | #ifdef __APPLE__ |
| 493 | dyld_unwind_sections dyldInfo; | 509 | dyld_unwind_sections dyldInfo; |
| 494 | if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { | 510 | if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { |
| ... | @@ -658,16 +674,21 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | ... | @@ -658,16 +674,21 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 658 | return false; | 674 | return false; |
| 659 | } | 675 | } |
| 660 | 676 | ||
| 661 | inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { | 677 | template <typename R> |
| 678 | inline bool | ||
| 679 | LocalAddressSpace::findOtherFDE(typename R::link_hardened_reg_arg_t targetAddr, | ||
| 680 | pint_t &fde) { | ||
| 662 | // TO DO: if OS has way to dynamically register FDEs, check that. | 681 | // TO DO: if OS has way to dynamically register FDEs, check that. |
| 663 | (void)targetAddr; | 682 | (void)targetAddr; |
| 664 | (void)fde; | 683 | (void)fde; |
| 665 | return false; | 684 | return false; |
| 666 | } | 685 | } |
| 667 | 686 | ||
| 668 | inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, | 687 | template <typename R> |
| 669 | size_t bufLen, | 688 | inline bool |
| 670 | unw_word_t *offset) { | 689 | LocalAddressSpace::findFunctionName(typename R::link_hardened_reg_arg_t addr, |
| 690 | char *buf, size_t bufLen, | ||
| 691 | unw_word_t *offset) { | ||
| 671 | #if _LIBUNWIND_USE_DLADDR | 692 | #if _LIBUNWIND_USE_DLADDR |
| 672 | Dl_info dyldInfo; | 693 | Dl_info dyldInfo; |
| 673 | if (dladdr((void *)addr, &dyldInfo)) { | 694 | if (dladdr((void *)addr, &dyldInfo)) { |
lib/libunwind/src/CompactUnwinder.hpp+16-5| ... | @@ -601,11 +601,17 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( | ... | @@ -601,11 +601,17 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( |
| 601 | savedRegisterLoc -= 8; | 601 | savedRegisterLoc -= 8; |
| 602 | } | 602 | } |
| 603 | 603 | ||
| 604 | // We load the link register prior to setting the new SP as the authentication | ||
| 605 | // schema for LR entangles the SP of the old frame into the diversifier. | ||
| 606 | Registers_arm64::reg_t linkRegister = registers.getRegister(UNW_AARCH64_LR); | ||
| 607 | |||
| 604 | // subtract stack size off of sp | 608 | // subtract stack size off of sp |
| 605 | registers.setSP(savedRegisterLoc); | 609 | registers.setSP(savedRegisterLoc); |
| 606 | 610 | ||
| 607 | // set pc to be value in lr | 611 | // Set pc to be value in lr. This needs to be performed after the new SP has |
| 608 | registers.setIP(registers.getRegister(UNW_AARCH64_LR)); | 612 | // been set, as the PC authentication schema entangles the SP of the new |
| 613 | // frame. | ||
| 614 | registers.setIP(linkRegister); | ||
| 609 | 615 | ||
| 610 | return UNW_STEP_SUCCESS; | 616 | return UNW_STEP_SUCCESS; |
| 611 | } | 617 | } |
| ... | @@ -614,7 +620,7 @@ template <typename A> | ... | @@ -614,7 +620,7 @@ template <typename A> |
| 614 | int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( | 620 | int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( |
| 615 | compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, | 621 | compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, |
| 616 | Registers_arm64 &registers) { | 622 | Registers_arm64 &registers) { |
| 617 | uint64_t savedRegisterLoc = registers.getFP() - 8; | 623 | Registers_arm64::reg_t savedRegisterLoc = registers.getFP() - 8; |
| 618 | 624 | ||
| 619 | if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { | 625 | if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { |
| 620 | registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); | 626 | registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); |
| ... | @@ -680,11 +686,16 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( | ... | @@ -680,11 +686,16 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( |
| 680 | savedRegisterLoc -= 8; | 686 | savedRegisterLoc -= 8; |
| 681 | } | 687 | } |
| 682 | 688 | ||
| 683 | uint64_t fp = registers.getFP(); | 689 | Registers_arm64::reg_t fp = registers.getFP(); |
| 690 | |||
| 684 | // fp points to old fp | 691 | // fp points to old fp |
| 685 | registers.setFP(addressSpace.get64(fp)); | 692 | registers.setFP(addressSpace.get64(fp)); |
| 686 | // old sp is fp less saved fp and lr | 693 | |
| 694 | // Old sp is fp less saved fp and lr. We need to set this prior to setting | ||
| 695 | // the lr as the pointer authentication schema for the lr incorporates the | ||
| 696 | // sp as part of the diversifier. | ||
| 687 | registers.setSP(fp + 16); | 697 | registers.setSP(fp + 16); |
| 698 | |||
| 688 | // pop return address into pc | 699 | // pop return address into pc |
| 689 | registers.setIP(addressSpace.get64(fp + 8)); | 700 | registers.setIP(addressSpace.get64(fp + 8)); |
| 690 | 701 |
lib/libunwind/src/DwarfInstructions.hpp+24-13| ... | @@ -22,7 +22,6 @@ | ... | @@ -22,7 +22,6 @@ |
| 22 | #include "dwarf2.h" | 22 | #include "dwarf2.h" |
| 23 | #include "libunwind_ext.h" | 23 | #include "libunwind_ext.h" |
| 24 | 24 | ||
| 25 | |||
| 26 | namespace libunwind { | 25 | namespace libunwind { |
| 27 | 26 | ||
| 28 | 27 | ||
| ... | @@ -34,8 +33,10 @@ public: | ... | @@ -34,8 +33,10 @@ public: |
| 34 | typedef typename A::pint_t pint_t; | 33 | typedef typename A::pint_t pint_t; |
| 35 | typedef typename A::sint_t sint_t; | 34 | typedef typename A::sint_t sint_t; |
| 36 | 35 | ||
| 37 | static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, | 36 | static int stepWithDwarf(A &addressSpace, |
| 38 | R &registers, bool &isSignalFrame, bool stage2); | 37 | typename R::link_hardened_reg_arg_t pc, |
| 38 | pint_t fdeStart, R &registers, bool &isSignalFrame, | ||
| 39 | bool stage2); | ||
| 39 | 40 | ||
| 40 | private: | 41 | private: |
| 41 | 42 | ||
| ... | @@ -64,9 +65,10 @@ private: | ... | @@ -64,9 +65,10 @@ private: |
| 64 | 65 | ||
| 65 | static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, | 66 | static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, |
| 66 | const R &registers) { | 67 | const R &registers) { |
| 67 | if (prolog.cfaRegister != 0) | 68 | if (prolog.cfaRegister != 0) { |
| 68 | return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + | 69 | uintptr_t cfaRegister = registers.getRegister((int)prolog.cfaRegister); |
| 69 | prolog.cfaRegisterOffset); | 70 | return (pint_t)(cfaRegister + prolog.cfaRegisterOffset); |
| 71 | } | ||
| 70 | if (prolog.cfaExpression != 0) | 72 | if (prolog.cfaExpression != 0) |
| 71 | return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, | 73 | return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, |
| 72 | registers, 0); | 74 | registers, 0); |
| ... | @@ -207,16 +209,16 @@ bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace, | ... | @@ -207,16 +209,16 @@ bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace, |
| 207 | #endif | 209 | #endif |
| 208 | 210 | ||
| 209 | template <typename A, typename R> | 211 | template <typename A, typename R> |
| 210 | int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, | 212 | int DwarfInstructions<A, R>::stepWithDwarf( |
| 211 | pint_t fdeStart, R &registers, | 213 | A &addressSpace, typename R::link_hardened_reg_arg_t pc, pint_t fdeStart, |
| 212 | bool &isSignalFrame, bool stage2) { | 214 | R &registers, bool &isSignalFrame, bool stage2) { |
| 213 | FDE_Info fdeInfo; | 215 | FDE_Info fdeInfo; |
| 214 | CIE_Info cieInfo; | 216 | CIE_Info cieInfo; |
| 215 | if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, | 217 | if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, |
| 216 | &cieInfo) == NULL) { | 218 | &cieInfo) == NULL) { |
| 217 | PrologInfo prolog; | 219 | PrologInfo prolog; |
| 218 | if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, | 220 | if (CFI_Parser<A>::template parseFDEInstructions<R>( |
| 219 | R::getArch(), &prolog)) { | 221 | addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { |
| 220 | // get pointer to cfa (architecture specific) | 222 | // get pointer to cfa (architecture specific) |
| 221 | pint_t cfa = getCFA(addressSpace, prolog, registers); | 223 | pint_t cfa = getCFA(addressSpace, prolog, registers); |
| 222 | 224 | ||
| ... | @@ -264,7 +266,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, | ... | @@ -264,7 +266,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 264 | // by a CFI directive later on. | 266 | // by a CFI directive later on. |
| 265 | newRegisters.setSP(cfa); | 267 | newRegisters.setSP(cfa); |
| 266 | 268 | ||
| 267 | pint_t returnAddress = 0; | 269 | typename R::reg_t returnAddress = 0; |
| 268 | constexpr int lastReg = R::lastDwarfRegNum(); | 270 | constexpr int lastReg = R::lastDwarfRegNum(); |
| 269 | static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= | 271 | static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= |
| 270 | lastReg, | 272 | lastReg, |
| ... | @@ -300,7 +302,16 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, | ... | @@ -300,7 +302,16 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 300 | 302 | ||
| 301 | isSignalFrame = cieInfo.isSignalFrame; | 303 | isSignalFrame = cieInfo.isSignalFrame; |
| 302 | 304 | ||
| 303 | #if defined(_LIBUNWIND_TARGET_AARCH64) | 305 | #if defined(_LIBUNWIND_TARGET_AARCH64) && \ |
| 306 | !defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 307 | // There are two ways of return address signing: pac-ret (enabled via | ||
| 308 | // -mbranch-protection=pac-ret) and ptrauth-returns (enabled as part of | ||
| 309 | // Apple's arm64e or experimental pauthtest ABI on Linux). The code | ||
| 310 | // below handles signed RA for pac-ret, while ptrauth-returns uses | ||
| 311 | // different logic. | ||
| 312 | // TODO: unify logic for both cases, see | ||
| 313 | // https://github.com/llvm/llvm-project/issues/160110 | ||
| 314 | // | ||
| 304 | // If the target is aarch64 then the return address may have been signed | 315 | // If the target is aarch64 then the return address may have been signed |
| 305 | // using the v8.3 pointer authentication extensions. The original | 316 | // using the v8.3 pointer authentication extensions. The original |
| 306 | // return address needs to be authenticated before the return address is | 317 | // return address needs to be authenticated before the return address is |
lib/libunwind/src/DwarfParser.hpp+60-22| ... | @@ -23,6 +23,10 @@ | ... | @@ -23,6 +23,10 @@ |
| 23 | 23 | ||
| 24 | #include "config.h" | 24 | #include "config.h" |
| 25 | 25 | ||
| 26 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 27 | #include <ptrauth.h> | ||
| 28 | #endif | ||
| 29 | |||
| 26 | namespace libunwind { | 30 | namespace libunwind { |
| 27 | 31 | ||
| 28 | /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. | 32 | /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records. |
| ... | @@ -33,6 +37,7 @@ template <typename A> | ... | @@ -33,6 +37,7 @@ template <typename A> |
| 33 | class CFI_Parser { | 37 | class CFI_Parser { |
| 34 | public: | 38 | public: |
| 35 | typedef typename A::pint_t pint_t; | 39 | typedef typename A::pint_t pint_t; |
| 40 | typedef pint_t __ptrauth_unwind_cie_info_personality personality_t; | ||
| 36 | 41 | ||
| 37 | /// Information encoded in a CIE (Common Information Entry) | 42 | /// Information encoded in a CIE (Common Information Entry) |
| 38 | struct CIE_Info { | 43 | struct CIE_Info { |
| ... | @@ -43,7 +48,7 @@ public: | ... | @@ -43,7 +48,7 @@ public: |
| 43 | uint8_t lsdaEncoding; | 48 | uint8_t lsdaEncoding; |
| 44 | uint8_t personalityEncoding; | 49 | uint8_t personalityEncoding; |
| 45 | uint8_t personalityOffsetInCIE; | 50 | uint8_t personalityOffsetInCIE; |
| 46 | pint_t personality; | 51 | personality_t personality; |
| 47 | uint32_t codeAlignFactor; | 52 | uint32_t codeAlignFactor; |
| 48 | int dataAlignFactor; | 53 | int dataAlignFactor; |
| 49 | bool isSignalFrame; | 54 | bool isSignalFrame; |
| ... | @@ -155,14 +160,17 @@ public: | ... | @@ -155,14 +160,17 @@ public: |
| 155 | } | 160 | } |
| 156 | }; | 161 | }; |
| 157 | 162 | ||
| 158 | static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, | 163 | template <typename R> |
| 159 | size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, | 164 | static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc, |
| 160 | CIE_Info *cieInfo); | 165 | pint_t ehSectionStart, size_t sectionLength, |
| 166 | pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo); | ||
| 161 | static const char *decodeFDE(A &addressSpace, pint_t fdeStart, | 167 | static const char *decodeFDE(A &addressSpace, pint_t fdeStart, |
| 162 | FDE_Info *fdeInfo, CIE_Info *cieInfo, | 168 | FDE_Info *fdeInfo, CIE_Info *cieInfo, |
| 163 | bool useCIEInfo = false); | 169 | bool useCIEInfo = false); |
| 170 | template <typename R> | ||
| 164 | static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, | 171 | static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, |
| 165 | const CIE_Info &cieInfo, pint_t upToPC, | 172 | const CIE_Info &cieInfo, |
| 173 | typename R::link_hardened_reg_arg_t upToPC, | ||
| 166 | int arch, PrologInfo *results); | 174 | int arch, PrologInfo *results); |
| 167 | 175 | ||
| 168 | static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); | 176 | static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); |
| ... | @@ -234,9 +242,12 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, | ... | @@ -234,9 +242,12 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, |
| 234 | 242 | ||
| 235 | /// Scan an eh_frame section to find an FDE for a pc | 243 | /// Scan an eh_frame section to find an FDE for a pc |
| 236 | template <typename A> | 244 | template <typename A> |
| 237 | bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, | 245 | template <typename R> |
| 238 | size_t sectionLength, pint_t fdeHint, | 246 | bool CFI_Parser<A>::findFDE(A &addressSpace, |
| 239 | FDE_Info *fdeInfo, CIE_Info *cieInfo) { | 247 | typename R::link_hardened_reg_arg_t pc, |
| 248 | pint_t ehSectionStart, size_t sectionLength, | ||
| 249 | pint_t fdeHint, FDE_Info *fdeInfo, | ||
| 250 | CIE_Info *cieInfo) { | ||
| 240 | //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); | 251 | //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); |
| 241 | pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; | 252 | pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; |
| 242 | const pint_t ehSectionEnd = (sectionLength == SIZE_MAX) | 253 | const pint_t ehSectionEnd = (sectionLength == SIZE_MAX) |
| ... | @@ -273,7 +284,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, | ... | @@ -273,7 +284,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, |
| 273 | pint_t pcRange = addressSpace.getEncodedP( | 284 | pint_t pcRange = addressSpace.getEncodedP( |
| 274 | p, nextCFI, cieInfo->pointerEncoding & 0x0F); | 285 | p, nextCFI, cieInfo->pointerEncoding & 0x0F); |
| 275 | // Test if pc is within the function this FDE covers. | 286 | // Test if pc is within the function this FDE covers. |
| 276 | if ((pcStart < pc) && (pc <= pcStart + pcRange)) { | 287 | if ((pcStart <= pc) && (pc < pcStart + pcRange)) { |
| 277 | // parse rest of info | 288 | // parse rest of info |
| 278 | fdeInfo->lsda = 0; | 289 | fdeInfo->lsda = 0; |
| 279 | // check for augmentation length | 290 | // check for augmentation length |
| ... | @@ -369,6 +380,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, | ... | @@ -369,6 +380,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 369 | cieInfo->returnAddressRegister = (uint8_t)raReg; | 380 | cieInfo->returnAddressRegister = (uint8_t)raReg; |
| 370 | // parse augmentation data based on augmentation string | 381 | // parse augmentation data based on augmentation string |
| 371 | const char *result = NULL; | 382 | const char *result = NULL; |
| 383 | pint_t resultAddr = 0; | ||
| 372 | if (addressSpace.get8(strStart) == 'z') { | 384 | if (addressSpace.get8(strStart) == 'z') { |
| 373 | // parse augmentation data length | 385 | // parse augmentation data length |
| 374 | addressSpace.getULEB128(p, cieContentEnd); | 386 | addressSpace.getULEB128(p, cieContentEnd); |
| ... | @@ -377,13 +389,41 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, | ... | @@ -377,13 +389,41 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 377 | case 'z': | 389 | case 'z': |
| 378 | cieInfo->fdesHaveAugmentationData = true; | 390 | cieInfo->fdesHaveAugmentationData = true; |
| 379 | break; | 391 | break; |
| 380 | case 'P': | 392 | case 'P': { |
| 381 | cieInfo->personalityEncoding = addressSpace.get8(p); | 393 | cieInfo->personalityEncoding = addressSpace.get8(p); |
| 382 | ++p; | 394 | ++p; |
| 383 | cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie); | 395 | cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie); |
| 384 | cieInfo->personality = addressSpace | 396 | pint_t personality = addressSpace.getEncodedP( |
| 385 | .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding); | 397 | p, cieContentEnd, cieInfo->personalityEncoding, |
| 398 | /*datarelBase=*/0, &resultAddr); | ||
| 399 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 400 | if (personality) { | ||
| 401 | // The GOT for the personality function was signed address | ||
| 402 | // authenticated. Manually re-sign with the CIE_Info::personality | ||
| 403 | // schema. If we could guarantee the encoding of the personality we | ||
| 404 | // could avoid this by simply giving resultAddr the correct ptrauth | ||
| 405 | // schema and performing an assignment. | ||
| 406 | #if defined(__arm64e__) | ||
| 407 | const auto oldDiscriminator = resultAddr; | ||
| 408 | #else | ||
| 409 | const auto oldDiscriminator = ptrauth_blend_discriminator( | ||
| 410 | (void *)resultAddr, __ptrauth_unwind_pauthtest_personality_disc); | ||
| 411 | #endif | ||
| 412 | const auto discriminator = ptrauth_blend_discriminator( | ||
| 413 | &cieInfo->personality, | ||
| 414 | __ptrauth_unwind_cie_info_personality_disc); | ||
| 415 | void *signedPtr = ptrauth_auth_and_resign( | ||
| 416 | (void *)personality, ptrauth_key_function_pointer, | ||
| 417 | oldDiscriminator, ptrauth_key_function_pointer, discriminator); | ||
| 418 | personality = (pint_t)signedPtr; | ||
| 419 | } | ||
| 420 | #endif | ||
| 421 | // We use memmove to set the CIE personality as we have already | ||
| 422 | // re-signed the pointer to the correct schema. | ||
| 423 | memmove((void *)&cieInfo->personality, (void *)&personality, | ||
| 424 | sizeof(personality)); | ||
| 386 | break; | 425 | break; |
| 426 | } | ||
| 387 | case 'L': | 427 | case 'L': |
| 388 | cieInfo->lsdaEncoding = addressSpace.get8(p); | 428 | cieInfo->lsdaEncoding = addressSpace.get8(p); |
| 389 | ++p; | 429 | ++p; |
| ... | @@ -417,10 +457,10 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, | ... | @@ -417,10 +457,10 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 417 | 457 | ||
| 418 | /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE | 458 | /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE |
| 419 | template <typename A> | 459 | template <typename A> |
| 420 | bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, | 460 | template <typename R> |
| 421 | const FDE_Info &fdeInfo, | 461 | bool CFI_Parser<A>::parseFDEInstructions( |
| 422 | const CIE_Info &cieInfo, pint_t upToPC, | 462 | A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo, |
| 423 | int arch, PrologInfo *results) { | 463 | typename R::link_hardened_reg_arg_t upToPC, int arch, PrologInfo *results) { |
| 424 | // Alloca is used for the allocation of the rememberStack entries. It removes | 464 | // Alloca is used for the allocation of the rememberStack entries. It removes |
| 425 | // the dependency on new/malloc but the below for loop can not be refactored | 465 | // the dependency on new/malloc but the below for loop can not be refactored |
| 426 | // into functions. Entry could be saved during the processing of a CIE and | 466 | // into functions. Entry could be saved during the processing of a CIE and |
| ... | @@ -808,12 +848,10 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, | ... | @@ -808,12 +848,10 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 808 | results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3; | 848 | results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3; |
| 809 | results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, | 849 | results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, |
| 810 | initialState); | 850 | initialState); |
| 811 | // When calculating the value of the PC, it is assumed that the CFI | 851 | // When using Feat_PAuthLR, the PC value needs to be captured so that |
| 812 | // instruction is placed before the signing instruction, however it is | 852 | // during unwinding, the correct PC value is used for re-authentication. |
| 813 | // placed after. Because of this, we need to take into account the CFI | 853 | // It is assumed that the CFI is placed before the signing instruction. |
| 814 | // instruction is one instruction call later than expected, and reduce | 854 | results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset; |
| 815 | // the PC value by 4 bytes to compensate. | ||
| 816 | results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4; | ||
| 817 | _LIBUNWIND_TRACE_DWARF( | 855 | _LIBUNWIND_TRACE_DWARF( |
| 818 | "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n", | 856 | "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n", |
| 819 | static_cast<uint64_t>(results->ptrAuthDiversifier)); | 857 | static_cast<uint64_t>(results->ptrAuthDiversifier)); |
lib/libunwind/src/EHHeaderParser.hpp+7-4| ... | @@ -37,8 +37,9 @@ public: | ... | @@ -37,8 +37,9 @@ public: |
| 37 | 37 | ||
| 38 | static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, | 38 | static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, |
| 39 | EHHeaderInfo &ehHdrInfo); | 39 | EHHeaderInfo &ehHdrInfo); |
| 40 | static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, | 40 | template <typename R> |
| 41 | uint32_t sectionLength, | 41 | static bool findFDE(A &addressSpace, typename R::link_hardened_reg_arg_t pc, |
| 42 | pint_t ehHdrStart, uint32_t sectionLength, | ||
| 42 | typename CFI_Parser<A>::FDE_Info *fdeInfo, | 43 | typename CFI_Parser<A>::FDE_Info *fdeInfo, |
| 43 | typename CFI_Parser<A>::CIE_Info *cieInfo); | 44 | typename CFI_Parser<A>::CIE_Info *cieInfo); |
| 44 | 45 | ||
| ... | @@ -112,8 +113,10 @@ bool EHHeaderParser<A>::decodeTableEntry( | ... | @@ -112,8 +113,10 @@ bool EHHeaderParser<A>::decodeTableEntry( |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | template <typename A> | 115 | template <typename A> |
| 115 | bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, | 116 | template <typename R> |
| 116 | uint32_t sectionLength, | 117 | bool EHHeaderParser<A>::findFDE(A &addressSpace, |
| 118 | typename R::link_hardened_reg_arg_t pc, | ||
| 119 | pint_t ehHdrStart, uint32_t sectionLength, | ||
| 117 | typename CFI_Parser<A>::FDE_Info *fdeInfo, | 120 | typename CFI_Parser<A>::FDE_Info *fdeInfo, |
| 118 | typename CFI_Parser<A>::CIE_Info *cieInfo) { | 121 | typename CFI_Parser<A>::CIE_Info *cieInfo) { |
| 119 | pint_t ehHdrEnd = ehHdrStart + sectionLength; | 122 | pint_t ehHdrEnd = ehHdrStart + sectionLength; |
lib/libunwind/src/Registers.hpp+226-22| ... | @@ -17,8 +17,13 @@ | ... | @@ -17,8 +17,13 @@ |
| 17 | 17 | ||
| 18 | #include "config.h" | 18 | #include "config.h" |
| 19 | #include "libunwind.h" | 19 | #include "libunwind.h" |
| 20 | #include "libunwind_ext.h" | ||
| 20 | #include "shadow_stack_unwind.h" | 21 | #include "shadow_stack_unwind.h" |
| 21 | 22 | ||
| 23 | #if defined(_LIBUNWIND_HAVE_GETAUXVAL) || defined(_LIBUNWIND_HAVE_ELF_AUX_INFO) | ||
| 24 | #include <sys/auxv.h> | ||
| 25 | #endif | ||
| 26 | |||
| 22 | namespace libunwind { | 27 | namespace libunwind { |
| 23 | 28 | ||
| 24 | // For emulating 128-bit registers | 29 | // For emulating 128-bit registers |
| ... | @@ -60,6 +65,10 @@ public: | ... | @@ -60,6 +65,10 @@ public: |
| 60 | Registers_x86(); | 65 | Registers_x86(); |
| 61 | Registers_x86(const void *registers); | 66 | Registers_x86(const void *registers); |
| 62 | 67 | ||
| 68 | typedef uint32_t reg_t; | ||
| 69 | typedef uint32_t link_reg_t; | ||
| 70 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 71 | |||
| 63 | bool validRegister(int num) const; | 72 | bool validRegister(int num) const; |
| 64 | uint32_t getRegister(int num) const; | 73 | uint32_t getRegister(int num) const; |
| 65 | void setRegister(int num, uint32_t value); | 74 | void setRegister(int num, uint32_t value); |
| ... | @@ -278,6 +287,10 @@ public: | ... | @@ -278,6 +287,10 @@ public: |
| 278 | Registers_x86_64(); | 287 | Registers_x86_64(); |
| 279 | Registers_x86_64(const void *registers); | 288 | Registers_x86_64(const void *registers); |
| 280 | 289 | ||
| 290 | typedef uint64_t reg_t; | ||
| 291 | typedef uint64_t link_reg_t; | ||
| 292 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 293 | |||
| 281 | bool validRegister(int num) const; | 294 | bool validRegister(int num) const; |
| 282 | uint64_t getRegister(int num) const; | 295 | uint64_t getRegister(int num) const; |
| 283 | void setRegister(int num, uint64_t value); | 296 | void setRegister(int num, uint64_t value); |
| ... | @@ -597,6 +610,10 @@ public: | ... | @@ -597,6 +610,10 @@ public: |
| 597 | Registers_ppc(); | 610 | Registers_ppc(); |
| 598 | Registers_ppc(const void *registers); | 611 | Registers_ppc(const void *registers); |
| 599 | 612 | ||
| 613 | typedef uint32_t reg_t; | ||
| 614 | typedef uint32_t link_reg_t; | ||
| 615 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 616 | |||
| 600 | bool validRegister(int num) const; | 617 | bool validRegister(int num) const; |
| 601 | uint32_t getRegister(int num) const; | 618 | uint32_t getRegister(int num) const; |
| 602 | void setRegister(int num, uint32_t value); | 619 | void setRegister(int num, uint32_t value); |
| ... | @@ -1169,6 +1186,10 @@ public: | ... | @@ -1169,6 +1186,10 @@ public: |
| 1169 | Registers_ppc64(); | 1186 | Registers_ppc64(); |
| 1170 | Registers_ppc64(const void *registers); | 1187 | Registers_ppc64(const void *registers); |
| 1171 | 1188 | ||
| 1189 | typedef uint64_t reg_t; | ||
| 1190 | typedef uint64_t link_reg_t; | ||
| 1191 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 1192 | |||
| 1172 | bool validRegister(int num) const; | 1193 | bool validRegister(int num) const; |
| 1173 | uint64_t getRegister(int num) const; | 1194 | uint64_t getRegister(int num) const; |
| 1174 | void setRegister(int num, uint64_t value); | 1195 | void setRegister(int num, uint64_t value); |
| ... | @@ -1814,7 +1835,9 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { | ... | @@ -1814,7 +1835,9 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { |
| 1814 | /// Registers_arm64 holds the register state of a thread in a 64-bit arm | 1835 | /// Registers_arm64 holds the register state of a thread in a 64-bit arm |
| 1815 | /// process. | 1836 | /// process. |
| 1816 | class _LIBUNWIND_HIDDEN Registers_arm64; | 1837 | class _LIBUNWIND_HIDDEN Registers_arm64; |
| 1817 | extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); | 1838 | extern "C" int64_t __libunwind_Registers_arm64_za_disable(); |
| 1839 | extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, | ||
| 1840 | unsigned walkedFrames); | ||
| 1818 | 1841 | ||
| 1819 | #if defined(_LIBUNWIND_USE_GCS) | 1842 | #if defined(_LIBUNWIND_USE_GCS) |
| 1820 | extern "C" void *__libunwind_shstk_get_jump_target() { | 1843 | extern "C" void *__libunwind_shstk_get_jump_target() { |
| ... | @@ -1824,8 +1847,21 @@ extern "C" void *__libunwind_shstk_get_jump_target() { | ... | @@ -1824,8 +1847,21 @@ extern "C" void *__libunwind_shstk_get_jump_target() { |
| 1824 | 1847 | ||
| 1825 | class _LIBUNWIND_HIDDEN Registers_arm64 { | 1848 | class _LIBUNWIND_HIDDEN Registers_arm64 { |
| 1826 | public: | 1849 | public: |
| 1827 | Registers_arm64(); | 1850 | Registers_arm64() = default; |
| 1828 | Registers_arm64(const void *registers); | 1851 | Registers_arm64(const void *registers); |
| 1852 | Registers_arm64(const Registers_arm64 &); | ||
| 1853 | Registers_arm64 &operator=(const Registers_arm64 &); | ||
| 1854 | |||
| 1855 | typedef uint64_t reg_t; | ||
| 1856 | typedef uint64_t __ptrauth_unwind_registers_arm64_link_reg link_reg_t; | ||
| 1857 | |||
| 1858 | // Use `link_hardened_reg_arg_t` to pass values of `link_reg_t` type as | ||
| 1859 | // function arguments. We need to use a const l-value reference to keep | ||
| 1860 | // signature of `__ptrauth`-qualified values of `link_reg_t` type on AArch64 | ||
| 1861 | // PAuth-enabled ABI intact. Passing the raw pointer by value would cause | ||
| 1862 | // authentication on the caller side and make the pointer prone to | ||
| 1863 | // substitution if spilled to the stack in the callee. | ||
| 1864 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 1829 | 1865 | ||
| 1830 | bool validRegister(int num) const; | 1866 | bool validRegister(int num) const; |
| 1831 | uint64_t getRegister(int num) const; | 1867 | uint64_t getRegister(int num) const; |
| ... | @@ -1837,7 +1873,14 @@ public: | ... | @@ -1837,7 +1873,14 @@ public: |
| 1837 | v128 getVectorRegister(int num) const; | 1873 | v128 getVectorRegister(int num) const; |
| 1838 | void setVectorRegister(int num, v128 value); | 1874 | void setVectorRegister(int num, v128 value); |
| 1839 | static const char *getRegisterName(int num); | 1875 | static const char *getRegisterName(int num); |
| 1840 | void jumpto() { __libunwind_Registers_arm64_jumpto(this); } | 1876 | void jumpto(unsigned walkedFrames = 0) { |
| 1877 | zaDisable(); | ||
| 1878 | __libunwind_Registers_arm64_jumpto(this, walkedFrames); | ||
| 1879 | } | ||
| 1880 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 1881 | _LIBUNWIND_TRACE_NO_INLINE | ||
| 1882 | void returnto(unsigned walkedFrames) { jumpto(walkedFrames); } | ||
| 1883 | #endif | ||
| 1841 | static constexpr int lastDwarfRegNum() { | 1884 | static constexpr int lastDwarfRegNum() { |
| 1842 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; | 1885 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; |
| 1843 | } | 1886 | } |
| ... | @@ -1845,27 +1888,104 @@ public: | ... | @@ -1845,27 +1888,104 @@ public: |
| 1845 | 1888 | ||
| 1846 | uint64_t getSP() const { return _registers.__sp; } | 1889 | uint64_t getSP() const { return _registers.__sp; } |
| 1847 | void setSP(uint64_t value) { _registers.__sp = value; } | 1890 | void setSP(uint64_t value) { _registers.__sp = value; } |
| 1848 | uint64_t getIP() const { return _registers.__pc; } | 1891 | uint64_t getIP() const { |
| 1849 | void setIP(uint64_t value) { _registers.__pc = value; } | 1892 | uint64_t value = _registers.__pc; |
| 1850 | uint64_t getFP() const { return _registers.__fp; } | 1893 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) |
| 1851 | void setFP(uint64_t value) { _registers.__fp = value; } | 1894 | // Note the value of the PC was signed to its address in the register state |
| 1895 | // but everyone else expects it to be sign by the SP, so convert on return. | ||
| 1896 | value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc, | ||
| 1897 | ptrauth_key_return_address, | ||
| 1898 | &_registers.__pc, | ||
| 1899 | ptrauth_key_return_address, | ||
| 1900 | getSP()); | ||
| 1901 | #endif | ||
| 1902 | return value; | ||
| 1903 | } | ||
| 1904 | void setIP(uint64_t value) { | ||
| 1905 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 1906 | // Note the value which was set should have been signed with the SP. | ||
| 1907 | // We then resign with the slot we are being stored in to so that both SP | ||
| 1908 | // and LR can't be spoofed at the same time. | ||
| 1909 | value = (uint64_t)ptrauth_auth_and_resign((void *)value, | ||
| 1910 | ptrauth_key_return_address, | ||
| 1911 | getSP(), | ||
| 1912 | ptrauth_key_return_address, | ||
| 1913 | &_registers.__pc); | ||
| 1914 | #endif | ||
| 1915 | _registers.__pc = value; | ||
| 1916 | } | ||
| 1917 | uint64_t getFP() const { return _registers.__fp; } | ||
| 1918 | void setFP(uint64_t value) { _registers.__fp = value; } | ||
| 1919 | |||
| 1920 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 1921 | void | ||
| 1922 | loadAndAuthenticateLinkRegister(reg_t inplaceAuthedLinkRegister, | ||
| 1923 | link_reg_t *referenceAuthedLinkRegister) { | ||
| 1924 | // If we are in an arm64/arm64e frame, then the PC should have been signed | ||
| 1925 | // with the SP | ||
| 1926 | *referenceAuthedLinkRegister = | ||
| 1927 | (uint64_t)ptrauth_auth_data((void *)inplaceAuthedLinkRegister, | ||
| 1928 | ptrauth_key_return_address, | ||
| 1929 | _registers.__sp); | ||
| 1930 | } | ||
| 1931 | #endif | ||
| 1852 | 1932 | ||
| 1853 | private: | 1933 | private: |
| 1934 | uint64_t lazyGetVG() const; | ||
| 1935 | |||
| 1936 | void zaDisable() const { | ||
| 1937 | if (!_misc_registers.__has_sme) | ||
| 1938 | return; | ||
| 1939 | if (__libunwind_Registers_arm64_za_disable() != 0) | ||
| 1940 | _LIBUNWIND_ABORT("SME ZA disable failed"); | ||
| 1941 | } | ||
| 1942 | |||
| 1943 | #if defined(_LIBUNWIND_HAVE_GETAUXVAL) | ||
| 1944 | static bool checkHasSME() { | ||
| 1945 | constexpr int hwcap2_sme = (1 << 23); | ||
| 1946 | unsigned long hwcap2 = getauxval(AT_HWCAP2); | ||
| 1947 | return (hwcap2 & hwcap2_sme) != 0; | ||
| 1948 | } | ||
| 1949 | #elif defined(_LIBUNWIND_HAVE_ELF_AUX_INFO) | ||
| 1950 | static bool checkHasSME() { | ||
| 1951 | constexpr int hwcap2_sme = (1 << 23); | ||
| 1952 | unsigned long hwcap2 = 0; | ||
| 1953 | elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2)); | ||
| 1954 | return (hwcap2 & hwcap2_sme) != 0; | ||
| 1955 | } | ||
| 1956 | #else | ||
| 1957 | static bool checkHasSME() { | ||
| 1958 | // TODO: Support other platforms. | ||
| 1959 | return false; | ||
| 1960 | } | ||
| 1961 | #endif | ||
| 1962 | |||
| 1854 | struct GPRs { | 1963 | struct GPRs { |
| 1855 | uint64_t __x[29]; // x0-x28 | 1964 | uint64_t __x[29] = {}; // x0-x28 |
| 1856 | uint64_t __fp; // Frame pointer x29 | 1965 | uint64_t __fp = 0; // Frame pointer x29 |
| 1857 | uint64_t __lr; // Link register x30 | 1966 | uint64_t __lr = 0; // Link register x30 |
| 1858 | uint64_t __sp; // Stack pointer x31 | 1967 | uint64_t __sp = 0; // Stack pointer x31 |
| 1859 | uint64_t __pc; // Program counter | 1968 | uint64_t __pc = 0; // Program counter |
| 1860 | uint64_t __ra_sign_state; // RA sign state register | 1969 | uint64_t __ra_sign_state = 0; // RA sign state register |
| 1970 | }; | ||
| 1971 | |||
| 1972 | struct Misc { | ||
| 1973 | mutable uint32_t __vg = 0; // Vector Granule | ||
| 1974 | bool __has_sme = checkHasSME(); | ||
| 1861 | }; | 1975 | }; |
| 1862 | 1976 | ||
| 1863 | GPRs _registers; | 1977 | GPRs _registers = {}; |
| 1864 | double _vectorHalfRegisters[32]; | ||
| 1865 | // Currently only the lower double in 128-bit vectore registers | 1978 | // Currently only the lower double in 128-bit vectore registers |
| 1866 | // is perserved during unwinding. We could define new register | 1979 | // is perserved during unwinding. We could define new register |
| 1867 | // numbers (> 96) which mean whole vector registers, then this | 1980 | // numbers (> 96) which mean whole vector registers, then this |
| 1868 | // struct would need to change to contain whole vector registers. | 1981 | // struct would need to change to contain whole vector registers. |
| 1982 | double _vectorHalfRegisters[32] = {}; | ||
| 1983 | |||
| 1984 | // Miscellaneous/virtual registers. These are stored below the GPRs and FPRs | ||
| 1985 | // as they do not correspond to physical registers, so do not need to be | ||
| 1986 | // saved/restored in UnwindRegistersRestore.S and UnwindRegistersSave.S, and | ||
| 1987 | // we don't want to modify the existing offsets for GPRs and FPRs. | ||
| 1988 | Misc _misc_registers; | ||
| 1869 | }; | 1989 | }; |
| 1870 | 1990 | ||
| 1871 | inline Registers_arm64::Registers_arm64(const void *registers) { | 1991 | inline Registers_arm64::Registers_arm64(const void *registers) { |
| ... | @@ -1877,11 +1997,31 @@ inline Registers_arm64::Registers_arm64(const void *registers) { | ... | @@ -1877,11 +1997,31 @@ inline Registers_arm64::Registers_arm64(const void *registers) { |
| 1877 | memcpy(_vectorHalfRegisters, | 1997 | memcpy(_vectorHalfRegisters, |
| 1878 | static_cast<const uint8_t *>(registers) + sizeof(GPRs), | 1998 | static_cast<const uint8_t *>(registers) + sizeof(GPRs), |
| 1879 | sizeof(_vectorHalfRegisters)); | 1999 | sizeof(_vectorHalfRegisters)); |
| 2000 | _misc_registers.__vg = 0; | ||
| 2001 | |||
| 2002 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 2003 | // We have to do some pointer authentication fixups after this copy, | ||
| 2004 | // and as part of that we need to load the source pc without | ||
| 2005 | // authenticating so that we maintain the signature for the resigning | ||
| 2006 | // performed by setIP. | ||
| 2007 | uint64_t pcRegister = 0; | ||
| 2008 | memmove(&pcRegister, ((uint8_t *)&_registers) + offsetof(GPRs, __pc), | ||
| 2009 | sizeof(pcRegister)); | ||
| 2010 | setIP(pcRegister); | ||
| 2011 | #endif | ||
| 1880 | } | 2012 | } |
| 1881 | 2013 | ||
| 1882 | inline Registers_arm64::Registers_arm64() { | 2014 | inline Registers_arm64::Registers_arm64(const Registers_arm64 &other) { |
| 1883 | memset(&_registers, 0, sizeof(_registers)); | 2015 | *this = other; |
| 1884 | memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); | 2016 | } |
| 2017 | |||
| 2018 | inline Registers_arm64 & | ||
| 2019 | Registers_arm64::operator=(const Registers_arm64 &other) { | ||
| 2020 | memmove(static_cast<void *>(this), &other, sizeof(*this)); | ||
| 2021 | // We perform this step to ensure that we correctly authenticate and re-sign | ||
| 2022 | // the pc after the bitwise copy. | ||
| 2023 | setIP(other.getIP()); | ||
| 2024 | return *this; | ||
| 1885 | } | 2025 | } |
| 1886 | 2026 | ||
| 1887 | inline bool Registers_arm64::validRegister(int regNum) const { | 2027 | inline bool Registers_arm64::validRegister(int regNum) const { |
| ... | @@ -1895,22 +2035,40 @@ inline bool Registers_arm64::validRegister(int regNum) const { | ... | @@ -1895,22 +2035,40 @@ inline bool Registers_arm64::validRegister(int regNum) const { |
| 1895 | return false; | 2035 | return false; |
| 1896 | if (regNum == UNW_AARCH64_RA_SIGN_STATE) | 2036 | if (regNum == UNW_AARCH64_RA_SIGN_STATE) |
| 1897 | return true; | 2037 | return true; |
| 2038 | if (regNum == UNW_AARCH64_VG) | ||
| 2039 | return true; | ||
| 1898 | if ((regNum > 32) && (regNum < 64)) | 2040 | if ((regNum > 32) && (regNum < 64)) |
| 1899 | return false; | 2041 | return false; |
| 1900 | return true; | 2042 | return true; |
| 1901 | } | 2043 | } |
| 1902 | 2044 | ||
| 2045 | inline uint64_t Registers_arm64::lazyGetVG() const { | ||
| 2046 | if (!_misc_registers.__vg) { | ||
| 2047 | #if defined(__aarch64__) | ||
| 2048 | register uint64_t vg asm("x0"); | ||
| 2049 | asm(".inst 0x04e0e3e0" // CNTD x0 | ||
| 2050 | : "=r"(vg)); | ||
| 2051 | _misc_registers.__vg = vg; | ||
| 2052 | #else | ||
| 2053 | _LIBUNWIND_ABORT("arm64 VG undefined"); | ||
| 2054 | #endif | ||
| 2055 | } | ||
| 2056 | return _misc_registers.__vg; | ||
| 2057 | } | ||
| 2058 | |||
| 1903 | inline uint64_t Registers_arm64::getRegister(int regNum) const { | 2059 | inline uint64_t Registers_arm64::getRegister(int regNum) const { |
| 1904 | if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) | 2060 | if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) |
| 1905 | return _registers.__pc; | 2061 | return getIP(); |
| 1906 | if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) | 2062 | if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) |
| 1907 | return _registers.__sp; | 2063 | return _registers.__sp; |
| 1908 | if (regNum == UNW_AARCH64_RA_SIGN_STATE) | 2064 | if (regNum == UNW_AARCH64_RA_SIGN_STATE) |
| 1909 | return _registers.__ra_sign_state; | 2065 | return _registers.__ra_sign_state; |
| 1910 | if (regNum == UNW_AARCH64_FP) | 2066 | if (regNum == UNW_AARCH64_FP) |
| 1911 | return _registers.__fp; | 2067 | return getFP(); |
| 1912 | if (regNum == UNW_AARCH64_LR) | 2068 | if (regNum == UNW_AARCH64_LR) |
| 1913 | return _registers.__lr; | 2069 | return _registers.__lr; |
| 2070 | if (regNum == UNW_AARCH64_VG) | ||
| 2071 | return lazyGetVG(); | ||
| 1914 | if ((regNum >= 0) && (regNum < 29)) | 2072 | if ((regNum >= 0) && (regNum < 29)) |
| 1915 | return _registers.__x[regNum]; | 2073 | return _registers.__x[regNum]; |
| 1916 | _LIBUNWIND_ABORT("unsupported arm64 register"); | 2074 | _LIBUNWIND_ABORT("unsupported arm64 register"); |
| ... | @@ -1918,15 +2076,17 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const { | ... | @@ -1918,15 +2076,17 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const { |
| 1918 | 2076 | ||
| 1919 | inline void Registers_arm64::setRegister(int regNum, uint64_t value) { | 2077 | inline void Registers_arm64::setRegister(int regNum, uint64_t value) { |
| 1920 | if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) | 2078 | if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) |
| 1921 | _registers.__pc = value; | 2079 | setIP(value); |
| 1922 | else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) | 2080 | else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) |
| 1923 | _registers.__sp = value; | 2081 | _registers.__sp = value; |
| 1924 | else if (regNum == UNW_AARCH64_RA_SIGN_STATE) | 2082 | else if (regNum == UNW_AARCH64_RA_SIGN_STATE) |
| 1925 | _registers.__ra_sign_state = value; | 2083 | _registers.__ra_sign_state = value; |
| 1926 | else if (regNum == UNW_AARCH64_FP) | 2084 | else if (regNum == UNW_AARCH64_FP) |
| 1927 | _registers.__fp = value; | 2085 | setFP(value); |
| 1928 | else if (regNum == UNW_AARCH64_LR) | 2086 | else if (regNum == UNW_AARCH64_LR) |
| 1929 | _registers.__lr = value; | 2087 | _registers.__lr = value; |
| 2088 | else if (regNum == UNW_AARCH64_VG) | ||
| 2089 | _misc_registers.__vg = value; | ||
| 1930 | else if ((regNum >= 0) && (regNum < 29)) | 2090 | else if ((regNum >= 0) && (regNum < 29)) |
| 1931 | _registers.__x[regNum] = value; | 2091 | _registers.__x[regNum] = value; |
| 1932 | else | 2092 | else |
| ... | @@ -2116,6 +2276,10 @@ public: | ... | @@ -2116,6 +2276,10 @@ public: |
| 2116 | Registers_arm(); | 2276 | Registers_arm(); |
| 2117 | Registers_arm(const void *registers); | 2277 | Registers_arm(const void *registers); |
| 2118 | 2278 | ||
| 2279 | typedef uint32_t reg_t; | ||
| 2280 | typedef uint32_t link_reg_t; | ||
| 2281 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 2282 | |||
| 2119 | bool validRegister(int num) const; | 2283 | bool validRegister(int num) const; |
| 2120 | uint32_t getRegister(int num) const; | 2284 | uint32_t getRegister(int num) const; |
| 2121 | void setRegister(int num, uint32_t value); | 2285 | void setRegister(int num, uint32_t value); |
| ... | @@ -2621,6 +2785,10 @@ public: | ... | @@ -2621,6 +2785,10 @@ public: |
| 2621 | Registers_or1k(); | 2785 | Registers_or1k(); |
| 2622 | Registers_or1k(const void *registers); | 2786 | Registers_or1k(const void *registers); |
| 2623 | 2787 | ||
| 2788 | typedef uint32_t reg_t; | ||
| 2789 | typedef uint32_t link_reg_t; | ||
| 2790 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 2791 | |||
| 2624 | bool validRegister(int num) const; | 2792 | bool validRegister(int num) const; |
| 2625 | uint32_t getRegister(int num) const; | 2793 | uint32_t getRegister(int num) const; |
| 2626 | void setRegister(int num, uint32_t value); | 2794 | void setRegister(int num, uint32_t value); |
| ... | @@ -2820,6 +2988,10 @@ public: | ... | @@ -2820,6 +2988,10 @@ public: |
| 2820 | Registers_mips_o32(); | 2988 | Registers_mips_o32(); |
| 2821 | Registers_mips_o32(const void *registers); | 2989 | Registers_mips_o32(const void *registers); |
| 2822 | 2990 | ||
| 2991 | typedef uint32_t reg_t; | ||
| 2992 | typedef uint32_t link_reg_t; | ||
| 2993 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 2994 | |||
| 2823 | bool validRegister(int num) const; | 2995 | bool validRegister(int num) const; |
| 2824 | uint32_t getRegister(int num) const; | 2996 | uint32_t getRegister(int num) const; |
| 2825 | void setRegister(int num, uint32_t value); | 2997 | void setRegister(int num, uint32_t value); |
| ... | @@ -3155,6 +3327,10 @@ public: | ... | @@ -3155,6 +3327,10 @@ public: |
| 3155 | Registers_mips_newabi(); | 3327 | Registers_mips_newabi(); |
| 3156 | Registers_mips_newabi(const void *registers); | 3328 | Registers_mips_newabi(const void *registers); |
| 3157 | 3329 | ||
| 3330 | typedef uint64_t reg_t; | ||
| 3331 | typedef uint64_t link_reg_t; | ||
| 3332 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 3333 | |||
| 3158 | bool validRegister(int num) const; | 3334 | bool validRegister(int num) const; |
| 3159 | uint64_t getRegister(int num) const; | 3335 | uint64_t getRegister(int num) const; |
| 3160 | void setRegister(int num, uint64_t value); | 3336 | void setRegister(int num, uint64_t value); |
| ... | @@ -3458,6 +3634,10 @@ public: | ... | @@ -3458,6 +3634,10 @@ public: |
| 3458 | Registers_sparc(); | 3634 | Registers_sparc(); |
| 3459 | Registers_sparc(const void *registers); | 3635 | Registers_sparc(const void *registers); |
| 3460 | 3636 | ||
| 3637 | typedef uint32_t reg_t; | ||
| 3638 | typedef uint32_t link_reg_t; | ||
| 3639 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 3640 | |||
| 3461 | bool validRegister(int num) const; | 3641 | bool validRegister(int num) const; |
| 3462 | uint32_t getRegister(int num) const; | 3642 | uint32_t getRegister(int num) const; |
| 3463 | void setRegister(int num, uint32_t value); | 3643 | void setRegister(int num, uint32_t value); |
| ... | @@ -3644,6 +3824,10 @@ public: | ... | @@ -3644,6 +3824,10 @@ public: |
| 3644 | Registers_sparc64() = default; | 3824 | Registers_sparc64() = default; |
| 3645 | Registers_sparc64(const void *registers); | 3825 | Registers_sparc64(const void *registers); |
| 3646 | 3826 | ||
| 3827 | typedef uint64_t reg_t; | ||
| 3828 | typedef uint64_t link_reg_t; | ||
| 3829 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 3830 | |||
| 3647 | bool validRegister(int num) const; | 3831 | bool validRegister(int num) const; |
| 3648 | uint64_t getRegister(int num) const; | 3832 | uint64_t getRegister(int num) const; |
| 3649 | void setRegister(int num, uint64_t value); | 3833 | void setRegister(int num, uint64_t value); |
| ... | @@ -3829,6 +4013,10 @@ public: | ... | @@ -3829,6 +4013,10 @@ public: |
| 3829 | Registers_hexagon(); | 4013 | Registers_hexagon(); |
| 3830 | Registers_hexagon(const void *registers); | 4014 | Registers_hexagon(const void *registers); |
| 3831 | 4015 | ||
| 4016 | typedef uint32_t reg_t; | ||
| 4017 | typedef uint32_t link_reg_t; | ||
| 4018 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 4019 | |||
| 3832 | bool validRegister(int num) const; | 4020 | bool validRegister(int num) const; |
| 3833 | uint32_t getRegister(int num) const; | 4021 | uint32_t getRegister(int num) const; |
| 3834 | void setRegister(int num, uint32_t value); | 4022 | void setRegister(int num, uint32_t value); |
| ... | @@ -4044,6 +4232,10 @@ public: | ... | @@ -4044,6 +4232,10 @@ public: |
| 4044 | Registers_riscv(); | 4232 | Registers_riscv(); |
| 4045 | Registers_riscv(const void *registers); | 4233 | Registers_riscv(const void *registers); |
| 4046 | 4234 | ||
| 4235 | typedef ::libunwind::reg_t reg_t; | ||
| 4236 | typedef ::libunwind::reg_t link_reg_t; | ||
| 4237 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 4238 | |||
| 4047 | bool validRegister(int num) const; | 4239 | bool validRegister(int num) const; |
| 4048 | reg_t getRegister(int num) const; | 4240 | reg_t getRegister(int num) const; |
| 4049 | void setRegister(int num, reg_t value); | 4241 | void setRegister(int num, reg_t value); |
| ... | @@ -4341,6 +4533,10 @@ public: | ... | @@ -4341,6 +4533,10 @@ public: |
| 4341 | Registers_ve(); | 4533 | Registers_ve(); |
| 4342 | Registers_ve(const void *registers); | 4534 | Registers_ve(const void *registers); |
| 4343 | 4535 | ||
| 4536 | typedef uint64_t reg_t; | ||
| 4537 | typedef uint64_t link_reg_t; | ||
| 4538 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 4539 | |||
| 4344 | bool validRegister(int num) const; | 4540 | bool validRegister(int num) const; |
| 4345 | uint64_t getRegister(int num) const; | 4541 | uint64_t getRegister(int num) const; |
| 4346 | void setRegister(int num, uint64_t value); | 4542 | void setRegister(int num, uint64_t value); |
| ... | @@ -4784,6 +4980,10 @@ public: | ... | @@ -4784,6 +4980,10 @@ public: |
| 4784 | Registers_s390x(); | 4980 | Registers_s390x(); |
| 4785 | Registers_s390x(const void *registers); | 4981 | Registers_s390x(const void *registers); |
| 4786 | 4982 | ||
| 4983 | typedef uint64_t reg_t; | ||
| 4984 | typedef uint64_t link_reg_t; | ||
| 4985 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 4986 | |||
| 4787 | bool validRegister(int num) const; | 4987 | bool validRegister(int num) const; |
| 4788 | uint64_t getRegister(int num) const; | 4988 | uint64_t getRegister(int num) const; |
| 4789 | void setRegister(int num, uint64_t value); | 4989 | void setRegister(int num, uint64_t value); |
| ... | @@ -5072,6 +5272,10 @@ public: | ... | @@ -5072,6 +5272,10 @@ public: |
| 5072 | Registers_loongarch(); | 5272 | Registers_loongarch(); |
| 5073 | Registers_loongarch(const void *registers); | 5273 | Registers_loongarch(const void *registers); |
| 5074 | 5274 | ||
| 5275 | typedef uint64_t reg_t; | ||
| 5276 | typedef uint64_t link_reg_t; | ||
| 5277 | typedef const link_reg_t &link_hardened_reg_arg_t; | ||
| 5278 | |||
| 5075 | bool validRegister(int num) const; | 5279 | bool validRegister(int num) const; |
| 5076 | uint64_t getRegister(int num) const; | 5280 | uint64_t getRegister(int num) const; |
| 5077 | void setRegister(int num, uint64_t value); | 5281 | void setRegister(int num, uint64_t value); |
lib/libunwind/src/Unwind-seh.cpp+6-7| ... | @@ -163,7 +163,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, | ... | @@ -163,7 +163,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, |
| 163 | // If we were called by __libunwind_seh_personality(), indicate that | 163 | // If we were called by __libunwind_seh_personality(), indicate that |
| 164 | // a handler was found; otherwise, initiate phase 2 by unwinding. | 164 | // a handler was found; otherwise, initiate phase 2 by unwinding. |
| 165 | if (ours && ms_exc->NumberParameters > 1) | 165 | if (ours && ms_exc->NumberParameters > 1) |
| 166 | return 4 /* ExceptionExecuteHandler in mingw */; | 166 | return static_cast<EXCEPTION_DISPOSITION>(4); |
| 167 | // This should never happen in phase 2. | 167 | // This should never happen in phase 2. |
| 168 | if (IS_UNWINDING(ms_exc->ExceptionFlags)) | 168 | if (IS_UNWINDING(ms_exc->ExceptionFlags)) |
| 169 | _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!"); | 169 | _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!"); |
| ... | @@ -182,7 +182,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, | ... | @@ -182,7 +182,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, |
| 182 | // a handler was found; otherwise, it's time to initiate a collided | 182 | // a handler was found; otherwise, it's time to initiate a collided |
| 183 | // unwind to the target. | 183 | // unwind to the target. |
| 184 | if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) | 184 | if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) |
| 185 | return 4 /* ExceptionExecuteHandler in mingw */; | 185 | return static_cast<EXCEPTION_DISPOSITION>(4); |
| 186 | // This should never happen in phase 1. | 186 | // This should never happen in phase 1. |
| 187 | if (!IS_UNWINDING(ms_exc->ExceptionFlags)) | 187 | if (!IS_UNWINDING(ms_exc->ExceptionFlags)) |
| 188 | _LIBUNWIND_ABORT("Personality installed context during phase 1!"); | 188 | _LIBUNWIND_ABORT("Personality installed context during phase 1!"); |
| ... | @@ -259,13 +259,12 @@ __libunwind_seh_personality(int version, _Unwind_Action state, | ... | @@ -259,13 +259,12 @@ __libunwind_seh_personality(int version, _Unwind_Action state, |
| 259 | (void *)disp_ctx->LanguageHandler, (void *)&ms_exc, | 259 | (void *)disp_ctx->LanguageHandler, (void *)&ms_exc, |
| 260 | (void *)disp_ctx->EstablisherFrame, | 260 | (void *)disp_ctx->EstablisherFrame, |
| 261 | (void *)disp_ctx->ContextRecord, (void *)disp_ctx); | 261 | (void *)disp_ctx->ContextRecord, (void *)disp_ctx); |
| 262 | EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc, | 262 | int ms_act = static_cast<int>( |
| 263 | (PVOID)disp_ctx->EstablisherFrame, | 263 | disp_ctx->LanguageHandler(&ms_exc, (PVOID)disp_ctx->EstablisherFrame, |
| 264 | disp_ctx->ContextRecord, | 264 | disp_ctx->ContextRecord, disp_ctx)); |
| 265 | disp_ctx); | ||
| 266 | _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler " | 265 | _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler " |
| 267 | "returned %d", | 266 | "returned %d", |
| 268 | (int)ms_act); | 267 | ms_act); |
| 269 | switch (ms_act) { | 268 | switch (ms_act) { |
| 270 | case ExceptionContinueExecution: return _URC_END_OF_STACK; | 269 | case ExceptionContinueExecution: return _URC_END_OF_STACK; |
| 271 | case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND; | 270 | case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND; |
lib/libunwind/src/Unwind-wasm.c+7-7| ... | @@ -37,13 +37,13 @@ struct _Unwind_LandingPadContext { | ... | @@ -37,13 +37,13 @@ struct _Unwind_LandingPadContext { |
| 37 | // function | 37 | // function |
| 38 | thread_local struct _Unwind_LandingPadContext __wasm_lpad_context; | 38 | thread_local struct _Unwind_LandingPadContext __wasm_lpad_context; |
| 39 | 39 | ||
| 40 | /// Calls to this function is in landing pads in compiler-generated user code. | 40 | /// Calls to this function are in landing pads in compiler-generated user code. |
| 41 | /// In other EH schemes, stack unwinding is done by libunwind library, which | 41 | /// In other EH schemes, stack unwinding is done by libunwind library, which |
| 42 | /// calls the personality function for each each frame it lands. On the other | 42 | /// calls the personality function for each frame it lands. On the other hand, |
| 43 | /// hand, WebAssembly stack unwinding process is performed by a VM, and the | 43 | /// WebAssembly stack unwinding process is performed by a VM, and the |
| 44 | /// personality function cannot be called from there. So the compiler inserts | 44 | /// personality function cannot be called from there. So the compiler inserts a |
| 45 | /// a call to this function in landing pads in the user code, which in turn | 45 | /// call to this function in landing pads in the user code, which in turn calls |
| 46 | /// calls the personality function. | 46 | /// the personality function. |
| 47 | _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) { | 47 | _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) { |
| 48 | struct _Unwind_Exception *exception_object = | 48 | struct _Unwind_Exception *exception_object = |
| 49 | (struct _Unwind_Exception *)exception_ptr; | 49 | (struct _Unwind_Exception *)exception_ptr; |
| ... | @@ -92,7 +92,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, | ... | @@ -92,7 +92,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, |
| 92 | 92 | ||
| 93 | /// Called by personality handler to get instruction pointer. | 93 | /// Called by personality handler to get instruction pointer. |
| 94 | _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { | 94 | _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { |
| 95 | // The result will be used as an 1-based index after decrementing 1, so we | 95 | // The result will be used as a 1-based index after decrementing 1, so we |
| 96 | // increment 2 here | 96 | // increment 2 here |
| 97 | uintptr_t result = | 97 | uintptr_t result = |
| 98 | ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2; | 98 | ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2; |
lib/libunwind/src/UnwindCursor.hpp+167-49| ... | @@ -41,7 +41,8 @@ | ... | @@ -41,7 +41,8 @@ |
| 41 | #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 | 41 | #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 |
| 42 | #endif | 42 | #endif |
| 43 | 43 | ||
| 44 | #if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) | 44 | #if defined(_LIBUNWIND_TARGET_HAIKU) && \ |
| 45 | (defined(_LIBUNWIND_TARGET_I386) || defined(_LIBUNWIND_TARGET_X86_64)) | ||
| 45 | #include <OS.h> | 46 | #include <OS.h> |
| 46 | #include <signal.h> | 47 | #include <signal.h> |
| 47 | #define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1 | 48 | #define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1 |
| ... | @@ -120,7 +121,9 @@ class _LIBUNWIND_HIDDEN DwarfFDECache { | ... | @@ -120,7 +121,9 @@ class _LIBUNWIND_HIDDEN DwarfFDECache { |
| 120 | typedef typename A::pint_t pint_t; | 121 | typedef typename A::pint_t pint_t; |
| 121 | public: | 122 | public: |
| 122 | static constexpr pint_t kSearchAll = static_cast<pint_t>(-1); | 123 | static constexpr pint_t kSearchAll = static_cast<pint_t>(-1); |
| 123 | static pint_t findFDE(pint_t mh, pint_t pc); | 124 | template <typename R> |
| 125 | static pint_t findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc); | ||
| 126 | |||
| 124 | static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); | 127 | static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); |
| 125 | static void removeAllIn(pint_t mh); | 128 | static void removeAllIn(pint_t mh); |
| 126 | static void iterateCacheEntries(void (*func)(unw_word_t ip_start, | 129 | static void iterateCacheEntries(void (*func)(unw_word_t ip_start, |
| ... | @@ -173,7 +176,9 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false; | ... | @@ -173,7 +176,9 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false; |
| 173 | #endif | 176 | #endif |
| 174 | 177 | ||
| 175 | template <typename A> | 178 | template <typename A> |
| 176 | typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { | 179 | template <typename R> |
| 180 | typename DwarfFDECache<A>::pint_t | ||
| 181 | DwarfFDECache<A>::findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc) { | ||
| 177 | pint_t result = 0; | 182 | pint_t result = 0; |
| 178 | _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); | 183 | _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); |
| 179 | for (entry *p = _buffer; p < _bufferUsed; ++p) { | 184 | for (entry *p = _buffer; p < _bufferUsed; ++p) { |
| ... | @@ -471,7 +476,9 @@ public: | ... | @@ -471,7 +476,9 @@ public: |
| 471 | virtual void getInfo(unw_proc_info_t *) { | 476 | virtual void getInfo(unw_proc_info_t *) { |
| 472 | _LIBUNWIND_ABORT("getInfo not implemented"); | 477 | _LIBUNWIND_ABORT("getInfo not implemented"); |
| 473 | } | 478 | } |
| 474 | virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } | 479 | _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto() { |
| 480 | _LIBUNWIND_ABORT("jumpto not implemented"); | ||
| 481 | } | ||
| 475 | virtual bool isSignalFrame() { | 482 | virtual bool isSignalFrame() { |
| 476 | _LIBUNWIND_ABORT("isSignalFrame not implemented"); | 483 | _LIBUNWIND_ABORT("isSignalFrame not implemented"); |
| 477 | } | 484 | } |
| ... | @@ -488,6 +495,12 @@ public: | ... | @@ -488,6 +495,12 @@ public: |
| 488 | virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } | 495 | virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } |
| 489 | #endif | 496 | #endif |
| 490 | 497 | ||
| 498 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 499 | virtual void setWalkedFrames(unsigned) { | ||
| 500 | _LIBUNWIND_ABORT("setWalkedFrames not implemented"); | ||
| 501 | } | ||
| 502 | #endif | ||
| 503 | |||
| 491 | #ifdef _AIX | 504 | #ifdef _AIX |
| 492 | virtual uintptr_t getDataRelBase() { | 505 | virtual uintptr_t getDataRelBase() { |
| 493 | _LIBUNWIND_ABORT("getDataRelBase not implemented"); | 506 | _LIBUNWIND_ABORT("getDataRelBase not implemented"); |
| ... | @@ -964,7 +977,8 @@ public: | ... | @@ -964,7 +977,8 @@ public: |
| 964 | virtual void setFloatReg(int, unw_fpreg_t); | 977 | virtual void setFloatReg(int, unw_fpreg_t); |
| 965 | virtual int step(bool stage2 = false); | 978 | virtual int step(bool stage2 = false); |
| 966 | virtual void getInfo(unw_proc_info_t *); | 979 | virtual void getInfo(unw_proc_info_t *); |
| 967 | virtual void jumpto(); | 980 | _LIBUNWIND_TRACE_NO_INLINE |
| 981 | virtual void jumpto(); | ||
| 968 | virtual bool isSignalFrame(); | 982 | virtual bool isSignalFrame(); |
| 969 | virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); | 983 | virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); |
| 970 | virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); | 984 | virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); |
| ... | @@ -973,6 +987,10 @@ public: | ... | @@ -973,6 +987,10 @@ public: |
| 973 | virtual void saveVFPAsX(); | 987 | virtual void saveVFPAsX(); |
| 974 | #endif | 988 | #endif |
| 975 | 989 | ||
| 990 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 991 | virtual void setWalkedFrames(unsigned); | ||
| 992 | #endif | ||
| 993 | |||
| 976 | #ifdef _AIX | 994 | #ifdef _AIX |
| 977 | virtual uintptr_t getDataRelBase(); | 995 | virtual uintptr_t getDataRelBase(); |
| 978 | #endif | 996 | #endif |
| ... | @@ -1045,19 +1063,28 @@ private: | ... | @@ -1045,19 +1063,28 @@ private: |
| 1045 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 1063 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 1046 | bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo, | 1064 | bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo, |
| 1047 | const typename CFI_Parser<A>::CIE_Info &cieInfo, | 1065 | const typename CFI_Parser<A>::CIE_Info &cieInfo, |
| 1048 | pint_t pc, uintptr_t dso_base); | 1066 | typename R::link_hardened_reg_arg_t pc, |
| 1049 | bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects, | 1067 | uintptr_t dso_base); |
| 1050 | uint32_t fdeSectionOffsetHint=0); | 1068 | bool getInfoFromDwarfSection(typename R::link_hardened_reg_arg_t pc, |
| 1069 | const UnwindInfoSections &sects, | ||
| 1070 | uint32_t fdeSectionOffsetHint = 0); | ||
| 1051 | int stepWithDwarfFDE(bool stage2) { | 1071 | int stepWithDwarfFDE(bool stage2) { |
| 1072 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 1073 | typename R::reg_t rawPC = this->getReg(UNW_REG_IP); | ||
| 1074 | typename R::link_reg_t pc; | ||
| 1075 | _registers.loadAndAuthenticateLinkRegister(rawPC, &pc); | ||
| 1076 | #else | ||
| 1077 | typename R::link_reg_t pc = this->getReg(UNW_REG_IP); | ||
| 1078 | #endif | ||
| 1052 | return DwarfInstructions<A, R>::stepWithDwarf( | 1079 | return DwarfInstructions<A, R>::stepWithDwarf( |
| 1053 | _addressSpace, (pint_t)this->getReg(UNW_REG_IP), | 1080 | _addressSpace, pc, (pint_t)_info.unwind_info, _registers, |
| 1054 | (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2); | 1081 | _isSignalFrame, stage2); |
| 1055 | } | 1082 | } |
| 1056 | #endif | 1083 | #endif |
| 1057 | 1084 | ||
| 1058 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) | 1085 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
| 1059 | bool getInfoFromCompactEncodingSection(pint_t pc, | 1086 | bool getInfoFromCompactEncodingSection(typename R::link_hardened_reg_arg_t pc, |
| 1060 | const UnwindInfoSections &sects); | 1087 | const UnwindInfoSections &sects); |
| 1061 | int stepWithCompactEncoding(bool stage2 = false) { | 1088 | int stepWithCompactEncoding(bool stage2 = false) { |
| 1062 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 1089 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 1063 | if ( compactSaysUseDwarf() ) | 1090 | if ( compactSaysUseDwarf() ) |
| ... | @@ -1344,9 +1371,12 @@ private: | ... | @@ -1344,9 +1371,12 @@ private: |
| 1344 | bool _unwindInfoMissing; | 1371 | bool _unwindInfoMissing; |
| 1345 | bool _isSignalFrame; | 1372 | bool _isSignalFrame; |
| 1346 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ | 1373 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ |
| 1347 | defined(_LIBUNWIND_TARGET_HAIKU) | 1374 | defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) |
| 1348 | bool _isSigReturn = false; | 1375 | bool _isSigReturn = false; |
| 1349 | #endif | 1376 | #endif |
| 1377 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 1378 | uint32_t _walkedFrames; | ||
| 1379 | #endif | ||
| 1350 | }; | 1380 | }; |
| 1351 | 1381 | ||
| 1352 | 1382 | ||
| ... | @@ -1358,13 +1388,13 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) | ... | @@ -1358,13 +1388,13 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) |
| 1358 | "UnwindCursor<> does not fit in unw_cursor_t"); | 1388 | "UnwindCursor<> does not fit in unw_cursor_t"); |
| 1359 | static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)), | 1389 | static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)), |
| 1360 | "UnwindCursor<> requires more alignment than unw_cursor_t"); | 1390 | "UnwindCursor<> requires more alignment than unw_cursor_t"); |
| 1361 | memset(&_info, 0, sizeof(_info)); | 1391 | memset(static_cast<void *>(&_info), 0, sizeof(_info)); |
| 1362 | } | 1392 | } |
| 1363 | 1393 | ||
| 1364 | template <typename A, typename R> | 1394 | template <typename A, typename R> |
| 1365 | UnwindCursor<A, R>::UnwindCursor(A &as, void *) | 1395 | UnwindCursor<A, R>::UnwindCursor(A &as, void *) |
| 1366 | : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { | 1396 | : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { |
| 1367 | memset(&_info, 0, sizeof(_info)); | 1397 | memset(static_cast<void *>(&_info), 0, sizeof(_info)); |
| 1368 | // FIXME | 1398 | // FIXME |
| 1369 | // fill in _registers from thread arg | 1399 | // fill in _registers from thread arg |
| 1370 | } | 1400 | } |
| ... | @@ -1401,7 +1431,46 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { | ... | @@ -1401,7 +1431,46 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { |
| 1401 | } | 1431 | } |
| 1402 | 1432 | ||
| 1403 | template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { | 1433 | template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { |
| 1434 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 1435 | /* | ||
| 1436 | |||
| 1437 | The value of `_walkedFrames` is computed in `unwind_phase2` and represents the | ||
| 1438 | number of frames walked starting `unwind_phase2` to get to the landing pad. | ||
| 1439 | |||
| 1440 | ``` | ||
| 1441 | // uc is initialized by __unw_getcontext in the parent frame. | ||
| 1442 | // The first stack frame walked is unwind_phase2. | ||
| 1443 | unsigned framesWalked = 1; | ||
| 1444 | ``` | ||
| 1445 | |||
| 1446 | To that, we need to add the number of function calls in libunwind between | ||
| 1447 | `unwind_phase2` & `__libunwind_Registers_arm64_jumpto` which performs the long | ||
| 1448 | jump, to rebalance the execution flow. | ||
| 1449 | |||
| 1450 | ``` | ||
| 1451 | frame #0: libunwind.1.dylib`__libunwind_Registers_arm64_jumpto at UnwindRegistersRestore.S:646 | ||
| 1452 | frame #1: libunwind.1.dylib`libunwind::Registers_arm64::returnto at Registers.hpp:2291:3 | ||
| 1453 | frame #2: libunwind.1.dylib`libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_arm64>::jumpto at UnwindCursor.hpp:1474:14 | ||
| 1454 | frame #3: libunwind.1.dylib`__unw_resume at libunwind.cpp:375:7 | ||
| 1455 | frame #4: libunwind.1.dylib`__unw_resume_with_frames_walked at libunwind.cpp:363:10 | ||
| 1456 | frame #5: libunwind.1.dylib`unwind_phase2 at UnwindLevel1.c:328:9 | ||
| 1457 | frame #6: libunwind.1.dylib`_Unwind_RaiseException at UnwindLevel1.c:480:10 | ||
| 1458 | frame #7: libc++abi.dylib`__cxa_throw at cxa_exception.cpp:295:5 | ||
| 1459 | ... | ||
| 1460 | ``` | ||
| 1461 | |||
| 1462 | If we look at the backtrace from `__libunwind_Registers_arm64_jumpto`, we see | ||
| 1463 | there are 5 frames on the stack to reach `unwind_phase2`. However, only 4 of | ||
| 1464 | them will never return, since `__libunwind_Registers_arm64_jumpto` returns | ||
| 1465 | back to the landing pad, so we need to subtract 1 to the number of | ||
| 1466 | `_EXTRA_LIBUNWIND_FRAMES_WALKED`. | ||
| 1467 | */ | ||
| 1468 | |||
| 1469 | static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1; | ||
| 1470 | _registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED); | ||
| 1471 | #else | ||
| 1404 | _registers.jumpto(); | 1472 | _registers.jumpto(); |
| 1473 | #endif | ||
| 1405 | } | 1474 | } |
| 1406 | 1475 | ||
| 1407 | #ifdef __arm__ | 1476 | #ifdef __arm__ |
| ... | @@ -1410,6 +1479,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() { | ... | @@ -1410,6 +1479,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() { |
| 1410 | } | 1479 | } |
| 1411 | #endif | 1480 | #endif |
| 1412 | 1481 | ||
| 1482 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 1483 | template <typename A, typename R> | ||
| 1484 | void UnwindCursor<A, R>::setWalkedFrames(unsigned walkedFrames) { | ||
| 1485 | _walkedFrames = walkedFrames; | ||
| 1486 | } | ||
| 1487 | #endif | ||
| 1488 | |||
| 1413 | #ifdef _AIX | 1489 | #ifdef _AIX |
| 1414 | template <typename A, typename R> | 1490 | template <typename A, typename R> |
| 1415 | uintptr_t UnwindCursor<A, R>::getDataRelBase() { | 1491 | uintptr_t UnwindCursor<A, R>::getDataRelBase() { |
| ... | @@ -1658,11 +1734,11 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( | ... | @@ -1658,11 +1734,11 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( |
| 1658 | template <typename A, typename R> | 1734 | template <typename A, typename R> |
| 1659 | bool UnwindCursor<A, R>::getInfoFromFdeCie( | 1735 | bool UnwindCursor<A, R>::getInfoFromFdeCie( |
| 1660 | const typename CFI_Parser<A>::FDE_Info &fdeInfo, | 1736 | const typename CFI_Parser<A>::FDE_Info &fdeInfo, |
| 1661 | const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc, | 1737 | const typename CFI_Parser<A>::CIE_Info &cieInfo, |
| 1662 | uintptr_t dso_base) { | 1738 | typename R::link_hardened_reg_arg_t pc, uintptr_t dso_base) { |
| 1663 | typename CFI_Parser<A>::PrologInfo prolog; | 1739 | typename CFI_Parser<A>::PrologInfo prolog; |
| 1664 | if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, | 1740 | if (CFI_Parser<A>::template parseFDEInstructions<R>( |
| 1665 | R::getArch(), &prolog)) { | 1741 | _addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { |
| 1666 | // Save off parsed FDE info | 1742 | // Save off parsed FDE info |
| 1667 | _info.start_ip = fdeInfo.pcStart; | 1743 | _info.start_ip = fdeInfo.pcStart; |
| 1668 | _info.end_ip = fdeInfo.pcEnd; | 1744 | _info.end_ip = fdeInfo.pcEnd; |
| ... | @@ -1682,43 +1758,42 @@ bool UnwindCursor<A, R>::getInfoFromFdeCie( | ... | @@ -1682,43 +1758,42 @@ bool UnwindCursor<A, R>::getInfoFromFdeCie( |
| 1682 | } | 1758 | } |
| 1683 | 1759 | ||
| 1684 | template <typename A, typename R> | 1760 | template <typename A, typename R> |
| 1685 | bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, | 1761 | bool UnwindCursor<A, R>::getInfoFromDwarfSection( |
| 1686 | const UnwindInfoSections &sects, | 1762 | typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects, |
| 1687 | uint32_t fdeSectionOffsetHint) { | 1763 | uint32_t fdeSectionOffsetHint) { |
| 1688 | typename CFI_Parser<A>::FDE_Info fdeInfo; | 1764 | typename CFI_Parser<A>::FDE_Info fdeInfo; |
| 1689 | typename CFI_Parser<A>::CIE_Info cieInfo; | 1765 | typename CFI_Parser<A>::CIE_Info cieInfo; |
| 1690 | bool foundFDE = false; | 1766 | bool foundFDE = false; |
| 1691 | bool foundInCache = false; | 1767 | bool foundInCache = false; |
| 1692 | // If compact encoding table gave offset into dwarf section, go directly there | 1768 | // If compact encoding table gave offset into dwarf section, go directly there |
| 1693 | if (fdeSectionOffsetHint != 0) { | 1769 | if (fdeSectionOffsetHint != 0) { |
| 1694 | foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, | 1770 | foundFDE = CFI_Parser<A>::template findFDE<R>( |
| 1695 | sects.dwarf_section_length, | 1771 | _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, |
| 1696 | sects.dwarf_section + fdeSectionOffsetHint, | 1772 | sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo); |
| 1697 | &fdeInfo, &cieInfo); | ||
| 1698 | } | 1773 | } |
| 1699 | #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | 1774 | #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) |
| 1700 | if (!foundFDE && (sects.dwarf_index_section != 0)) { | 1775 | if (!foundFDE && (sects.dwarf_index_section != 0)) { |
| 1701 | foundFDE = EHHeaderParser<A>::findFDE( | 1776 | foundFDE = EHHeaderParser<A>::template findFDE<R>( |
| 1702 | _addressSpace, pc, sects.dwarf_index_section, | 1777 | _addressSpace, pc, sects.dwarf_index_section, |
| 1703 | (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); | 1778 | (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); |
| 1704 | } | 1779 | } |
| 1705 | #endif | 1780 | #endif |
| 1706 | if (!foundFDE) { | 1781 | if (!foundFDE) { |
| 1707 | // otherwise, search cache of previously found FDEs. | 1782 | // otherwise, search cache of previously found FDEs. |
| 1708 | pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc); | 1783 | pint_t cachedFDE = |
| 1784 | DwarfFDECache<A>::template findFDE<R>(sects.dso_base, pc); | ||
| 1709 | if (cachedFDE != 0) { | 1785 | if (cachedFDE != 0) { |
| 1710 | foundFDE = | 1786 | foundFDE = CFI_Parser<A>::template findFDE<R>( |
| 1711 | CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, | 1787 | _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, |
| 1712 | sects.dwarf_section_length, | 1788 | cachedFDE, &fdeInfo, &cieInfo); |
| 1713 | cachedFDE, &fdeInfo, &cieInfo); | ||
| 1714 | foundInCache = foundFDE; | 1789 | foundInCache = foundFDE; |
| 1715 | } | 1790 | } |
| 1716 | } | 1791 | } |
| 1717 | if (!foundFDE) { | 1792 | if (!foundFDE) { |
| 1718 | // Still not found, do full scan of __eh_frame section. | 1793 | // Still not found, do full scan of __eh_frame section. |
| 1719 | foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, | 1794 | foundFDE = CFI_Parser<A>::template findFDE<R>( |
| 1720 | sects.dwarf_section_length, 0, | 1795 | _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, 0, |
| 1721 | &fdeInfo, &cieInfo); | 1796 | &fdeInfo, &cieInfo); |
| 1722 | } | 1797 | } |
| 1723 | if (foundFDE) { | 1798 | if (foundFDE) { |
| 1724 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) { | 1799 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) { |
| ... | @@ -1742,8 +1817,8 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, | ... | @@ -1742,8 +1817,8 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1742 | 1817 | ||
| 1743 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) | 1818 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
| 1744 | template <typename A, typename R> | 1819 | template <typename A, typename R> |
| 1745 | bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, | 1820 | bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( |
| 1746 | const UnwindInfoSections &sects) { | 1821 | typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects) { |
| 1747 | const bool log = false; | 1822 | const bool log = false; |
| 1748 | if (log) | 1823 | if (log) |
| 1749 | fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", | 1824 | fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", |
| ... | @@ -1974,6 +2049,16 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, | ... | @@ -1974,6 +2049,16 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, |
| 1974 | personalityIndex * sizeof(uint32_t)); | 2049 | personalityIndex * sizeof(uint32_t)); |
| 1975 | pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; | 2050 | pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; |
| 1976 | personality = _addressSpace.getP(personalityPointer); | 2051 | personality = _addressSpace.getP(personalityPointer); |
| 2052 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 2053 | // The GOT for the personality function was signed address authenticated. | ||
| 2054 | // Resign it as a regular function pointer. | ||
| 2055 | const auto discriminator = ptrauth_blend_discriminator( | ||
| 2056 | &_info.handler, __ptrauth_unwind_upi_handler_disc); | ||
| 2057 | void *signedPtr = ptrauth_auth_and_resign( | ||
| 2058 | (void *)personality, ptrauth_key_function_pointer, personalityPointer, | ||
| 2059 | ptrauth_key_function_pointer, discriminator); | ||
| 2060 | personality = (__typeof(personality))signedPtr; | ||
| 2061 | #endif | ||
| 1977 | if (log) | 2062 | if (log) |
| 1978 | fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " | 2063 | fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " |
| 1979 | "personalityDelta=0x%08X, personality=0x%08llX\n", | 2064 | "personalityDelta=0x%08X, personality=0x%08llX\n", |
| ... | @@ -1987,7 +2072,11 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, | ... | @@ -1987,7 +2072,11 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, |
| 1987 | _info.start_ip = funcStart; | 2072 | _info.start_ip = funcStart; |
| 1988 | _info.end_ip = funcEnd; | 2073 | _info.end_ip = funcEnd; |
| 1989 | _info.lsda = lsda; | 2074 | _info.lsda = lsda; |
| 1990 | _info.handler = personality; | 2075 | // We use memmove to copy the personality function as we have already manually |
| 2076 | // re-signed the pointer, and assigning directly will attempt to incorrectly | ||
| 2077 | // sign the already signed value. | ||
| 2078 | memmove(reinterpret_cast<void *>(&_info.handler), | ||
| 2079 | reinterpret_cast<void *>(&personality), sizeof(personality)); | ||
| 1991 | _info.gp = 0; | 2080 | _info.gp = 0; |
| 1992 | _info.flags = 0; | 2081 | _info.flags = 0; |
| 1993 | _info.format = encoding; | 2082 | _info.format = encoding; |
| ... | @@ -2640,11 +2729,19 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | ... | @@ -2640,11 +2729,19 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2640 | _isSigReturn = false; | 2729 | _isSigReturn = false; |
| 2641 | #endif | 2730 | #endif |
| 2642 | 2731 | ||
| 2643 | pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); | 2732 | typename R::reg_t rawPC = this->getReg(UNW_REG_IP); |
| 2733 | |||
| 2644 | #if defined(_LIBUNWIND_ARM_EHABI) | 2734 | #if defined(_LIBUNWIND_ARM_EHABI) |
| 2645 | // Remove the thumb bit so the IP represents the actual instruction address. | 2735 | // Remove the thumb bit so the IP represents the actual instruction address. |
| 2646 | // This matches the behaviour of _Unwind_GetIP on arm. | 2736 | // This matches the behaviour of _Unwind_GetIP on arm. |
| 2647 | pc &= (pint_t)~0x1; | 2737 | rawPC &= (pint_t)~0x1; |
| 2738 | #endif | ||
| 2739 | |||
| 2740 | typename R::link_reg_t pc; | ||
| 2741 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 2742 | _registers.loadAndAuthenticateLinkRegister(rawPC, &pc); | ||
| 2743 | #else | ||
| 2744 | pc = rawPC; | ||
| 2648 | #endif | 2745 | #endif |
| 2649 | 2746 | ||
| 2650 | // Exit early if at the top of the stack. | 2747 | // Exit early if at the top of the stack. |
| ... | @@ -2679,7 +2776,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | ... | @@ -2679,7 +2776,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2679 | 2776 | ||
| 2680 | // Ask address space object to find unwind sections for this pc. | 2777 | // Ask address space object to find unwind sections for this pc. |
| 2681 | UnwindInfoSections sects; | 2778 | UnwindInfoSections sects; |
| 2682 | if (_addressSpace.findUnwindSections(pc, sects)) { | 2779 | if (_addressSpace.template findUnwindSections<R>(pc, sects)) { |
| 2683 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) | 2780 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
| 2684 | // If there is a compact unwind encoding table, look there first. | 2781 | // If there is a compact unwind encoding table, look there first. |
| 2685 | if (sects.compact_unwind_section != 0) { | 2782 | if (sects.compact_unwind_section != 0) { |
| ... | @@ -2735,8 +2832,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | ... | @@ -2735,8 +2832,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2735 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 2832 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 2736 | // There is no static unwind info for this pc. Look to see if an FDE was | 2833 | // There is no static unwind info for this pc. Look to see if an FDE was |
| 2737 | // dynamically registered for it. | 2834 | // dynamically registered for it. |
| 2738 | pint_t cachedFDE = DwarfFDECache<A>::findFDE(DwarfFDECache<A>::kSearchAll, | 2835 | pint_t cachedFDE = |
| 2739 | pc); | 2836 | DwarfFDECache<A>::template findFDE<R>(DwarfFDECache<A>::kSearchAll, pc); |
| 2740 | if (cachedFDE != 0) { | 2837 | if (cachedFDE != 0) { |
| 2741 | typename CFI_Parser<A>::FDE_Info fdeInfo; | 2838 | typename CFI_Parser<A>::FDE_Info fdeInfo; |
| 2742 | typename CFI_Parser<A>::CIE_Info cieInfo; | 2839 | typename CFI_Parser<A>::CIE_Info cieInfo; |
| ... | @@ -2748,7 +2845,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | ... | @@ -2748,7 +2845,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2748 | // Lastly, ask AddressSpace object about platform specific ways to locate | 2845 | // Lastly, ask AddressSpace object about platform specific ways to locate |
| 2749 | // other FDEs. | 2846 | // other FDEs. |
| 2750 | pint_t fde; | 2847 | pint_t fde; |
| 2751 | if (_addressSpace.findOtherFDE(pc, fde)) { | 2848 | if (_addressSpace.template findOtherFDE<R>(pc, fde)) { |
| 2752 | typename CFI_Parser<A>::FDE_Info fdeInfo; | 2849 | typename CFI_Parser<A>::FDE_Info fdeInfo; |
| 2753 | typename CFI_Parser<A>::CIE_Info cieInfo; | 2850 | typename CFI_Parser<A>::CIE_Info cieInfo; |
| 2754 | if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { | 2851 | if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { |
| ... | @@ -2772,6 +2869,21 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | ... | @@ -2772,6 +2869,21 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2772 | 2869 | ||
| 2773 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ | 2870 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ |
| 2774 | defined(_LIBUNWIND_TARGET_AARCH64) | 2871 | defined(_LIBUNWIND_TARGET_AARCH64) |
| 2872 | |||
| 2873 | /* | ||
| 2874 | * The linux sigreturn restorer stub will always have the form: | ||
| 2875 | * | ||
| 2876 | * d2801168 movz x8, #0x8b | ||
| 2877 | * d4000001 svc #0x0 | ||
| 2878 | */ | ||
| 2879 | #if defined(__AARCH64EB__) | ||
| 2880 | #define MOVZ_X8_8B 0x681180d2 | ||
| 2881 | #define SVC_0 0x010000d4 | ||
| 2882 | #else | ||
| 2883 | #define MOVZ_X8_8B 0xd2801168 | ||
| 2884 | #define SVC_0 0xd4000001 | ||
| 2885 | #endif | ||
| 2886 | |||
| 2775 | template <typename A, typename R> | 2887 | template <typename A, typename R> |
| 2776 | bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) { | 2888 | bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) { |
| 2777 | // Look for the sigreturn trampoline. The trampoline's body is two | 2889 | // Look for the sigreturn trampoline. The trampoline's body is two |
| ... | @@ -2796,7 +2908,7 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) { | ... | @@ -2796,7 +2908,7 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) { |
| 2796 | return false; | 2908 | return false; |
| 2797 | auto *instructions = reinterpret_cast<const uint32_t *>(pc); | 2909 | auto *instructions = reinterpret_cast<const uint32_t *>(pc); |
| 2798 | // Look for instructions: mov x8, #0x8b; svc #0x0 | 2910 | // Look for instructions: mov x8, #0x8b; svc #0x0 |
| 2799 | if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001) | 2911 | if (instructions[0] != MOVZ_X8_8B || instructions[1] != SVC_0) |
| 2800 | return false; | 2912 | return false; |
| 2801 | 2913 | ||
| 2802 | _info = {}; | 2914 | _info = {}; |
| ... | @@ -3188,16 +3300,22 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { | ... | @@ -3188,16 +3300,22 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { |
| 3188 | template <typename A, typename R> | 3300 | template <typename A, typename R> |
| 3189 | void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) { | 3301 | void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) { |
| 3190 | if (_unwindInfoMissing) | 3302 | if (_unwindInfoMissing) |
| 3191 | memset(info, 0, sizeof(*info)); | 3303 | memset(static_cast<void *>(info), 0, sizeof(*info)); |
| 3192 | else | 3304 | else |
| 3193 | *info = _info; | 3305 | *info = _info; |
| 3194 | } | 3306 | } |
| 3195 | 3307 | ||
| 3196 | template <typename A, typename R> | 3308 | template <typename A, typename R> |
| 3197 | bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen, | 3309 | bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen, |
| 3198 | unw_word_t *offset) { | 3310 | unw_word_t *offset) { |
| 3199 | return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP), | 3311 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) |
| 3200 | buf, bufLen, offset); | 3312 | typename R::reg_t rawPC = this->getReg(UNW_REG_IP); |
| 3313 | typename R::link_reg_t pc; | ||
| 3314 | _registers.loadAndAuthenticateLinkRegister(rawPC, &pc); | ||
| 3315 | #else | ||
| 3316 | typename R::link_reg_t pc = this->getReg(UNW_REG_IP); | ||
| 3317 | #endif | ||
| 3318 | return _addressSpace.template findFunctionName<R>(pc, buf, bufLen, offset); | ||
| 3201 | } | 3319 | } |
| 3202 | 3320 | ||
| 3203 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) | 3321 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) |
lib/libunwind/src/UnwindLevel1.c+46-17| ... | @@ -48,16 +48,15 @@ | ... | @@ -48,16 +48,15 @@ |
| 48 | // avoided when invoking the `jumpto()` function. To do this, we use inline | 48 | // avoided when invoking the `jumpto()` function. To do this, we use inline |
| 49 | // assemblies to "goto" the `jumpto()` for these architectures. | 49 | // assemblies to "goto" the `jumpto()` for these architectures. |
| 50 | #if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS) | 50 | #if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS) |
| 51 | #define __unw_phase2_resume(cursor, fn) \ | 51 | #define __unw_phase2_resume(cursor, payload) \ |
| 52 | do { \ | 52 | do { \ |
| 53 | (void)fn; \ | 53 | __unw_resume_with_frames_walked((cursor), (payload)); \ |
| 54 | __unw_resume((cursor)); \ | ||
| 55 | } while (0) | 54 | } while (0) |
| 56 | #elif defined(_LIBUNWIND_TARGET_I386) | 55 | #elif defined(_LIBUNWIND_TARGET_I386) |
| 57 | #define __shstk_step_size (4) | 56 | #define __shstk_step_size (4) |
| 58 | #define __unw_phase2_resume(cursor, fn) \ | 57 | #define __unw_phase2_resume(cursor, payload) \ |
| 59 | do { \ | 58 | do { \ |
| 60 | _LIBUNWIND_POP_SHSTK_SSP((fn)); \ | 59 | _LIBUNWIND_POP_SHSTK_SSP((payload)); \ |
| 61 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ | 60 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ |
| 62 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ | 61 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ |
| 63 | __asm__ volatile("push %%edi\n\t" \ | 62 | __asm__ volatile("push %%edi\n\t" \ |
| ... | @@ -67,9 +66,9 @@ | ... | @@ -67,9 +66,9 @@ |
| 67 | } while (0) | 66 | } while (0) |
| 68 | #elif defined(_LIBUNWIND_TARGET_X86_64) | 67 | #elif defined(_LIBUNWIND_TARGET_X86_64) |
| 69 | #define __shstk_step_size (8) | 68 | #define __shstk_step_size (8) |
| 70 | #define __unw_phase2_resume(cursor, fn) \ | 69 | #define __unw_phase2_resume(cursor, payload) \ |
| 71 | do { \ | 70 | do { \ |
| 72 | _LIBUNWIND_POP_SHSTK_SSP((fn)); \ | 71 | _LIBUNWIND_POP_SHSTK_SSP((payload)); \ |
| 73 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ | 72 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ |
| 74 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ | 73 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ |
| 75 | __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \ | 74 | __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \ |
| ... | @@ -77,19 +76,37 @@ | ... | @@ -77,19 +76,37 @@ |
| 77 | } while (0) | 76 | } while (0) |
| 78 | #elif defined(_LIBUNWIND_TARGET_AARCH64) | 77 | #elif defined(_LIBUNWIND_TARGET_AARCH64) |
| 79 | #define __shstk_step_size (8) | 78 | #define __shstk_step_size (8) |
| 80 | #define __unw_phase2_resume(cursor, fn) \ | 79 | #define __unw_phase2_resume(cursor, payload) \ |
| 81 | do { \ | 80 | do { \ |
| 82 | _LIBUNWIND_POP_SHSTK_SSP((fn)); \ | 81 | _LIBUNWIND_POP_SHSTK_SSP((payload)); \ |
| 83 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ | 82 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ |
| 84 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ | 83 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ |
| 85 | __asm__ volatile("mov x0, %0\n\t" \ | 84 | __asm__ volatile("mov x0, %0\n\t" \ |
| 85 | "mov x1, #0\n\t" \ | ||
| 86 | "br %1\n\t" \ | 86 | "br %1\n\t" \ |
| 87 | : \ | 87 | : \ |
| 88 | : "r"(shstkRegContext), "r"(shstkJumpAddress) \ | 88 | : "r"(shstkRegContext), "r"(shstkJumpAddress) \ |
| 89 | : "x0"); \ | 89 | : "x0", "x1"); \ |
| 90 | } while (0) | 90 | } while (0) |
| 91 | #endif | 91 | #endif |
| 92 | 92 | ||
| 93 | // We need this helper function as the semantics of casting between integers and | ||
| 94 | // function pointers mean that we end up with a function pointer without the | ||
| 95 | // correct signature. Instead we assign to an integer with a matching schema, | ||
| 96 | // and then memmove the result into a variable of the correct type. This memmove | ||
| 97 | // is possible as `_Unwind_Personality_Fn` is a standard function pointer, and | ||
| 98 | // as such is not address diversified. | ||
| 99 | static _Unwind_Personality_Fn get_handler_function(unw_proc_info_t *frameInfo) { | ||
| 100 | uintptr_t __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, | ||
| 101 | 0, | ||
| 102 | ptrauth_function_pointer_type_discriminator(_Unwind_Personality_Fn)) | ||
| 103 | reauthenticatedIntegerHandler = frameInfo->handler; | ||
| 104 | _Unwind_Personality_Fn handler; | ||
| 105 | memmove(&handler, (void *)&reauthenticatedIntegerHandler, | ||
| 106 | sizeof(_Unwind_Personality_Fn)); | ||
| 107 | return handler; | ||
| 108 | } | ||
| 109 | |||
| 93 | static _Unwind_Reason_Code | 110 | static _Unwind_Reason_Code |
| 94 | unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { | 111 | unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { |
| 95 | __unw_init_local(cursor, uc); | 112 | __unw_init_local(cursor, uc); |
| ... | @@ -147,8 +164,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | ... | @@ -147,8 +164,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 147 | // If there is a personality routine, ask it if it will want to stop at | 164 | // If there is a personality routine, ask it if it will want to stop at |
| 148 | // this frame. | 165 | // this frame. |
| 149 | if (frameInfo.handler != 0) { | 166 | if (frameInfo.handler != 0) { |
| 150 | _Unwind_Personality_Fn p = | 167 | _Unwind_Personality_Fn p = get_handler_function(&frameInfo); |
| 151 | (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); | ||
| 152 | _LIBUNWIND_TRACE_UNWINDING( | 168 | _LIBUNWIND_TRACE_UNWINDING( |
| 153 | "unwind_phase1(ex_obj=%p): calling personality function %p", | 169 | "unwind_phase1(ex_obj=%p): calling personality function %p", |
| 154 | (void *)exception_object, (void *)(uintptr_t)p); | 170 | (void *)exception_object, (void *)(uintptr_t)p); |
| ... | @@ -184,11 +200,12 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | ... | @@ -184,11 +200,12 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 184 | } | 200 | } |
| 185 | return _URC_NO_REASON; | 201 | return _URC_NO_REASON; |
| 186 | } | 202 | } |
| 187 | extern int __unw_step_stage2(unw_cursor_t *); | ||
| 188 | 203 | ||
| 189 | #if defined(_LIBUNWIND_USE_GCS) | 204 | #if defined(_LIBUNWIND_USE_GCS) |
| 190 | // Enable the GCS target feature to permit gcspop instructions to be used. | 205 | // Enable the GCS target feature to permit gcspop instructions to be used. |
| 191 | __attribute__((target("+gcs"))) | 206 | __attribute__((target("+gcs"))) |
| 207 | #else | ||
| 208 | _LIBUNWIND_TRACE_NO_INLINE | ||
| 192 | #endif | 209 | #endif |
| 193 | static _Unwind_Reason_Code | 210 | static _Unwind_Reason_Code |
| 194 | unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, | 211 | unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, |
| ... | @@ -276,8 +293,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, | ... | @@ -276,8 +293,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, |
| 276 | ++framesWalked; | 293 | ++framesWalked; |
| 277 | // If there is a personality routine, tell it we are unwinding. | 294 | // If there is a personality routine, tell it we are unwinding. |
| 278 | if (frameInfo.handler != 0) { | 295 | if (frameInfo.handler != 0) { |
| 279 | _Unwind_Personality_Fn p = | 296 | _Unwind_Personality_Fn p = get_handler_function(&frameInfo); |
| 280 | (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); | ||
| 281 | _Unwind_Action action = _UA_CLEANUP_PHASE; | 297 | _Unwind_Action action = _UA_CLEANUP_PHASE; |
| 282 | if (sp == exception_object->private_2) { | 298 | if (sp == exception_object->private_2) { |
| 283 | // Tell personality this was the frame it marked in phase 1. | 299 | // Tell personality this was the frame it marked in phase 1. |
| ... | @@ -334,6 +350,8 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, | ... | @@ -334,6 +350,8 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, |
| 334 | #if defined(_LIBUNWIND_USE_GCS) | 350 | #if defined(_LIBUNWIND_USE_GCS) |
| 335 | // Enable the GCS target feature to permit gcspop instructions to be used. | 351 | // Enable the GCS target feature to permit gcspop instructions to be used. |
| 336 | __attribute__((target("+gcs"))) | 352 | __attribute__((target("+gcs"))) |
| 353 | #else | ||
| 354 | _LIBUNWIND_TRACE_NO_INLINE | ||
| 337 | #endif | 355 | #endif |
| 338 | static _Unwind_Reason_Code | 356 | static _Unwind_Reason_Code |
| 339 | unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, | 357 | unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| ... | @@ -394,8 +412,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, | ... | @@ -394,8 +412,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 394 | ++framesWalked; | 412 | ++framesWalked; |
| 395 | // If there is a personality routine, tell it we are unwinding. | 413 | // If there is a personality routine, tell it we are unwinding. |
| 396 | if (frameInfo.handler != 0) { | 414 | if (frameInfo.handler != 0) { |
| 397 | _Unwind_Personality_Fn p = | 415 | _Unwind_Personality_Fn p = get_handler_function(&frameInfo); |
| 398 | (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); | ||
| 399 | _LIBUNWIND_TRACE_UNWINDING( | 416 | _LIBUNWIND_TRACE_UNWINDING( |
| 400 | "unwind_phase2_forced(ex_obj=%p): calling personality function %p", | 417 | "unwind_phase2_forced(ex_obj=%p): calling personality function %p", |
| 401 | (void *)exception_object, (void *)(uintptr_t)p); | 418 | (void *)exception_object, (void *)(uintptr_t)p); |
| ... | @@ -597,6 +614,18 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { | ... | @@ -597,6 +614,18 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { |
| 597 | unw_cursor_t *cursor = (unw_cursor_t *)context; | 614 | unw_cursor_t *cursor = (unw_cursor_t *)context; |
| 598 | unw_word_t result; | 615 | unw_word_t result; |
| 599 | __unw_get_reg(cursor, UNW_REG_IP, &result); | 616 | __unw_get_reg(cursor, UNW_REG_IP, &result); |
| 617 | |||
| 618 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 619 | // If we are in an arm64e frame, then the PC should have been signed with the | ||
| 620 | // sp | ||
| 621 | { | ||
| 622 | unw_word_t sp; | ||
| 623 | __unw_get_reg(cursor, UNW_REG_SP, &sp); | ||
| 624 | result = (unw_word_t)ptrauth_auth_data((void *)result, | ||
| 625 | ptrauth_key_return_address, sp); | ||
| 626 | } | ||
| 627 | #endif | ||
| 628 | |||
| 600 | _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR, | 629 | _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR, |
| 601 | (void *)context, result); | 630 | (void *)context, result); |
| 602 | return (uintptr_t)result; | 631 | return (uintptr_t)result; |
lib/libunwind/src/UnwindRegistersRestore.S+46-5| ... | @@ -6,6 +6,8 @@ | ... | @@ -6,6 +6,8 @@ |
| 6 | // | 6 | // |
| 7 | //===----------------------------------------------------------------------===// | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | ||
| 9 | #if !defined(__wasm__) | ||
| 10 | |||
| 9 | #include "assembly.h" | 11 | #include "assembly.h" |
| 10 | 12 | ||
| 11 | #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | 13 | #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
| ... | @@ -16,13 +18,17 @@ | ... | @@ -16,13 +18,17 @@ |
| 16 | 18 | ||
| 17 | #if defined(_AIX) | 19 | #if defined(_AIX) |
| 18 | .toc | 20 | .toc |
| 21 | #elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE) | ||
| 22 | .section .text,"axy",@progbits,unique,0 | ||
| 19 | #else | 23 | #else |
| 20 | .text | 24 | .text |
| 21 | #endif | 25 | #endif |
| 22 | 26 | ||
| 23 | #if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) | 27 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
| 24 | 28 | ||
| 25 | #if defined(__i386__) | 29 | #if defined(__i386__) |
| 30 | .att_syntax | ||
| 31 | |||
| 26 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) | 32 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) |
| 27 | # | 33 | # |
| 28 | # extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); | 34 | # extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); |
| ... | @@ -67,6 +73,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) | ... | @@ -67,6 +73,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) |
| 67 | # skip gs | 73 | # skip gs |
| 68 | 74 | ||
| 69 | #elif defined(__x86_64__) && !defined(__arm64ec__) | 75 | #elif defined(__x86_64__) && !defined(__arm64ec__) |
| 76 | .att_syntax | ||
| 70 | 77 | ||
| 71 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) | 78 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) |
| 72 | # | 79 | # |
| ... | @@ -629,18 +636,35 @@ Lnovec: | ... | @@ -629,18 +636,35 @@ Lnovec: |
| 629 | 636 | ||
| 630 | #elif defined(__aarch64__) | 637 | #elif defined(__aarch64__) |
| 631 | 638 | ||
| 639 | #ifndef __has_feature | ||
| 640 | #define __has_feature(__feature) 0 | ||
| 641 | #endif | ||
| 642 | |||
| 632 | #if defined(__ARM_FEATURE_GCS_DEFAULT) | 643 | #if defined(__ARM_FEATURE_GCS_DEFAULT) |
| 633 | .arch_extension gcs | 644 | .arch_extension gcs |
| 634 | #endif | 645 | #endif |
| 635 | 646 | ||
| 636 | // | 647 | // |
| 637 | // extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); | 648 | // extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *, unsigned); |
| 638 | // | 649 | // |
| 639 | // On entry: | 650 | // On entry: |
| 640 | // thread_state pointer is in x0 | 651 | // thread_state pointer is in x0 |
| 652 | // walked_frames counter is in x1 | ||
| 641 | // | 653 | // |
| 642 | .p2align 2 | 654 | .p2align 2 |
| 643 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) | 655 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 656 | |||
| 657 | #if defined(_LIBUNWIND_TRACE_RET_INJECT) | ||
| 658 | cbz w1, 1f | ||
| 659 | 0: | ||
| 660 | subs w1, w1, #1 | ||
| 661 | adr x16, #8 | ||
| 662 | ret x16 | ||
| 663 | |||
| 664 | b.ne 0b | ||
| 665 | 1: | ||
| 666 | #endif | ||
| 667 | |||
| 644 | // skip restore of x0,x1 for now | 668 | // skip restore of x0,x1 for now |
| 645 | ldp x2, x3, [x0, #0x010] | 669 | ldp x2, x3, [x0, #0x010] |
| 646 | ldp x4, x5, [x0, #0x020] | 670 | ldp x4, x5, [x0, #0x020] |
| ... | @@ -657,7 +681,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) | ... | @@ -657,7 +681,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 657 | ldp x24,x25, [x0, #0x0C0] | 681 | ldp x24,x25, [x0, #0x0C0] |
| 658 | ldp x26,x27, [x0, #0x0D0] | 682 | ldp x26,x27, [x0, #0x0D0] |
| 659 | ldp x28,x29, [x0, #0x0E0] | 683 | ldp x28,x29, [x0, #0x0E0] |
| 660 | ldr x30, [x0, #0x100] // restore pc into lr | 684 | |
| 661 | #if defined(__ARM_FP) && __ARM_FP != 0 | 685 | #if defined(__ARM_FP) && __ARM_FP != 0 |
| 662 | ldp d0, d1, [x0, #0x110] | 686 | ldp d0, d1, [x0, #0x110] |
| 663 | ldp d2, d3, [x0, #0x120] | 687 | ldp d2, d3, [x0, #0x120] |
| ... | @@ -681,7 +705,18 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) | ... | @@ -681,7 +705,18 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 681 | // context struct, because it is allocated on the stack, and an exception | 705 | // context struct, because it is allocated on the stack, and an exception |
| 682 | // could clobber the de-allocated portion of the stack after sp has been | 706 | // could clobber the de-allocated portion of the stack after sp has been |
| 683 | // restored. | 707 | // restored. |
| 684 | ldr x16, [x0, #0x0F8] | 708 | |
| 709 | ldr x16, [x0, #0x0F8] // load sp into scratch | ||
| 710 | ldr lr, [x0, #0x100] // restore pc into lr | ||
| 711 | |||
| 712 | #if __has_feature(ptrauth_calls) | ||
| 713 | // The LR is signed with its address inside the register state. Time | ||
| 714 | // to resign to be a regular ROP protected signed pointer | ||
| 715 | add x1, x0, #0x100 | ||
| 716 | autib lr, x1 | ||
| 717 | pacib lr, x16 // signed the scratch register for sp | ||
| 718 | #endif | ||
| 719 | |||
| 685 | ldp x0, x1, [x0, #0x000] // restore x0,x1 | 720 | ldp x0, x1, [x0, #0x000] // restore x0,x1 |
| 686 | mov sp,x16 // restore sp | 721 | mov sp,x16 // restore sp |
| 687 | #if defined(__ARM_FEATURE_GCS_DEFAULT) | 722 | #if defined(__ARM_FEATURE_GCS_DEFAULT) |
| ... | @@ -694,7 +729,12 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) | ... | @@ -694,7 +729,12 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 694 | gcspushm x30 | 729 | gcspushm x30 |
| 695 | Lnogcs: | 730 | Lnogcs: |
| 696 | #endif | 731 | #endif |
| 732 | |||
| 733 | #if __has_feature(ptrauth_calls) | ||
| 734 | retab | ||
| 735 | #else | ||
| 697 | ret x30 // jump to pc | 736 | ret x30 // jump to pc |
| 737 | #endif | ||
| 698 | 738 | ||
| 699 | #elif defined(__arm__) && !defined(__APPLE__) | 739 | #elif defined(__arm__) && !defined(__APPLE__) |
| 700 | 740 | ||
| ... | @@ -1253,7 +1293,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) | ... | @@ -1253,7 +1293,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) |
| 1253 | 1293 | ||
| 1254 | #endif | 1294 | #endif |
| 1255 | 1295 | ||
| 1256 | #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ | 1296 | #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ |
| 1257 | 1297 | ||
| 1258 | NO_EXEC_STACK_DIRECTIVE | 1298 | NO_EXEC_STACK_DIRECTIVE |
| 1259 | 1299 | ||
| 1300 | #endif /* !defined(__wasm__) */ |
lib/libunwind/src/UnwindRegistersSave.S+86-2| ... | @@ -6,6 +6,8 @@ | ... | @@ -6,6 +6,8 @@ |
| 6 | // | 6 | // |
| 7 | //===----------------------------------------------------------------------===// | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | ||
| 9 | #if !defined(__wasm__) | ||
| 10 | |||
| 9 | #include "assembly.h" | 11 | #include "assembly.h" |
| 10 | 12 | ||
| 11 | #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | 13 | #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 |
| ... | @@ -16,13 +18,16 @@ | ... | @@ -16,13 +18,16 @@ |
| 16 | 18 | ||
| 17 | #if defined(_AIX) | 19 | #if defined(_AIX) |
| 18 | .toc | 20 | .toc |
| 21 | #elif defined(__aarch64__) && defined(__ELF__) && defined(_LIBUNWIND_EXECUTE_ONLY_CODE) | ||
| 22 | .section .text,"axy",@progbits,unique,0 | ||
| 19 | #else | 23 | #else |
| 20 | .text | 24 | .text |
| 21 | #endif | 25 | #endif |
| 22 | 26 | ||
| 23 | #if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) | 27 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
| 24 | 28 | ||
| 25 | #if defined(__i386__) | 29 | #if defined(__i386__) |
| 30 | .att_syntax | ||
| 26 | 31 | ||
| 27 | # | 32 | # |
| 28 | # extern int __unw_getcontext(unw_context_t* thread_state) | 33 | # extern int __unw_getcontext(unw_context_t* thread_state) |
| ... | @@ -107,6 +112,7 @@ DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext") | ... | @@ -107,6 +112,7 @@ DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext") |
| 107 | .text | 112 | .text |
| 108 | 113 | ||
| 109 | #elif defined(__x86_64__) | 114 | #elif defined(__x86_64__) |
| 115 | .att_syntax | ||
| 110 | 116 | ||
| 111 | # | 117 | # |
| 112 | # extern int __unw_getcontext(unw_context_t* thread_state) | 118 | # extern int __unw_getcontext(unw_context_t* thread_state) |
| ... | @@ -759,6 +765,10 @@ LnoR2Fix: | ... | @@ -759,6 +765,10 @@ LnoR2Fix: |
| 759 | 765 | ||
| 760 | #elif defined(__aarch64__) | 766 | #elif defined(__aarch64__) |
| 761 | 767 | ||
| 768 | #ifndef __has_feature | ||
| 769 | #define __has_feature(__feature) 0 | ||
| 770 | #endif | ||
| 771 | |||
| 762 | // | 772 | // |
| 763 | // extern int __unw_getcontext(unw_context_t* thread_state) | 773 | // extern int __unw_getcontext(unw_context_t* thread_state) |
| 764 | // | 774 | // |
| ... | @@ -767,6 +777,11 @@ LnoR2Fix: | ... | @@ -767,6 +777,11 @@ LnoR2Fix: |
| 767 | // | 777 | // |
| 768 | .p2align 2 | 778 | .p2align 2 |
| 769 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | 779 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 780 | |||
| 781 | #if __has_feature(ptrauth_calls) | ||
| 782 | pacibsp | ||
| 783 | #endif | ||
| 784 | |||
| 770 | stp x0, x1, [x0, #0x000] | 785 | stp x0, x1, [x0, #0x000] |
| 771 | stp x2, x3, [x0, #0x010] | 786 | stp x2, x3, [x0, #0x010] |
| 772 | stp x4, x5, [x0, #0x020] | 787 | stp x4, x5, [x0, #0x020] |
| ... | @@ -807,7 +822,74 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -807,7 +822,74 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 807 | str d31, [x0, #0x208] | 822 | str d31, [x0, #0x208] |
| 808 | #endif | 823 | #endif |
| 809 | mov x0, #0 // return UNW_ESUCCESS | 824 | mov x0, #0 // return UNW_ESUCCESS |
| 825 | |||
| 826 | #if __has_feature(ptrauth_calls) | ||
| 827 | retab | ||
| 828 | #else | ||
| 829 | ret | ||
| 830 | #endif | ||
| 831 | |||
| 832 | // | ||
| 833 | // extern "C" int64_t __libunwind_Registers_arm64_za_disable() | ||
| 834 | // | ||
| 835 | // This function implements the requirements of the __arm_za_disable ABI | ||
| 836 | // routine, except that it will not abort; it will return a non-zero value | ||
| 837 | // to signify the routine failed. | ||
| 838 | // | ||
| 839 | // Note: This function uses SME instructions. It must only be called if SME | ||
| 840 | // has been confirmed to be available. | ||
| 841 | // | ||
| 842 | // On return: | ||
| 843 | // | ||
| 844 | // A status is placed in x0. A zero value indicates success; any non-zero | ||
| 845 | // value indicates failure. | ||
| 846 | // | ||
| 847 | .p2align 2 | ||
| 848 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_za_disable) | ||
| 849 | .variant_pcs __libunwind_Registers_arm64_za_disable | ||
| 850 | #if __has_feature(ptrauth_calls) | ||
| 851 | pacibsp | ||
| 852 | #endif | ||
| 853 | // If TPIDR2_EL0 is null, the subroutine just disables ZA. | ||
| 854 | .inst 0xd53bd0b0 // mrs x16, TPIDR2_EL0 | ||
| 855 | cbz x16, 1f | ||
| 856 | |||
| 857 | // If any of the reserved bytes in the first 16 bytes of the TPIDR2 block are | ||
| 858 | // nonzero, return a non-zero value (libunwind will then abort). | ||
| 859 | ldrh w0, [x16, #10] | ||
| 860 | cbnz w0, 2f | ||
| 861 | ldr w0, [x16, #12] | ||
| 862 | cbnz w0, 2f | ||
| 863 | |||
| 864 | // If num_za_save_slices is zero, the subroutine just disables ZA. | ||
| 865 | ldrh w0, [x16, #8] | ||
| 866 | cbz x0, 1f | ||
| 867 | |||
| 868 | // If za_save_buffer is NULL, the subroutine just disables ZA. | ||
| 869 | ldr x16, [x16] | ||
| 870 | cbz x16, 1f | ||
| 871 | |||
| 872 | // Store ZA to za_save_buffer. | ||
| 873 | mov x15, xzr | ||
| 874 | 0: | ||
| 875 | .inst 0xe1206200 // str za[w15,0], [x16] | ||
| 876 | .inst 0x04305830 // addsvl x16, x16, #1 | ||
| 877 | add x15, x15, #1 | ||
| 878 | cmp x0, x15 | ||
| 879 | b.ne 0b | ||
| 880 | 1: | ||
| 881 | // * Set TPIDR2_EL0 to null. | ||
| 882 | .inst 0xd51bd0bf // msr TPIDR2_EL0, xzr | ||
| 883 | // * Set PSTATE.ZA to 0. | ||
| 884 | .inst 0xd503447f // smstop za | ||
| 885 | // * Return zero (success) | ||
| 886 | mov x0, xzr | ||
| 887 | 2: | ||
| 888 | #if __has_feature(ptrauth_calls) | ||
| 889 | retab | ||
| 890 | #else | ||
| 810 | ret | 891 | ret |
| 892 | #endif | ||
| 811 | 893 | ||
| 812 | #elif defined(__arm__) && !defined(__APPLE__) | 894 | #elif defined(__arm__) && !defined(__APPLE__) |
| 813 | 895 | ||
| ... | @@ -1232,6 +1314,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -1232,6 +1314,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1232 | WEAK_ALIAS(__unw_getcontext, unw_getcontext) | 1314 | WEAK_ALIAS(__unw_getcontext, unw_getcontext) |
| 1233 | #endif | 1315 | #endif |
| 1234 | 1316 | ||
| 1235 | #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ | 1317 | #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ |
| 1236 | 1318 | ||
| 1237 | NO_EXEC_STACK_DIRECTIVE | 1319 | NO_EXEC_STACK_DIRECTIVE |
| 1320 | |||
| 1321 | #endif /* !defined(__wasm__) */ |
lib/libunwind/src/assembly.h+5-1| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | #ifndef UNWIND_ASSEMBLY_H | 15 | #ifndef UNWIND_ASSEMBLY_H |
| 16 | #define UNWIND_ASSEMBLY_H | 16 | #define UNWIND_ASSEMBLY_H |
| 17 | 17 | ||
| 18 | #if defined(__linux__) && defined(__CET__) | 18 | #if defined(__CET__) |
| 19 | #include <cet.h> | 19 | #include <cet.h> |
| 20 | #define _LIBUNWIND_CET_ENDBR _CET_ENDBR | 20 | #define _LIBUNWIND_CET_ENDBR _CET_ENDBR |
| 21 | #else | 21 | #else |
| ... | @@ -132,6 +132,10 @@ | ... | @@ -132,6 +132,10 @@ |
| 132 | 132 | ||
| 133 | #if defined(__APPLE__) | 133 | #if defined(__APPLE__) |
| 134 | 134 | ||
| 135 | #if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__) | ||
| 136 | #define _LIBUNWIND_TRACE_RET_INJECT 1 | ||
| 137 | #endif | ||
| 138 | |||
| 135 | #define SYMBOL_IS_FUNC(name) | 139 | #define SYMBOL_IS_FUNC(name) |
| 136 | #define HIDDEN_SYMBOL(name) .private_extern name | 140 | #define HIDDEN_SYMBOL(name) .private_extern name |
| 137 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) | 141 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) |
lib/libunwind/src/config.h+9| ... | @@ -28,6 +28,9 @@ | ... | @@ -28,6 +28,9 @@ |
| 28 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 | 28 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 |
| 29 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 | 29 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
| 30 | #endif | 30 | #endif |
| 31 | #if defined(__aarch64__) || defined(__arm64__) || defined(__arm64e__) | ||
| 32 | #define _LIBUNWIND_TRACE_RET_INJECT 1 | ||
| 33 | #endif | ||
| 31 | #elif defined(_WIN32) | 34 | #elif defined(_WIN32) |
| 32 | #ifdef __SEH__ | 35 | #ifdef __SEH__ |
| 33 | #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1 | 36 | #define _LIBUNWIND_SUPPORT_SEH_UNWIND 1 |
| ... | @@ -61,6 +64,12 @@ | ... | @@ -61,6 +64,12 @@ |
| 61 | #endif | 64 | #endif |
| 62 | #endif | 65 | #endif |
| 63 | 66 | ||
| 67 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 68 | #define _LIBUNWIND_TRACE_NO_INLINE __attribute__((noinline, disable_tail_calls)) | ||
| 69 | #else | ||
| 70 | #define _LIBUNWIND_TRACE_NO_INLINE | ||
| 71 | #endif | ||
| 72 | |||
| 64 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) | 73 | #if defined(_LIBUNWIND_HIDE_SYMBOLS) |
| 65 | // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility. | 74 | // The CMake file passes -fvisibility=hidden to control ELF/Mach-O visibility. |
| 66 | #define _LIBUNWIND_EXPORT | 75 | #define _LIBUNWIND_EXPORT |
lib/libunwind/src/gcc_personality_v0.c+79-6| ... | @@ -31,6 +31,58 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT, | ... | @@ -31,6 +31,58 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT, |
| 31 | _Unwind_Personality_Fn); | 31 | _Unwind_Personality_Fn); |
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | #ifndef __has_feature | ||
| 35 | #define __has_feature(__feature) 0 | ||
| 36 | #endif | ||
| 37 | |||
| 38 | #if __has_feature(ptrauth_calls) | ||
| 39 | #include <ptrauth.h> | ||
| 40 | |||
| 41 | // `__ptrauth_restricted_intptr` is a feature of apple clang that predates | ||
| 42 | // support for direct application of `__ptrauth` to integer types. This | ||
| 43 | // guard is necessary to support compilation with those compiler. | ||
| 44 | #if __has_feature(ptrauth_restricted_intptr_qualifier) | ||
| 45 | #define __ptrauth_gcc_personality_intptr(key, addressDiscriminated, \ | ||
| 46 | discriminator) \ | ||
| 47 | __ptrauth_restricted_intptr(key, addressDiscriminated, discriminator) | ||
| 48 | #else | ||
| 49 | #define __ptrauth_gcc_personality_intptr(key, addressDiscriminated, \ | ||
| 50 | discriminator) \ | ||
| 51 | __ptrauth(key, addressDiscriminated, discriminator) | ||
| 52 | #endif | ||
| 53 | #else | ||
| 54 | #define __ptrauth_gcc_personality_intptr(...) | ||
| 55 | #endif | ||
| 56 | |||
| 57 | #define __ptrauth_gcc_personality_func_key ptrauth_key_function_pointer | ||
| 58 | |||
| 59 | // ptrauth_string_discriminator("__gcc_personality_v0'funcStart") == 0xDFEB | ||
| 60 | #define __ptrauth_gcc_personality_func_start \ | ||
| 61 | __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ | ||
| 62 | 0xDFEB) | ||
| 63 | |||
| 64 | // ptrauth_string_discriminator("__gcc_personality_v0'start") == 0x52DC | ||
| 65 | #define __ptrauth_gcc_personality_start \ | ||
| 66 | __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ | ||
| 67 | 0x52DC) | ||
| 68 | |||
| 69 | // ptrauth_string_discriminator("__gcc_personality_v0'length") == 0xFFF7 | ||
| 70 | #define __ptrauth_gcc_personality_length \ | ||
| 71 | __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ | ||
| 72 | 0xFFF7) | ||
| 73 | |||
| 74 | // ptrauth_string_discriminator("__gcc_personality_v0'landingPadOffset") == | ||
| 75 | // 0x6498 | ||
| 76 | #define __ptrauth_gcc_personality_lpoffset \ | ||
| 77 | __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ | ||
| 78 | 0x6498) | ||
| 79 | |||
| 80 | // ptrauth_string_discriminator("__gcc_personality_v0'landingPad") == 0xA134 | ||
| 81 | #define __ptrauth_gcc_personality_lpad_disc 0xA134 | ||
| 82 | #define __ptrauth_gcc_personality_lpad \ | ||
| 83 | __ptrauth_gcc_personality_intptr(__ptrauth_gcc_personality_func_key, 1, \ | ||
| 84 | __ptrauth_gcc_personality_lpad_disc) | ||
| 85 | |||
| 34 | // Pointer encodings documented at: | 86 | // Pointer encodings documented at: |
| 35 | // http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html | 87 | // http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html |
| 36 | 88 | ||
| ... | @@ -206,7 +258,8 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( | ... | @@ -206,7 +258,8 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( |
| 206 | return continueUnwind(exceptionObject, context); | 258 | return continueUnwind(exceptionObject, context); |
| 207 | 259 | ||
| 208 | uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1; | 260 | uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1; |
| 209 | uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context); | 261 | uintptr_t __ptrauth_gcc_personality_func_start funcStart = |
| 262 | (uintptr_t)_Unwind_GetRegionStart(context); | ||
| 210 | uintptr_t pcOffset = pc - funcStart; | 263 | uintptr_t pcOffset = pc - funcStart; |
| 211 | 264 | ||
| 212 | // Parse LSDA header. | 265 | // Parse LSDA header. |
| ... | @@ -225,11 +278,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( | ... | @@ -225,11 +278,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( |
| 225 | const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength; | 278 | const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength; |
| 226 | const uint8_t *p = callSiteTableStart; | 279 | const uint8_t *p = callSiteTableStart; |
| 227 | while (p < callSiteTableEnd) { | 280 | while (p < callSiteTableEnd) { |
| 228 | uintptr_t start = readEncodedPointer(&p, callSiteEncoding); | 281 | uintptr_t __ptrauth_gcc_personality_start start = |
| 229 | size_t length = readEncodedPointer(&p, callSiteEncoding); | 282 | readEncodedPointer(&p, callSiteEncoding); |
| 230 | size_t landingPad = readEncodedPointer(&p, callSiteEncoding); | 283 | size_t __ptrauth_gcc_personality_length length = |
| 284 | readEncodedPointer(&p, callSiteEncoding); | ||
| 285 | size_t __ptrauth_gcc_personality_lpoffset landingPadOffset = | ||
| 286 | readEncodedPointer(&p, callSiteEncoding); | ||
| 231 | readULEB128(&p); // action value not used for C code | 287 | readULEB128(&p); // action value not used for C code |
| 232 | if (landingPad == 0) | 288 | if (landingPadOffset == 0) |
| 233 | continue; // no landing pad for this entry | 289 | continue; // no landing pad for this entry |
| 234 | if ((start <= pcOffset) && (pcOffset < (start + length))) { | 290 | if ((start <= pcOffset) && (pcOffset < (start + length))) { |
| 235 | // Found landing pad for the PC. | 291 | // Found landing pad for the PC. |
| ... | @@ -239,7 +295,24 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( | ... | @@ -239,7 +295,24 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( |
| 239 | _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), | 295 | _Unwind_SetGR(context, __builtin_eh_return_data_regno(0), |
| 240 | (uintptr_t)exceptionObject); | 296 | (uintptr_t)exceptionObject); |
| 241 | _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); | 297 | _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); |
| 242 | _Unwind_SetIP(context, (funcStart + landingPad)); | 298 | size_t __ptrauth_gcc_personality_lpad landingPad = |
| 299 | funcStart + landingPadOffset; | ||
| 300 | #if __has_feature(ptrauth_calls) | ||
| 301 | uintptr_t stackPointer = _Unwind_GetGR(context, -2); | ||
| 302 | const uintptr_t existingDiscriminator = ptrauth_blend_discriminator( | ||
| 303 | &landingPad, __ptrauth_gcc_personality_lpad_disc); | ||
| 304 | // newIP is authenticated as if it were qualified with a pseudo qualifier | ||
| 305 | // along the lines of: | ||
| 306 | // __ptrauth(ptrauth_key_return_address, <stackPointer>, 0) | ||
| 307 | // where the stack pointer is used in place of the strict storage | ||
| 308 | // address. | ||
| 309 | uintptr_t newIP = (uintptr_t)ptrauth_auth_and_resign( | ||
| 310 | *(void **)&landingPad, __ptrauth_gcc_personality_func_key, | ||
| 311 | existingDiscriminator, ptrauth_key_return_address, stackPointer); | ||
| 312 | _Unwind_SetIP(context, newIP); | ||
| 313 | #else | ||
| 314 | _Unwind_SetIP(context, landingPad); | ||
| 315 | #endif | ||
| 243 | return _URC_INSTALL_CONTEXT; | 316 | return _URC_INSTALL_CONTEXT; |
| 244 | } | 317 | } |
| 245 | } | 318 | } |
lib/libunwind/src/libunwind.cpp+104-4| ... | @@ -118,14 +118,55 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, | ... | @@ -118,14 +118,55 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, |
| 118 | typedef LocalAddressSpace::pint_t pint_t; | 118 | typedef LocalAddressSpace::pint_t pint_t; |
| 119 | AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; | 119 | AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; |
| 120 | if (co->validReg(regNum)) { | 120 | if (co->validReg(regNum)) { |
| 121 | co->setReg(regNum, (pint_t)value); | ||
| 122 | // special case altering IP to re-find info (being called by personality | 121 | // special case altering IP to re-find info (being called by personality |
| 123 | // function) | 122 | // function) |
| 124 | if (regNum == UNW_REG_IP) { | 123 | if (regNum == UNW_REG_IP) { |
| 125 | unw_proc_info_t info; | 124 | unw_proc_info_t info; |
| 126 | // First, get the FDE for the old location and then update it. | 125 | // First, get the FDE for the old location and then update it. |
| 127 | co->getInfo(&info); | 126 | co->getInfo(&info); |
| 128 | co->setInfoBasedOnIPRegister(false); | 127 | |
| 128 | pint_t sp = (pint_t)co->getReg(UNW_REG_SP); | ||
| 129 | |||
| 130 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) | ||
| 131 | { | ||
| 132 | // It is only valid to set the IP within the current function. This is | ||
| 133 | // important for ptrauth, otherwise the IP cannot be correctly signed. | ||
| 134 | // The current signature of `value` is via the schema: | ||
| 135 | // __ptrauth(ptrauth_key_return_address, <<sp>>, 0) | ||
| 136 | // For this to be generally usable we manually re-sign it to the | ||
| 137 | // directly supported schema: | ||
| 138 | // __ptrauth(ptrauth_key_return_address, 1, 0) | ||
| 139 | unw_word_t | ||
| 140 | __unwind_ptrauth_restricted_intptr(ptrauth_key_return_address, 1, | ||
| 141 | 0) authenticated_value; | ||
| 142 | unw_word_t opaque_value = (uint64_t)ptrauth_auth_and_resign( | ||
| 143 | (void *)value, ptrauth_key_return_address, sp, | ||
| 144 | ptrauth_key_return_address, &authenticated_value); | ||
| 145 | memmove(reinterpret_cast<void *>(&authenticated_value), | ||
| 146 | reinterpret_cast<void *>(&opaque_value), | ||
| 147 | sizeof(authenticated_value)); | ||
| 148 | if (authenticated_value < info.start_ip || | ||
| 149 | authenticated_value > info.end_ip) | ||
| 150 | _LIBUNWIND_ABORT("PC vs frame info mismatch"); | ||
| 151 | |||
| 152 | // PC should have been signed with the sp, so we verify that | ||
| 153 | // roundtripping does not fail. The `ptrauth_auth_and_resign` is | ||
| 154 | // guaranteed to trap on authentication failure even without FPAC | ||
| 155 | // feature. | ||
| 156 | pint_t pc = (pint_t)co->getReg(UNW_REG_IP); | ||
| 157 | if (ptrauth_auth_and_resign((void *)pc, ptrauth_key_return_address, sp, | ||
| 158 | ptrauth_key_return_address, | ||
| 159 | sp) != (void *)pc) { | ||
| 160 | _LIBUNWIND_LOG( | ||
| 161 | "Bad unwind with PAuth-enabled ABI (0x%zX, 0x%zX)->0x%zX\n", pc, | ||
| 162 | sp, | ||
| 163 | (pint_t)ptrauth_auth_data((void *)pc, ptrauth_key_return_address, | ||
| 164 | sp)); | ||
| 165 | _LIBUNWIND_ABORT("Bad unwind with PAuth-enabled ABI"); | ||
| 166 | } | ||
| 167 | } | ||
| 168 | #endif | ||
| 169 | |||
| 129 | // If the original call expects stack adjustment, perform this now. | 170 | // If the original call expects stack adjustment, perform this now. |
| 130 | // Normal frame unwinding would have included the offset already in the | 171 | // Normal frame unwinding would have included the offset already in the |
| 131 | // CFA computation. | 172 | // CFA computation. |
| ... | @@ -133,7 +174,11 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, | ... | @@ -133,7 +174,11 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, |
| 133 | // this should actually be - info.gp. LLVM doesn't currently support | 174 | // this should actually be - info.gp. LLVM doesn't currently support |
| 134 | // any such platforms and Clang doesn't export a macro for them. | 175 | // any such platforms and Clang doesn't export a macro for them. |
| 135 | if (info.gp) | 176 | if (info.gp) |
| 136 | co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp); | 177 | co->setReg(UNW_REG_SP, sp + info.gp); |
| 178 | co->setReg(UNW_REG_IP, value); | ||
| 179 | co->setInfoBasedOnIPRegister(false); | ||
| 180 | } else { | ||
| 181 | co->setReg(regNum, (pint_t)value); | ||
| 137 | } | 182 | } |
| 138 | return UNW_ESUCCESS; | 183 | return UNW_ESUCCESS; |
| 139 | } | 184 | } |
| ... | @@ -205,7 +250,27 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor, | ... | @@ -205,7 +250,27 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor, |
| 205 | } | 250 | } |
| 206 | _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info) | 251 | _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info) |
| 207 | 252 | ||
| 208 | /// Resume execution at cursor position (aka longjump). | 253 | /// Rebalance the execution flow by injecting the right amount of `ret` |
| 254 | /// instruction relatively to the amount of `walkedFrames` then resume execution | ||
| 255 | /// at cursor position (aka longjump). | ||
| 256 | _LIBUNWIND_HIDDEN int __unw_resume_with_frames_walked(unw_cursor_t *cursor, | ||
| 257 | unsigned walkedFrames) { | ||
| 258 | _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p, walkedFrames=%u)", | ||
| 259 | static_cast<void *>(cursor), walkedFrames); | ||
| 260 | #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) | ||
| 261 | // Inform the ASan runtime that now might be a good time to clean stuff up. | ||
| 262 | __asan_handle_no_return(); | ||
| 263 | #endif | ||
| 264 | #ifdef _LIBUNWIND_TRACE_RET_INJECT | ||
| 265 | AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; | ||
| 266 | co->setWalkedFrames(walkedFrames); | ||
| 267 | #endif | ||
| 268 | return __unw_resume(cursor); | ||
| 269 | } | ||
| 270 | _LIBUNWIND_WEAK_ALIAS(__unw_resume_with_frames_walked, | ||
| 271 | unw_resume_with_frames_walked) | ||
| 272 | |||
| 273 | /// Legacy function. Resume execution at cursor position (aka longjump). | ||
| 209 | _LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) { | 274 | _LIBUNWIND_HIDDEN int __unw_resume(unw_cursor_t *cursor) { |
| 210 | _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor)); | 275 | _LIBUNWIND_TRACE_API("__unw_resume(cursor=%p)", static_cast<void *>(cursor)); |
| 211 | #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) | 276 | #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) |
| ... | @@ -347,6 +412,41 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { | ... | @@ -347,6 +412,41 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { |
| 347 | } | 412 | } |
| 348 | 413 | ||
| 349 | #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 414 | #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 415 | |||
| 416 | /// Maps the UNW_* error code to a textual representation | ||
| 417 | _LIBUNWIND_HIDDEN const char *__unw_strerror(int error_code) { | ||
| 418 | switch (error_code) { | ||
| 419 | case UNW_ESUCCESS: | ||
| 420 | return "no error"; | ||
| 421 | case UNW_EUNSPEC: | ||
| 422 | return "unspecified (general) error"; | ||
| 423 | case UNW_ENOMEM: | ||
| 424 | return "out of memory"; | ||
| 425 | case UNW_EBADREG: | ||
| 426 | return "bad register number"; | ||
| 427 | case UNW_EREADONLYREG: | ||
| 428 | return "attempt to write read-only register"; | ||
| 429 | case UNW_ESTOPUNWIND: | ||
| 430 | return "stop unwinding"; | ||
| 431 | case UNW_EINVALIDIP: | ||
| 432 | return "invalid IP"; | ||
| 433 | case UNW_EBADFRAME: | ||
| 434 | return "bad frame"; | ||
| 435 | case UNW_EINVAL: | ||
| 436 | return "unsupported operation or bad value"; | ||
| 437 | case UNW_EBADVERSION: | ||
| 438 | return "unwind info has unsupported version"; | ||
| 439 | case UNW_ENOINFO: | ||
| 440 | return "no unwind info found"; | ||
| 441 | #if defined(_LIBUNWIND_TARGET_AARCH64) && !defined(_LIBUNWIND_IS_NATIVE_ONLY) | ||
| 442 | case UNW_ECROSSRASIGNING: | ||
| 443 | return "cross unwind with return address signing"; | ||
| 444 | #endif | ||
| 445 | } | ||
| 446 | return "invalid error code"; | ||
| 447 | } | ||
| 448 | _LIBUNWIND_WEAK_ALIAS(__unw_strerror, unw_strerror) | ||
| 449 | |||
| 350 | #endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) | 450 | #endif // !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) |
| 351 | 451 | ||
| 352 | #ifdef __APPLE__ | 452 | #ifdef __APPLE__ |
lib/libunwind/src/libunwind_ext.h+7-1| ... | @@ -26,11 +26,16 @@ extern "C" { | ... | @@ -26,11 +26,16 @@ extern "C" { |
| 26 | extern int __unw_getcontext(unw_context_t *); | 26 | extern int __unw_getcontext(unw_context_t *); |
| 27 | extern int __unw_init_local(unw_cursor_t *, unw_context_t *); | 27 | extern int __unw_init_local(unw_cursor_t *, unw_context_t *); |
| 28 | extern int __unw_step(unw_cursor_t *); | 28 | extern int __unw_step(unw_cursor_t *); |
| 29 | extern int __unw_step_stage2(unw_cursor_t *); | ||
| 29 | extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *); | 30 | extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *); |
| 30 | extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *); | 31 | extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *); |
| 31 | extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t); | 32 | extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t); |
| 32 | extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t); | 33 | extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t); |
| 33 | extern int __unw_resume(unw_cursor_t *); | 34 | _LIBUNWIND_TRACE_NO_INLINE |
| 35 | extern int __unw_resume_with_frames_walked(unw_cursor_t *, unsigned); | ||
| 36 | // `__unw_resume` is a legacy function. Use `__unw_resume_with_frames_walked` instead. | ||
| 37 | _LIBUNWIND_TRACE_NO_INLINE | ||
| 38 | extern int __unw_resume(unw_cursor_t *); | ||
| 34 | 39 | ||
| 35 | #ifdef __arm__ | 40 | #ifdef __arm__ |
| 36 | /* Save VFP registers in FSTMX format (instead of FSTMD). */ | 41 | /* Save VFP registers in FSTMX format (instead of FSTMD). */ |
| ... | @@ -42,6 +47,7 @@ extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *); | ... | @@ -42,6 +47,7 @@ extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *); |
| 42 | extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t); | 47 | extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t); |
| 43 | extern int __unw_is_signal_frame(unw_cursor_t *); | 48 | extern int __unw_is_signal_frame(unw_cursor_t *); |
| 44 | extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *); | 49 | extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *); |
| 50 | extern const char *__unw_strerror(int); | ||
| 45 | 51 | ||
| 46 | #if defined(_AIX) | 52 | #if defined(_AIX) |
| 47 | extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *); | 53 | extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *); |
lib/libunwind/src/shadow_stack_unwind.h+2-2| ... | @@ -12,8 +12,8 @@ | ... | @@ -12,8 +12,8 @@ |
| 12 | 12 | ||
| 13 | #include "libunwind.h" | 13 | #include "libunwind.h" |
| 14 | 14 | ||
| 15 | // Currently, CET is implemented on Linux x86 platforms. | 15 | // Currently, CET is implemented on some ELF x86 platforms. |
| 16 | #if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__) | 16 | #if defined(__CET__) && defined(__SHSTK__) |
| 17 | #define _LIBUNWIND_USE_CET 1 | 17 | #define _LIBUNWIND_USE_CET 1 |
| 18 | #endif | 18 | #endif |
| 19 | 19 |