| author | |
| committer | |
| log | 5c17ee74127366ad8cc4d4ce82f11aa51899e28a |
| tree | f22071af10195611570f07b92921da0df3f2ac30 |
| parent | e68a75dabdae364cd50daa11c197ab372149e8a7 |
| signature |
18 files changed, 248 insertions(+), 80 deletions(-)
lib/libunwind/include/__libunwind_config.h+1-1| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | #ifndef ____LIBUNWIND_CONFIG_H__ |
| 10 | 10 | #define ____LIBUNWIND_CONFIG_H__ |
| 11 | 11 | |
| 12 | #define _LIBUNWIND_VERSION 15000 | |
| 12 | #define _LIBUNWIND_VERSION 230000 | |
| 13 | 13 | |
| 14 | 14 | #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ |
| 15 | 15 | !defined(__ARM_DWARF_EH__) && !defined(__SEH__) |
lib/libunwind/include/libunwind.h+1-1| ... | ... | @@ -122,7 +122,7 @@ |
| 122 | 122 | __unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1, \ |
| 123 | 123 | __ptrauth_unwind_cie_info_personality_disc) |
| 124 | 124 | |
| 125 | // ptrauth_string_discriminator("personality") == 0x7EAD) | |
| 125 | // ptrauth_string_discriminator("personality") == 0x7EAD | |
| 126 | 126 | #define __ptrauth_unwind_pauthtest_personality_disc 0x7EAD |
| 127 | 127 | |
| 128 | 128 | #else |
lib/libunwind/include/mach-o/compact_unwind_encoding.h+1-1| ... | ... | @@ -443,7 +443,7 @@ struct unwind_info_section_header_lsda_index_entry |
| 443 | 443 | |
| 444 | 444 | struct unwind_info_regular_second_level_entry |
| 445 | 445 | { |
| 446 | uint32_t functionOffset; | |
| 446 | uint32_t functionOffset; | |
| 447 | 447 | compact_unwind_encoding_t encoding; |
| 448 | 448 | }; |
| 449 | 449 |
lib/libunwind/include/unwind_itanium.h+1-1| ... | ... | @@ -32,7 +32,7 @@ struct _Unwind_Exception { |
| 32 | 32 | // The implementation of _Unwind_Exception uses an attribute mode on the |
| 33 | 33 | // above fields which has the side effect of causing this whole struct to |
| 34 | 34 | // round up to 32 bytes in size (48 with SEH). To be more explicit, we add |
| 35 | // pad fields added for binary compatibility. | |
| 35 | // pad fields for binary compatibility. | |
| 36 | 36 | uint32_t reserved[3]; |
| 37 | 37 | #endif |
| 38 | 38 | // The Itanium ABI requires that _Unwind_Exception objects are "double-word |
lib/libunwind/src/AddressSpace.hpp-1| ... | ... | @@ -666,7 +666,6 @@ inline bool LocalAddressSpace::findUnwindSections( |
| 666 | 666 | return true; |
| 667 | 667 | } |
| 668 | 668 | #endif |
| 669 | // zig patch: https://github.com/llvm/llvm-project/issues/194228 | |
| 670 | 669 | dl_iterate_cb_data cb_data = {this, &info, static_cast<pint_t>(targetAddr)}; |
| 671 | 670 | int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); |
| 672 | 671 | return static_cast<bool>(found); |
lib/libunwind/src/CompactUnwinder.hpp+5-4| ... | ... | @@ -12,6 +12,7 @@ |
| 12 | 12 | #ifndef __COMPACT_UNWINDER_HPP__ |
| 13 | 13 | #define __COMPACT_UNWINDER_HPP__ |
| 14 | 14 | |
| 15 | #include <inttypes.h> | |
| 15 | 16 | #include <stdint.h> |
| 16 | 17 | #include <stdlib.h> |
| 17 | 18 | |
| ... | ... | @@ -335,8 +336,8 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame( |
| 335 | 336 | default: |
| 336 | 337 | (void)functionStart; |
| 337 | 338 | _LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for " |
| 338 | "function starting at 0x%llX", | |
| 339 | compactEncoding, functionStart); | |
| 339 | "function starting at 0x%" PRIu64 "X", | |
| 340 | compactEncoding, functionStart); | |
| 340 | 341 | _LIBUNWIND_ABORT("invalid compact unwind encoding"); |
| 341 | 342 | } |
| 342 | 343 | savedRegisters += 8; |
| ... | ... | @@ -454,8 +455,8 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless( |
| 454 | 455 | break; |
| 455 | 456 | default: |
| 456 | 457 | _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " |
| 457 | "function starting at 0x%llX", | |
| 458 | encoding, functionStart); | |
| 458 | "function starting at 0x%" PRIu64 "X", | |
| 459 | encoding, functionStart); | |
| 459 | 460 | _LIBUNWIND_ABORT("invalid compact unwind encoding"); |
| 460 | 461 | } |
| 461 | 462 | savedRegisters += 8; |
lib/libunwind/src/DwarfInstructions.hpp+17-26| ... | ... | @@ -76,10 +76,14 @@ private: |
| 76 | 76 | __builtin_unreachable(); |
| 77 | 77 | } |
| 78 | 78 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 79 | static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa, | |
| 80 | PrologInfo &prolog); | |
| 81 | static bool isReturnAddressSignedWithPC(A &addressSpace, R registers, | |
| 82 | pint_t cfa, PrologInfo &prolog); | |
| 79 | enum RASignStatus { | |
| 80 | RANotSigned = 0, | |
| 81 | RASigned = 1, | |
| 82 | RASignedWithPC = 2, | |
| 83 | }; | |
| 84 | static RASignStatus getReturnAddressSignStatus(A &addressSpace, R registers, | |
| 85 | pint_t cfa, | |
| 86 | PrologInfo &prolog); | |
| 83 | 87 | #endif |
| 84 | 88 | }; |
| 85 | 89 | |
| ... | ... | @@ -177,7 +181,8 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( |
| 177 | 181 | } |
| 178 | 182 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 179 | 183 | template <typename A, typename R> |
| 180 | bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace, | |
| 184 | typename DwarfInstructions<A, R>::RASignStatus | |
| 185 | DwarfInstructions<A, R>::getReturnAddressSignStatus(A &addressSpace, | |
| 181 | 186 | R registers, pint_t cfa, |
| 182 | 187 | PrologInfo &prolog) { |
| 183 | 188 | pint_t raSignState; |
| ... | ... | @@ -187,24 +192,9 @@ bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace, |
| 187 | 192 | else |
| 188 | 193 | raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); |
| 189 | 194 | |
| 190 | // Only bit[0] is meaningful. | |
| 191 | return raSignState & 0x01; | |
| 192 | } | |
| 193 | ||
| 194 | template <typename A, typename R> | |
| 195 | bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace, | |
| 196 | R registers, | |
| 197 | pint_t cfa, | |
| 198 | PrologInfo &prolog) { | |
| 199 | pint_t raSignState; | |
| 200 | auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; | |
| 201 | if (regloc.location == CFI_Parser<A>::kRegisterUnused) | |
| 202 | raSignState = static_cast<pint_t>(regloc.value); | |
| 203 | else | |
| 204 | raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); | |
| 205 | ||
| 206 | // Only bit[1] is meaningful. | |
| 207 | return raSignState & 0x02; | |
| 195 | // bits[1:0] describe how RA is signed. | |
| 196 | assert((raSignState & 0x3) != 3 && "unexpected RA sign state"); | |
| 197 | return static_cast<RASignStatus>(raSignState & 0x3); | |
| 208 | 198 | } |
| 209 | 199 | #endif |
| 210 | 200 | |
| ... | ... | @@ -317,8 +307,9 @@ int DwarfInstructions<A, R>::stepWithDwarf( |
| 317 | 307 | // return address needs to be authenticated before the return address is |
| 318 | 308 | // restored. autia1716 is used instead of autia as autia1716 assembles |
| 319 | 309 | // to a NOP on pre-v8.3a architectures. |
| 320 | if ((R::getArch() == REGISTERS_ARM64) && | |
| 321 | isReturnAddressSigned(addressSpace, registers, cfa, prolog) && | |
| 310 | RASignStatus RAState = | |
| 311 | getReturnAddressSignStatus(addressSpace, registers, cfa, prolog); | |
| 312 | if ((R::getArch() == REGISTERS_ARM64) && RAState != RANotSigned && | |
| 322 | 313 | returnAddress != 0) { |
| 323 | 314 | #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) |
| 324 | 315 | return UNW_ECROSSRASIGNING; |
| ... | ... | @@ -329,7 +320,7 @@ int DwarfInstructions<A, R>::stepWithDwarf( |
| 329 | 320 | // We use the hint versions of the authentication instructions below to |
| 330 | 321 | // ensure they're assembled by the compiler even for targets with no |
| 331 | 322 | // FEAT_PAuth/FEAT_PAuth_LR support. |
| 332 | if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) { | |
| 323 | if (RAState == RASignedWithPC) { | |
| 333 | 324 | register unsigned long long x15 __asm("x15") = |
| 334 | 325 | prolog.ptrAuthDiversifier; |
| 335 | 326 | if (cieInfo.addressesSignedWithBKey) { |
lib/libunwind/src/DwarfParser.hpp-1| ... | ... | @@ -473,7 +473,6 @@ bool CFI_Parser<A>::parseFDEInstructions( |
| 473 | 473 | pint_t pcoffset; |
| 474 | 474 | }; |
| 475 | 475 | |
| 476 | // zig patch: https://github.com/llvm/llvm-project/issues/194228 | |
| 477 | 476 | ParseInfo parseInfoArray[] = { |
| 478 | 477 | {cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, |
| 479 | 478 | (pint_t)(-1)}, |
lib/libunwind/src/FrameHeaderCache.hpp+1-1| ... | ... | @@ -24,7 +24,7 @@ |
| 24 | 24 | #define _LIBUNWIND_FRAMEHEADERCACHE_TRACE(msg, ...) |
| 25 | 25 | #endif |
| 26 | 26 | |
| 27 | // This cache should only be be used from within a dl_iterate_phdr callback. | |
| 27 | // This cache should only be used from within a dl_iterate_phdr callback. | |
| 28 | 28 | // dl_iterate_phdr does the necessary synchronization to prevent problems |
| 29 | 29 | // with concurrent access via the libc load lock. Adding synchronization |
| 30 | 30 | // for other uses is possible, but not currently done. |
lib/libunwind/src/Registers.hpp+17-6| ... | ... | @@ -20,6 +20,9 @@ |
| 20 | 20 | #include "libunwind_ext.h" |
| 21 | 21 | #include "shadow_stack_unwind.h" |
| 22 | 22 | |
| 23 | #if defined(__APPLE__) | |
| 24 | #include <sys/sysctl.h> | |
| 25 | #endif | |
| 23 | 26 | #if defined(_LIBUNWIND_HAVE_GETAUXVAL) || defined(_LIBUNWIND_HAVE_ELF_AUX_INFO) |
| 24 | 27 | #include <sys/auxv.h> |
| 25 | 28 | #endif |
| ... | ... | @@ -1892,7 +1895,7 @@ public: |
| 1892 | 1895 | uint64_t value = _registers.__pc; |
| 1893 | 1896 | #if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING) |
| 1894 | 1897 | // 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. | |
| 1898 | // but everyone else expects it to be signed by the SP, so convert on return. | |
| 1896 | 1899 | value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc, |
| 1897 | 1900 | ptrauth_key_return_address, |
| 1898 | 1901 | &_registers.__pc, |
| ... | ... | @@ -1940,7 +1943,15 @@ private: |
| 1940 | 1943 | _LIBUNWIND_ABORT("SME ZA disable failed"); |
| 1941 | 1944 | } |
| 1942 | 1945 | |
| 1943 | #if defined(_LIBUNWIND_HAVE_GETAUXVAL) | |
| 1946 | #if defined(__APPLE__) | |
| 1947 | static bool checkHasSME() { | |
| 1948 | int has_sme = 0; | |
| 1949 | size_t size = sizeof(has_sme); | |
| 1950 | if (sysctlbyname("hw.optional.arm.FEAT_SME", &has_sme, &size, NULL, 0)) | |
| 1951 | return false; | |
| 1952 | return has_sme != 0; | |
| 1953 | } | |
| 1954 | #elif defined(_LIBUNWIND_HAVE_GETAUXVAL) | |
| 1944 | 1955 | static bool checkHasSME() { |
| 1945 | 1956 | constexpr int hwcap2_sme = (1 << 23); |
| 1946 | 1957 | unsigned long hwcap2 = getauxval(AT_HWCAP2); |
| ... | ... | @@ -3724,21 +3735,21 @@ inline void Registers_sparc::setRegister(int regNum, uint32_t value) { |
| 3724 | 3735 | inline bool Registers_sparc::validFloatRegister(int) const { return false; } |
| 3725 | 3736 | |
| 3726 | 3737 | inline double Registers_sparc::getFloatRegister(int) const { |
| 3727 | _LIBUNWIND_ABORT("no Sparc float registers"); | |
| 3738 | _LIBUNWIND_ABORT("no sparc float registers"); | |
| 3728 | 3739 | } |
| 3729 | 3740 | |
| 3730 | 3741 | inline void Registers_sparc::setFloatRegister(int, double) { |
| 3731 | _LIBUNWIND_ABORT("no Sparc float registers"); | |
| 3742 | _LIBUNWIND_ABORT("no sparc float registers"); | |
| 3732 | 3743 | } |
| 3733 | 3744 | |
| 3734 | 3745 | inline bool Registers_sparc::validVectorRegister(int) const { return false; } |
| 3735 | 3746 | |
| 3736 | 3747 | inline v128 Registers_sparc::getVectorRegister(int) const { |
| 3737 | _LIBUNWIND_ABORT("no Sparc vector registers"); | |
| 3748 | _LIBUNWIND_ABORT("no sparc vector registers"); | |
| 3738 | 3749 | } |
| 3739 | 3750 | |
| 3740 | 3751 | inline void Registers_sparc::setVectorRegister(int, v128) { |
| 3741 | _LIBUNWIND_ABORT("no Sparc vector registers"); | |
| 3752 | _LIBUNWIND_ABORT("no sparc vector registers"); | |
| 3742 | 3753 | } |
| 3743 | 3754 | |
| 3744 | 3755 | inline const char *Registers_sparc::getRegisterName(int regNum) { |
lib/libunwind/src/Unwind-wasm.c+20-3| ... | ... | @@ -54,7 +54,7 @@ _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) { |
| 54 | 54 | __wasm_lpad_context.selector = 0; |
| 55 | 55 | |
| 56 | 56 | // Call personality function. Wasm does not have two-phase unwinding, so we |
| 57 | // only do the cleanup phase. | |
| 57 | // only do the search phase. | |
| 58 | 58 | return __gxx_personality_wasm0( |
| 59 | 59 | 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object, |
| 60 | 60 | (struct _Unwind_Context *)&__wasm_lpad_context); |
| ... | ... | @@ -69,6 +69,21 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) { |
| 69 | 69 | __builtin_wasm_throw(0, exception_object); |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | // Define the `__cpp_exception` symbol which `__builtin_wasm_throw` above will | |
| 73 | // reference. This is defined here in `libunwind` as the single canonical | |
| 74 | // definition for this API and it's required for users to ensure that there's | |
| 75 | // only one copy of `libunwind` within a wasm module to ensure this is only | |
| 76 | // defined once and exactly once. | |
| 77 | __asm__(".globl __cpp_exception\n" | |
| 78 | #if defined(__wasm32__) | |
| 79 | ".tagtype __cpp_exception i32\n" | |
| 80 | #elif defined(__wasm64__) | |
| 81 | ".tagtype __cpp_exception i64\n" | |
| 82 | #else | |
| 83 | #error "Unsupported Wasm architecture" | |
| 84 | #endif | |
| 85 | "__cpp_exception:\n"); | |
| 86 | ||
| 72 | 87 | /// Called by __cxa_end_catch. |
| 73 | 88 | _LIBUNWIND_EXPORT void |
| 74 | 89 | _Unwind_DeleteException(_Unwind_Exception *exception_object) { |
| ... | ... | @@ -102,7 +117,8 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { |
| 102 | 117 | } |
| 103 | 118 | |
| 104 | 119 | /// Not used in Wasm. |
| 105 | _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t) {} | |
| 120 | _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, | |
| 121 | uintptr_t value) {} | |
| 106 | 122 | |
| 107 | 123 | /// Called by personality handler to get LSDA for current frame. |
| 108 | 124 | _LIBUNWIND_EXPORT uintptr_t |
| ... | ... | @@ -114,7 +130,8 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { |
| 114 | 130 | } |
| 115 | 131 | |
| 116 | 132 | /// Not used in Wasm. |
| 117 | _LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *) { | |
| 133 | _LIBUNWIND_EXPORT uintptr_t | |
| 134 | _Unwind_GetRegionStart(struct _Unwind_Context *context) { | |
| 118 | 135 | return 0; |
| 119 | 136 | } |
| 120 | 137 |
lib/libunwind/src/UnwindCursor.hpp+119-7| ... | ... | @@ -963,7 +963,7 @@ template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() { |
| 963 | 963 | /// UnwindCursor contains all state (including all register values) during |
| 964 | 964 | /// an unwind. This is normally stack allocated inside a unw_cursor_t. |
| 965 | 965 | template <typename A, typename R> |
| 966 | class UnwindCursor : public AbstractUnwindCursor{ | |
| 966 | class UnwindCursor : public AbstractUnwindCursor { | |
| 967 | 967 | typedef typename A::pint_t pint_t; |
| 968 | 968 | public: |
| 969 | 969 | UnwindCursor(unw_context_t *context, A &as); |
| ... | ... | @@ -1363,6 +1363,10 @@ private: |
| 1363 | 1363 | reinterpret_cast<tbtable *>(_info.unwind_info), |
| 1364 | 1364 | _registers, _isSignalFrame); |
| 1365 | 1365 | } |
| 1366 | bool isKnownVapiNotActive() const { return _isKnownVapiNotActive; } | |
| 1367 | void setIsKnownVapiNotActive(bool val) { _isKnownVapiNotActive = val; } | |
| 1368 | static pint_t getVAPILR(); | |
| 1369 | ||
| 1366 | 1370 | #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) |
| 1367 | 1371 | |
| 1368 | 1372 | A &_addressSpace; |
| ... | ... | @@ -1377,13 +1381,23 @@ private: |
| 1377 | 1381 | #ifdef _LIBUNWIND_TRACE_RET_INJECT |
| 1378 | 1382 | uint32_t _walkedFrames; |
| 1379 | 1383 | #endif |
| 1384 | #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) | |
| 1385 | // TODO: this will need to be recorded in the unw_context_t by unw_getcontext | |
| 1386 | // to support cases where the cursor is retrieved prior to invocation of the | |
| 1387 | // Virtual API. | |
| 1388 | bool _isKnownVapiNotActive; | |
| 1389 | #endif | |
| 1380 | 1390 | }; |
| 1381 | 1391 | |
| 1382 | ||
| 1383 | 1392 | template <typename A, typename R> |
| 1384 | 1393 | UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) |
| 1385 | 1394 | : _addressSpace(as), _registers(context), _unwindInfoMissing(false), |
| 1386 | _isSignalFrame(false) { | |
| 1395 | _isSignalFrame(false) | |
| 1396 | #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) | |
| 1397 | , | |
| 1398 | _isKnownVapiNotActive(false) | |
| 1399 | #endif | |
| 1400 | { | |
| 1387 | 1401 | static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), |
| 1388 | 1402 | "UnwindCursor<> does not fit in unw_cursor_t"); |
| 1389 | 1403 | static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)), |
| ... | ... | @@ -1393,13 +1407,17 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) |
| 1393 | 1407 | |
| 1394 | 1408 | template <typename A, typename R> |
| 1395 | 1409 | UnwindCursor<A, R>::UnwindCursor(A &as, void *) |
| 1396 | : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { | |
| 1410 | : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) | |
| 1411 | #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) | |
| 1412 | , | |
| 1413 | _isKnownVapiNotActive(false) | |
| 1414 | #endif | |
| 1415 | { | |
| 1397 | 1416 | memset(static_cast<void *>(&_info), 0, sizeof(_info)); |
| 1398 | 1417 | // FIXME |
| 1399 | 1418 | // fill in _registers from thread arg |
| 1400 | 1419 | } |
| 1401 | 1420 | |
| 1402 | ||
| 1403 | 1421 | template <typename A, typename R> |
| 1404 | 1422 | bool UnwindCursor<A, R>::validReg(int regNum) { |
| 1405 | 1423 | return _registers.validRegister(regNum); |
| ... | ... | @@ -1469,6 +1487,30 @@ template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { |
| 1469 | 1487 | static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1; |
| 1470 | 1488 | _registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED); |
| 1471 | 1489 | #else |
| 1490 | #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) | |
| 1491 | if (isKnownVapiNotActive()) { | |
| 1492 | // If the current frame is known VAPI not active, execute the VAPI return | |
| 1493 | // glue to clear the VAPI control block. The VAPI return glue is used by | |
| 1494 | // AIX longjmp based on the VAPI active status recorded by setjmp in the | |
| 1495 | // jmp_buf, which means that the VAPI return glue can be called solely on | |
| 1496 | // the basis of the VAPI active status of the target context. | |
| 1497 | ||
| 1498 | // VAPI return glue address is the VAPI glue address - 4. | |
| 1499 | #ifdef __64BIT__ | |
| 1500 | constexpr pint_t VAPIReturnGlue = 0x8e40 - 4; | |
| 1501 | #else | |
| 1502 | constexpr pint_t VAPIReturnGlue = 0x8c40 - 4; | |
| 1503 | #endif | |
| 1504 | ||
| 1505 | _LIBUNWIND_TRACE_UNWINDING("VAPI: executing return glue %p\n", | |
| 1506 | reinterpret_cast<void *>(VAPIReturnGlue)); | |
| 1507 | register auto *registers __asm__("r30") = &_registers; | |
| 1508 | __asm__ __volatile__("bla %[retglue]" | |
| 1509 | : "+r"(registers) | |
| 1510 | : [retglue] "i"(VAPIReturnGlue)); | |
| 1511 | registers->jumpto(); | |
| 1512 | } | |
| 1513 | #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) | |
| 1472 | 1514 | _registers.jumpto(); |
| 1473 | 1515 | #endif |
| 1474 | 1516 | } |
| ... | ... | @@ -2037,7 +2079,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection( |
| 2037 | 2079 | if (personalityIndex != 0) { |
| 2038 | 2080 | --personalityIndex; // change 1-based to zero-based index |
| 2039 | 2081 | if (personalityIndex >= sectionHeader.personalityArrayCount()) { |
| 2040 | _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " | |
| 2082 | _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " | |
| 2041 | 2083 | "but personality table has only %d entries", |
| 2042 | 2084 | encoding, personalityIndex, |
| 2043 | 2085 | sectionHeader.personalityArrayCount()); |
| ... | ... | @@ -2459,6 +2501,45 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) { |
| 2459 | 2501 | return true; |
| 2460 | 2502 | } |
| 2461 | 2503 | |
| 2504 | // VAPI glue addresses | |
| 2505 | constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8b80; | |
| 2506 | constexpr uintptr_t vapi_addr_64 = 0x8e00; | |
| 2507 | constexpr size_t vapi_size_64 = 0x0200; | |
| 2508 | constexpr uintptr_t vapi_glue_addr_begin = | |
| 2509 | vapi_glue_addr_ext_32; // Start address in 32-bit | |
| 2510 | constexpr uintptr_t vapi_glue_addr_end = | |
| 2511 | vapi_addr_64 + vapi_size_64; // End address in 64-bit | |
| 2512 | ||
| 2513 | #ifdef __64BIT__ | |
| 2514 | constexpr size_t VAPI_CB_SIZE = 256; | |
| 2515 | constexpr ptrdiff_t TLS_POINTER_OFFSET = 30 * 1024; | |
| 2516 | constexpr size_t TLSCB_BASE_SIZE = 256; | |
| 2517 | ||
| 2518 | static __inline__ __attribute__((__always_inline__)) char *tptr(void) { | |
| 2519 | char *result; | |
| 2520 | __asm__("mr %0, 13" : "=r"(result)); | |
| 2521 | return result; | |
| 2522 | } | |
| 2523 | #else // 32-bit | |
| 2524 | constexpr size_t VAPI_CB_SIZE = 128; | |
| 2525 | constexpr ptrdiff_t TLS_POINTER_OFFSET = 31 * 1024; | |
| 2526 | constexpr size_t TLSCB_BASE_SIZE = 128; | |
| 2527 | ||
| 2528 | static __inline__ __attribute__((__always_inline__)) char *tptr(void) { | |
| 2529 | char *result; | |
| 2530 | __asm__("mfspr %0, 259" : "=r"(result)); | |
| 2531 | return result; | |
| 2532 | } | |
| 2533 | #endif | |
| 2534 | ||
| 2535 | constexpr ptrdiff_t VAPI_CB_OFFSET = | |
| 2536 | TLS_POINTER_OFFSET + VAPI_CB_SIZE + TLSCB_BASE_SIZE; | |
| 2537 | ||
| 2538 | template <typename A, typename R> | |
| 2539 | typename UnwindCursor<A, R>::pint_t UnwindCursor<A, R>::getVAPILR() { | |
| 2540 | return *reinterpret_cast<pint_t *>(tptr() - VAPI_CB_OFFSET + 8); | |
| 2541 | } | |
| 2542 | ||
| 2462 | 2543 | // Step back up the stack following the frame back link. |
| 2463 | 2544 | template <typename A, typename R> |
| 2464 | 2545 | int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
| ... | ... | @@ -2511,6 +2592,16 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
| 2511 | 2592 | _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p", |
| 2512 | 2593 | reinterpret_cast<void *>(lastStack)); |
| 2513 | 2594 | |
| 2595 | pint_t returnAddressInStack = reinterpret_cast<pint_t *>(lastStack)[2]; | |
| 2596 | if (vapi_glue_addr_begin <= returnAddressInStack && | |
| 2597 | returnAddressInStack < vapi_glue_addr_end) { | |
| 2598 | _LIBUNWIND_TRACE_UNWINDING( | |
| 2599 | "The return address in stack %p is within the range of VAPI address;" | |
| 2600 | " set isKnownVapiNotActive to true\n", | |
| 2601 | reinterpret_cast<void *>(returnAddressInStack)); | |
| 2602 | setIsKnownVapiNotActive(true); | |
| 2603 | } | |
| 2604 | ||
| 2514 | 2605 | sigcontext *sigContext = reinterpret_cast<sigcontext *>( |
| 2515 | 2606 | reinterpret_cast<char *>(lastStack) + STKMINALIGN); |
| 2516 | 2607 | returnAddress = sigContext->sc_jmpbuf.jmp_context.iar; |
| ... | ... | @@ -2579,6 +2670,17 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
| 2579 | 2670 | } else { |
| 2580 | 2671 | // Otherwise, use the LR value in the stack link area. |
| 2581 | 2672 | returnAddress = reinterpret_cast<pint_t *>(lastStack)[2]; |
| 2673 | ||
| 2674 | if (vapi_glue_addr_begin <= returnAddress && | |
| 2675 | returnAddress < vapi_glue_addr_end) { | |
| 2676 | _LIBUNWIND_TRACE_UNWINDING( | |
| 2677 | "The return address=%p is within the range of VAPI address;", | |
| 2678 | reinterpret_cast<void *>(returnAddress)); | |
| 2679 | setIsKnownVapiNotActive(true); | |
| 2680 | returnAddress = getVAPILR(); | |
| 2681 | _LIBUNWIND_TRACE_UNWINDING("return address=%p from VAPI\n", | |
| 2682 | reinterpret_cast<void *>(returnAddress)); | |
| 2683 | } | |
| 2582 | 2684 | } |
| 2583 | 2685 | |
| 2584 | 2686 | // Reset LR in the current context. |
| ... | ... | @@ -2709,6 +2811,16 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
| 2709 | 2811 | // Return address is the address after call site instruction. |
| 2710 | 2812 | pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2]; |
| 2711 | 2813 | |
| 2814 | if (vapi_glue_addr_begin <= nextReturnAddress && | |
| 2815 | nextReturnAddress < vapi_glue_addr_end) { | |
| 2816 | _LIBUNWIND_TRACE_UNWINDING( | |
| 2817 | "The next return address=%p is within the range of VAPI address;", | |
| 2818 | reinterpret_cast<void *>(nextReturnAddress)); | |
| 2819 | nextReturnAddress = getVAPILR(); | |
| 2820 | _LIBUNWIND_TRACE_UNWINDING("the next return address=%p from VAPI\n", | |
| 2821 | reinterpret_cast<void *>(nextReturnAddress)); | |
| 2822 | } | |
| 2823 | ||
| 2712 | 2824 | if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) { |
| 2713 | 2825 | _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: " |
| 2714 | 2826 | "nextStack=%p, next return address=%p\n", |
| ... | ... | @@ -3256,7 +3368,7 @@ int UnwindCursor<A, R>::stepThroughSigReturn() { |
| 3256 | 3368 | |
| 3257 | 3369 | template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { |
| 3258 | 3370 | (void)stage2; |
| 3259 | // Bottom of stack is defined is when unwind info cannot be found. | |
| 3371 | // Bottom of stack is defined when unwind info cannot be found. | |
| 3260 | 3372 | if (_unwindInfoMissing) |
| 3261 | 3373 | return UNW_STEP_END; |
| 3262 | 3374 |
lib/libunwind/src/UnwindLevel1-gcc-ext.c+1-1| ... | ... | @@ -284,7 +284,7 @@ _LIBUNWIND_EXPORT void __deregister_frame(const void *fde) { |
| 284 | 284 | // before 10.6 used keymgr to track known FDEs, but these functions |
| 285 | 285 | // never got updated to use keymgr. |
| 286 | 286 | // For now, we implement these as do-nothing functions to keep any existing |
| 287 | // applications working. We also add the not in 10.6 symbol so that nwe | |
| 287 | // applications working. We also add the not in 10.6 symbol so that new | |
| 288 | 288 | // application won't be able to use them. |
| 289 | 289 | |
| 290 | 290 | #if defined(_LIBUNWIND_SUPPORT_FRAME_APIS) |
lib/libunwind/src/UnwindLevel1.c+1-1| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | // ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are |
| 15 | 15 | // defining inline functions to delegate the function calls to |
| 16 | 16 | // _Unwind_VRS_{Get,Set}(). However, some applications might declare the |
| 17 | // function protetype directly (instead of including <unwind.h>), thus we need | |
| 17 | // function prototype directly (instead of including <unwind.h>), thus we need | |
| 18 | 18 | // to export these functions from libunwind.so as well. |
| 19 | 19 | #define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1 |
| 20 | 20 |
lib/libunwind/src/UnwindRegistersRestore.S+18-1| ... | ... | @@ -678,9 +678,15 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 678 | 678 | ldp x18,x19, [x0, #0x090] |
| 679 | 679 | ldp x20,x21, [x0, #0x0A0] |
| 680 | 680 | ldp x22,x23, [x0, #0x0B0] |
| 681 | #if defined(__LFI__) | |
| 682 | ldr x24, [x0, #0x0C0] | |
| 683 | // Skip reloading x25-x28; reserved by LFI ABI. | |
| 684 | ldr x29, [x0, #0x0E8] | |
| 685 | #else | |
| 681 | 686 | ldp x24,x25, [x0, #0x0C0] |
| 682 | 687 | ldp x26,x27, [x0, #0x0D0] |
| 683 | 688 | ldp x28,x29, [x0, #0x0E0] |
| 689 | #endif | |
| 684 | 690 | |
| 685 | 691 | #if defined(__ARM_FP) && __ARM_FP != 0 |
| 686 | 692 | ldp d0, d1, [x0, #0x110] |
| ... | ... | @@ -941,11 +947,22 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) |
| 941 | 947 | |
| 942 | 948 | #elif defined(__hexagon__) |
| 943 | 949 | # On entry: |
| 944 | # thread_state pointer is in r2 | |
| 950 | # thread_state pointer is in r0 | |
| 945 | 951 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_hexagon6jumptoEv) |
| 946 | 952 | # |
| 947 | 953 | # void libunwind::Registers_hexagon::jumpto() |
| 948 | 954 | # |
| 955 | # The context layout is hexagon_thread_state_t: unsigned int __r[35] | |
| 956 | # __r[0..31] = r0..r31, __r[32] = predicates, __r[33] = PC. | |
| 957 | # Offsets: __r[n] is at byte offset n*4. r0 is the context pointer, so | |
| 958 | # it is restored last; r31 is loaded with the saved PC as the jumpr target. | |
| 959 | r2 = memw(r0+#8) | |
| 960 | r3 = memw(r0+#12) | |
| 961 | r4 = memw(r0+#16) | |
| 962 | r5 = memw(r0+#20) | |
| 963 | r6 = memw(r0+#24) | |
| 964 | r7 = memw(r0+#28) | |
| 965 | ||
| 949 | 966 | r8 = memw(r0+#32) |
| 950 | 967 | r9 = memw(r0+#36) |
| 951 | 968 | r10 = memw(r0+#40) |
lib/libunwind/src/UnwindRegistersSave.S+28-3| ... | ... | @@ -794,13 +794,20 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 794 | 794 | stp x18,x19, [x0, #0x090] |
| 795 | 795 | stp x20,x21, [x0, #0x0A0] |
| 796 | 796 | stp x22,x23, [x0, #0x0B0] |
| 797 | #if defined(__LFI__) | |
| 798 | str x24, [x0, #0x0C0] | |
| 799 | // Skip spilling x25-x28; reserved by LFI ABI. | |
| 800 | str x29, [x0, #0x0E8] | |
| 801 | #else | |
| 797 | 802 | stp x24,x25, [x0, #0x0C0] |
| 798 | 803 | stp x26,x27, [x0, #0x0D0] |
| 799 | 804 | stp x28,x29, [x0, #0x0E0] |
| 805 | #endif | |
| 800 | 806 | str x30, [x0, #0x0F0] |
| 801 | 807 | mov x1,sp |
| 802 | 808 | str x1, [x0, #0x0F8] |
| 803 | 809 | str x30, [x0, #0x100] // store return address as pc |
| 810 | str xzr, [x0, #0x108] // zero __ra_sign_state | |
| 804 | 811 | // skip cpsr |
| 805 | 812 | #if defined(__ARM_FP) && __ARM_FP != 0 |
| 806 | 813 | stp d0, d1, [x0, #0x110] |
| ... | ... | @@ -1096,8 +1103,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1096 | 1103 | # On entry: |
| 1097 | 1104 | # thread_state pointer is in r0 |
| 1098 | 1105 | # |
| 1106 | # The context layout is hexagon_thread_state_t: unsigned int __r[35] | |
| 1107 | # __r[0..31] = r0..r31, __r[32] = predicates, __r[33] = PC, __r[34] = unused | |
| 1108 | # Offsets: __r[n] is at byte offset n*4. | |
| 1109 | # | |
| 1099 | 1110 | #define OFFSET(offset) (offset/4) |
| 1100 | 1111 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1112 | // Save r1-r7 first (r0 is the context pointer, saved last) | |
| 1113 | memw(r0+#4) = r1 | |
| 1114 | memw(r0+#8) = r2 | |
| 1115 | memw(r0+#12) = r3 | |
| 1116 | memw(r0+#16) = r4 | |
| 1117 | memw(r0+#20) = r5 | |
| 1118 | memw(r0+#24) = r6 | |
| 1119 | memw(r0+#28) = r7 | |
| 1120 | ||
| 1101 | 1121 | memw(r0+#32) = r8 |
| 1102 | 1122 | memw(r0+#36) = r9 |
| 1103 | 1123 | memw(r0+#40) = r10 |
| ... | ... | @@ -1127,12 +1147,17 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1127 | 1147 | memw(r0+#116) = r29 |
| 1128 | 1148 | memw(r0+#120) = r30 |
| 1129 | 1149 | memw(r0+#124) = r31 |
| 1130 | r1 = c4 // Predicate register | |
| 1150 | ||
| 1151 | r1 = c4 // Predicate register | |
| 1131 | 1152 | memw(r0+#128) = r1 |
| 1132 | r1 = memw(r30) // *FP == Saved FP | |
| 1133 | r1 = r31 | |
| 1153 | ||
| 1154 | r1 = r31 // Store return address as PC | |
| 1134 | 1155 | memw(r0+#132) = r1 |
| 1135 | 1156 | |
| 1157 | // Save r0 (the context pointer itself) last | |
| 1158 | memw(r0+#0) = r0 | |
| 1159 | ||
| 1160 | r0 = #0 // return UNW_ESUCCESS | |
| 1136 | 1161 | jumpr r31 |
| 1137 | 1162 | |
| 1138 | 1163 | #elif defined(__sparc__) && defined(__arch64__) |
lib/libunwind/src/libunwind.cpp+15-19| ... | ... | @@ -32,7 +32,7 @@ |
| 32 | 32 | |
| 33 | 33 | using namespace libunwind; |
| 34 | 34 | |
| 35 | /// internal object to represent this processes address space | |
| 35 | /// internal object to represent this process's address space | |
| 36 | 36 | LocalAddressSpace LocalAddressSpace::sThisAddressSpace; |
| 37 | 37 | |
| 38 | 38 | _LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space = |
| ... | ... | @@ -131,23 +131,19 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, |
| 131 | 131 | { |
| 132 | 132 | // It is only valid to set the IP within the current function. This is |
| 133 | 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"); | |
| 134 | // | |
| 135 | // However many JITs do not configure CFI frames, so we cannot actually | |
| 136 | // enforce this - at least not without an extremely expensive syscall. | |
| 137 | // | |
| 138 | // For the forseeable future this will need to be a debug only assertion | |
| 139 | // so we just strip and assert to avoid the unnecessary auths in release | |
| 140 | // builds. | |
| 141 | unw_word_t stripped_value = (unw_word_t)ptrauth_strip( | |
| 142 | (void *)value, ptrauth_key_return_address); | |
| 143 | if (stripped_value < info.start_ip && stripped_value > info.end_ip) | |
| 144 | _LIBUNWIND_LOG("Badly behaved use of unw_set_reg: moving IP(0x%zX) " | |
| 145 | "outside of CFI bounds function (0x%zX, 0x%zX)", | |
| 146 | stripped_value, info.start_ip, info.end_ip); | |
| 151 | 147 | |
| 152 | 148 | // PC should have been signed with the sp, so we verify that |
| 153 | 149 | // roundtripping does not fail. The `ptrauth_auth_and_resign` is |
| ... | ... | @@ -306,7 +302,7 @@ _LIBUNWIND_HIDDEN int __unw_is_fpreg(unw_cursor_t *cursor, |
| 306 | 302 | } |
| 307 | 303 | _LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg, unw_is_fpreg) |
| 308 | 304 | |
| 309 | /// Checks if a register is a floating-point register. | |
| 305 | /// Get name of specified register at cursor position in stack frame. | |
| 310 | 306 | _LIBUNWIND_HIDDEN const char *__unw_regname(unw_cursor_t *cursor, |
| 311 | 307 | unw_regnum_t regNum) { |
| 312 | 308 | _LIBUNWIND_TRACE_API("__unw_regname(cursor=%p, regNum=%d)", |
lib/libunwind/src/libunwind_ext.h+2-2| ... | ... | @@ -120,10 +120,10 @@ typedef int (*unw_find_dynamic_unwind_sections)( |
| 120 | 120 | extern int __unw_add_find_dynamic_unwind_sections( |
| 121 | 121 | unw_find_dynamic_unwind_sections find_dynamic_unwind_sections); |
| 122 | 122 | |
| 123 | // Deregister a dynacim unwind-info lookup callback. | |
| 123 | // Deregister a dynamic unwind-info lookup callback. | |
| 124 | 124 | // |
| 125 | 125 | // Returns UNW_ESUCCESS for successful deregistrations. If the given callback |
| 126 | // has already been registered then UNW_EINVAL will be returned. | |
| 126 | // is not present then UNW_EINVAL will be returned. | |
| 127 | 127 | extern int __unw_remove_find_dynamic_unwind_sections( |
| 128 | 128 | unw_find_dynamic_unwind_sections find_dynamic_unwind_sections); |
| 129 | 129 |