| author | |
| committer | |
| log | 85438e75e04b356ca319051c33e0987a9958ad4a |
| tree | 985baaa5543044d8ac252427e97ba4e1463975db |
| parent | c34fc8f19884ebe551b1dea9b8061efd3680848a |
| signature |
10 files changed, 430 insertions(+), 167 deletions(-)
lib/libunwind/src/Registers.hpp+5-5| ... | ... | @@ -15,9 +15,9 @@ |
| 15 | 15 | #include <stdint.h> |
| 16 | 16 | #include <string.h> |
| 17 | 17 | |
| 18 | #include "cet_unwind.h" | |
| 19 | 18 | #include "config.h" |
| 20 | 19 | #include "libunwind.h" |
| 20 | #include "shadow_stack_unwind.h" | |
| 21 | 21 | |
| 22 | 22 | namespace libunwind { |
| 23 | 23 | |
| ... | ... | @@ -48,7 +48,7 @@ class _LIBUNWIND_HIDDEN Registers_x86; |
| 48 | 48 | extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); |
| 49 | 49 | |
| 50 | 50 | #if defined(_LIBUNWIND_USE_CET) |
| 51 | extern "C" void *__libunwind_cet_get_jump_target() { | |
| 51 | extern "C" void *__libunwind_shstk_get_jump_target() { | |
| 52 | 52 | return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto); |
| 53 | 53 | } |
| 54 | 54 | #endif |
| ... | ... | @@ -268,7 +268,7 @@ class _LIBUNWIND_HIDDEN Registers_x86_64; |
| 268 | 268 | extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); |
| 269 | 269 | |
| 270 | 270 | #if defined(_LIBUNWIND_USE_CET) |
| 271 | extern "C" void *__libunwind_cet_get_jump_target() { | |
| 271 | extern "C" void *__libunwind_shstk_get_jump_target() { | |
| 272 | 272 | return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto); |
| 273 | 273 | } |
| 274 | 274 | #endif |
| ... | ... | @@ -1817,7 +1817,7 @@ class _LIBUNWIND_HIDDEN Registers_arm64; |
| 1817 | 1817 | extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); |
| 1818 | 1818 | |
| 1819 | 1819 | #if defined(_LIBUNWIND_USE_GCS) |
| 1820 | extern "C" void *__libunwind_cet_get_jump_target() { | |
| 1820 | extern "C" void *__libunwind_shstk_get_jump_target() { | |
| 1821 | 1821 | return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto); |
| 1822 | 1822 | } |
| 1823 | 1823 | #endif |
| ... | ... | @@ -4126,7 +4126,7 @@ inline reg_t Registers_riscv::getRegister(int regNum) const { |
| 4126 | 4126 | return _registers[regNum]; |
| 4127 | 4127 | if (regNum == UNW_RISCV_VLENB) { |
| 4128 | 4128 | reg_t vlenb; |
| 4129 | __asm__("csrr %0, 0xC22" : "=r"(vlenb)); | |
| 4129 | __asm__ volatile("csrr %0, 0xC22" : "=r"(vlenb)); | |
| 4130 | 4130 | return vlenb; |
| 4131 | 4131 | } |
| 4132 | 4132 | _LIBUNWIND_ABORT("unsupported riscv register"); |
lib/libunwind/src/Unwind-seh.cpp+41| ... | ... | @@ -51,6 +51,32 @@ static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor); |
| 51 | 51 | static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor, |
| 52 | 52 | DISPATCHER_CONTEXT *disp); |
| 53 | 53 | |
| 54 | #pragma clang diagnostic push | |
| 55 | #pragma clang diagnostic ignored "-Wgnu-anonymous-struct" | |
| 56 | // Local redefinition of this type; mingw-w64 headers lack the | |
| 57 | // DISPATCHER_CONTEXT_NONVOLREG_ARM64 type as of May 2025, so locally redefine | |
| 58 | // it and use that definition, to avoid needing to test/guess whether the real | |
| 59 | // type is available of not. | |
| 60 | union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 { | |
| 61 | BYTE Buffer[11 * sizeof(DWORD64) + 8 * sizeof(double)]; | |
| 62 | ||
| 63 | struct { | |
| 64 | DWORD64 GpNvRegs[11]; | |
| 65 | double FpNvRegs[8]; | |
| 66 | }; | |
| 67 | }; | |
| 68 | ||
| 69 | // Custom data type definition; this type is not defined in WinSDK. | |
| 70 | union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM { | |
| 71 | BYTE Buffer[8 * sizeof(DWORD) + 8 * sizeof(double)]; | |
| 72 | ||
| 73 | struct { | |
| 74 | DWORD GpNvRegs[8]; | |
| 75 | double FpNvRegs[8]; | |
| 76 | }; | |
| 77 | }; | |
| 78 | #pragma clang diagnostic pop | |
| 79 | ||
| 54 | 80 | /// Common implementation of SEH-style handler functions used by Itanium- |
| 55 | 81 | /// style frames. Depending on how and why it was called, it may do one of: |
| 56 | 82 | /// a) Delegate to the given Itanium-style personality function; or |
| ... | ... | @@ -212,6 +238,21 @@ __libunwind_seh_personality(int version, _Unwind_Action state, |
| 212 | 238 | ms_exc.ExceptionInformation[2] = state; |
| 213 | 239 | DISPATCHER_CONTEXT *disp_ctx = |
| 214 | 240 | __unw_seh_get_disp_ctx((unw_cursor_t *)context); |
| 241 | #if defined(__aarch64__) | |
| 242 | LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 nonvol; | |
| 243 | memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->X19, | |
| 244 | sizeof(nonvol.GpNvRegs)); | |
| 245 | for (int i = 0; i < 8; i++) | |
| 246 | nonvol.FpNvRegs[i] = disp_ctx->ContextRecord->V[i + 8].D[0]; | |
| 247 | disp_ctx->NonVolatileRegisters = nonvol.Buffer; | |
| 248 | #elif defined(__arm__) | |
| 249 | LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM nonvol; | |
| 250 | memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->R4, | |
| 251 | sizeof(nonvol.GpNvRegs)); | |
| 252 | memcpy(&nonvol.FpNvRegs, &disp_ctx->ContextRecord->D[8], | |
| 253 | sizeof(nonvol.FpNvRegs)); | |
| 254 | disp_ctx->NonVolatileRegisters = nonvol.Buffer; | |
| 255 | #endif | |
| 215 | 256 | _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling " |
| 216 | 257 | "LanguageHandler %p(%p, %p, %p, %p)", |
| 217 | 258 | (void *)disp_ctx->LanguageHandler, (void *)&ms_exc, |
lib/libunwind/src/Unwind-wasm.c+2-4| ... | ... | @@ -102,8 +102,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | 104 | /// Not used in Wasm. |
| 105 | _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, | |
| 106 | uintptr_t value) {} | |
| 105 | _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t) {} | |
| 107 | 106 | |
| 108 | 107 | /// Called by personality handler to get LSDA for current frame. |
| 109 | 108 | _LIBUNWIND_EXPORT uintptr_t |
| ... | ... | @@ -115,8 +114,7 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { |
| 115 | 114 | } |
| 116 | 115 | |
| 117 | 116 | /// Not used in Wasm. |
| 118 | _LIBUNWIND_EXPORT uintptr_t | |
| 119 | _Unwind_GetRegionStart(struct _Unwind_Context *context) { | |
| 117 | _LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *) { | |
| 120 | 118 | return 0; |
| 121 | 119 | } |
| 122 | 120 |
lib/libunwind/src/UnwindCursor.hpp+228-58| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | #ifndef __UNWINDCURSOR_HPP__ |
| 12 | 12 | #define __UNWINDCURSOR_HPP__ |
| 13 | 13 | |
| 14 | #include "cet_unwind.h" | |
| 14 | #include "shadow_stack_unwind.h" | |
| 15 | 15 | #include <stdint.h> |
| 16 | 16 | #include <stdio.h> |
| 17 | 17 | #include <stdlib.h> |
| ... | ... | @@ -31,8 +31,9 @@ |
| 31 | 31 | #endif |
| 32 | 32 | |
| 33 | 33 | #if defined(_LIBUNWIND_TARGET_LINUX) && \ |
| 34 | (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \ | |
| 35 | defined(_LIBUNWIND_TARGET_S390X)) | |
| 34 | (defined(_LIBUNWIND_TARGET_AARCH64) || \ | |
| 35 | defined(_LIBUNWIND_TARGET_LOONGARCH) || \ | |
| 36 | defined(_LIBUNWIND_TARGET_RISCV) || defined(_LIBUNWIND_TARGET_S390X)) | |
| 36 | 37 | #include <errno.h> |
| 37 | 38 | #include <signal.h> |
| 38 | 39 | #include <sys/syscall.h> |
| ... | ... | @@ -40,6 +41,12 @@ |
| 40 | 41 | #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 |
| 41 | 42 | #endif |
| 42 | 43 | |
| 44 | #if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) | |
| 45 | #include <OS.h> | |
| 46 | #include <signal.h> | |
| 47 | #define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1 | |
| 48 | #endif | |
| 49 | ||
| 43 | 50 | #include "AddressSpace.hpp" |
| 44 | 51 | #include "CompactUnwinder.hpp" |
| 45 | 52 | #include "config.h" |
| ... | ... | @@ -82,6 +89,22 @@ struct UNWIND_INFO { |
| 82 | 89 | uint16_t UnwindCodes[2]; |
| 83 | 90 | }; |
| 84 | 91 | |
| 92 | #pragma clang diagnostic push | |
| 93 | #pragma clang diagnostic ignored "-Wgnu-anonymous-struct" | |
| 94 | union UNWIND_INFO_ARM { | |
| 95 | DWORD HeaderData; | |
| 96 | struct { | |
| 97 | DWORD FunctionLength : 18; | |
| 98 | DWORD Version : 2; | |
| 99 | DWORD ExceptionDataPresent : 1; | |
| 100 | DWORD EpilogInHeader : 1; | |
| 101 | DWORD FunctionFragment : 1; | |
| 102 | DWORD EpilogCount : 5; | |
| 103 | DWORD CodeWords : 4; | |
| 104 | }; | |
| 105 | }; | |
| 106 | #pragma clang diagnostic pop | |
| 107 | ||
| 85 | 108 | extern "C" _Unwind_Reason_Code __libunwind_seh_personality( |
| 86 | 109 | int, _Unwind_Action, uint64_t, _Unwind_Exception *, |
| 87 | 110 | struct _Unwind_Context *); |
| ... | ... | @@ -150,7 +173,7 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false; |
| 150 | 173 | #endif |
| 151 | 174 | |
| 152 | 175 | template <typename A> |
| 153 | typename DwarfFDECache<A>::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { | |
| 176 | typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { | |
| 154 | 177 | pint_t result = 0; |
| 155 | 178 | _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); |
| 156 | 179 | for (entry *p = _buffer; p < _bufferUsed; ++p) { |
| ... | ... | @@ -996,6 +1019,10 @@ private: |
| 996 | 1019 | bool setInfoForSigReturn(Registers_arm64 &); |
| 997 | 1020 | int stepThroughSigReturn(Registers_arm64 &); |
| 998 | 1021 | #endif |
| 1022 | #if defined(_LIBUNWIND_TARGET_LOONGARCH) | |
| 1023 | bool setInfoForSigReturn(Registers_loongarch &); | |
| 1024 | int stepThroughSigReturn(Registers_loongarch &); | |
| 1025 | #endif | |
| 999 | 1026 | #if defined(_LIBUNWIND_TARGET_RISCV) |
| 1000 | 1027 | bool setInfoForSigReturn(Registers_riscv &); |
| 1001 | 1028 | int stepThroughSigReturn(Registers_riscv &); |
| ... | ... | @@ -1010,7 +1037,7 @@ private: |
| 1010 | 1037 | template <typename Registers> int stepThroughSigReturn(Registers &) { |
| 1011 | 1038 | return UNW_STEP_END; |
| 1012 | 1039 | } |
| 1013 | #elif defined(_LIBUNWIND_TARGET_HAIKU) | |
| 1040 | #elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) | |
| 1014 | 1041 | bool setInfoForSigReturn(); |
| 1015 | 1042 | int stepThroughSigReturn(); |
| 1016 | 1043 | #endif |
| ... | ... | @@ -2013,6 +2040,61 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) { |
| 2013 | 2040 | _info.handler = 0; |
| 2014 | 2041 | } |
| 2015 | 2042 | } |
| 2043 | #elif defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_ARM) | |
| 2044 | ||
| 2045 | #if defined(_LIBUNWIND_TARGET_AARCH64) | |
| 2046 | #define FUNC_LENGTH_UNIT 4 | |
| 2047 | #define XDATA_TYPE IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA | |
| 2048 | #else | |
| 2049 | #define FUNC_LENGTH_UNIT 2 | |
| 2050 | #define XDATA_TYPE UNWIND_INFO_ARM | |
| 2051 | #endif | |
| 2052 | if (unwindEntry->Flag != 0) { // Packed unwind info | |
| 2053 | _info.end_ip = | |
| 2054 | _info.start_ip + unwindEntry->FunctionLength * FUNC_LENGTH_UNIT; | |
| 2055 | // Only fill in the handler and LSDA if they're stale. | |
| 2056 | if (pc != getLastPC()) { | |
| 2057 | // Packed unwind info doesn't have an exception handler. | |
| 2058 | _info.lsda = 0; | |
| 2059 | _info.handler = 0; | |
| 2060 | } | |
| 2061 | } else { | |
| 2062 | XDATA_TYPE *xdata = | |
| 2063 | reinterpret_cast<XDATA_TYPE *>(base + unwindEntry->UnwindData); | |
| 2064 | _info.end_ip = _info.start_ip + xdata->FunctionLength * FUNC_LENGTH_UNIT; | |
| 2065 | // Only fill in the handler and LSDA if they're stale. | |
| 2066 | if (pc != getLastPC()) { | |
| 2067 | if (xdata->ExceptionDataPresent) { | |
| 2068 | uint32_t offset = 1; // The main xdata | |
| 2069 | uint32_t codeWords = xdata->CodeWords; | |
| 2070 | uint32_t epilogScopes = xdata->EpilogCount; | |
| 2071 | if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) { | |
| 2072 | // The extension word has got the same layout for both ARM and ARM64 | |
| 2073 | uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1]; | |
| 2074 | codeWords = (extensionWord >> 16) & 0xff; | |
| 2075 | epilogScopes = extensionWord & 0xffff; | |
| 2076 | offset++; | |
| 2077 | } | |
| 2078 | if (!xdata->EpilogInHeader) | |
| 2079 | offset += epilogScopes; | |
| 2080 | offset += codeWords; | |
| 2081 | uint32_t *exceptionHandlerInfo = | |
| 2082 | reinterpret_cast<uint32_t *>(xdata) + offset; | |
| 2083 | _dispContext.HandlerData = &exceptionHandlerInfo[1]; | |
| 2084 | _dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>( | |
| 2085 | base + exceptionHandlerInfo[0]); | |
| 2086 | _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData); | |
| 2087 | if (exceptionHandlerInfo[0]) | |
| 2088 | _info.handler = | |
| 2089 | reinterpret_cast<unw_word_t>(__libunwind_seh_personality); | |
| 2090 | else | |
| 2091 | _info.handler = 0; | |
| 2092 | } else { | |
| 2093 | _info.lsda = 0; | |
| 2094 | _info.handler = 0; | |
| 2095 | } | |
| 2096 | } | |
| 2097 | } | |
| 2016 | 2098 | #endif |
| 2017 | 2099 | setLastPC(pc); |
| 2018 | 2100 | return true; |
| ... | ... | @@ -2554,7 +2636,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
| 2554 | 2636 | template <typename A, typename R> |
| 2555 | 2637 | void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2556 | 2638 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ |
| 2557 | defined(_LIBUNWIND_TARGET_HAIKU) | |
| 2639 | defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) | |
| 2558 | 2640 | _isSigReturn = false; |
| 2559 | 2641 | #endif |
| 2560 | 2642 | |
| ... | ... | @@ -2679,7 +2761,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2679 | 2761 | #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 2680 | 2762 | |
| 2681 | 2763 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ |
| 2682 | defined(_LIBUNWIND_TARGET_HAIKU) | |
| 2764 | defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) | |
| 2683 | 2765 | if (setInfoForSigReturn()) |
| 2684 | 2766 | return; |
| 2685 | 2767 | #endif |
| ... | ... | @@ -2755,65 +2837,63 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) { |
| 2755 | 2837 | _isSignalFrame = true; |
| 2756 | 2838 | return UNW_STEP_SUCCESS; |
| 2757 | 2839 | } |
| 2840 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && | |
| 2841 | // defined(_LIBUNWIND_TARGET_AARCH64) | |
| 2758 | 2842 | |
| 2759 | #elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) | |
| 2760 | #include <commpage_defs.h> | |
| 2761 | #include <signal.h> | |
| 2843 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ | |
| 2844 | defined(_LIBUNWIND_TARGET_LOONGARCH) | |
| 2845 | template <typename A, typename R> | |
| 2846 | bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_loongarch &) { | |
| 2847 | const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP)); | |
| 2848 | // The PC might contain an invalid address if the unwind info is bad, so | |
| 2849 | // directly accessing it could cause a SIGSEGV. | |
| 2850 | if (!isReadableAddr(pc)) | |
| 2851 | return false; | |
| 2852 | const auto *instructions = reinterpret_cast<const uint32_t *>(pc); | |
| 2853 | // Look for the two instructions used in the sigreturn trampoline | |
| 2854 | // __vdso_rt_sigreturn: | |
| 2855 | // | |
| 2856 | // 0x03822c0b li a7,0x8b | |
| 2857 | // 0x002b0000 syscall 0 | |
| 2858 | if (instructions[0] != 0x03822c0b || instructions[1] != 0x002b0000) | |
| 2859 | return false; | |
| 2762 | 2860 | |
| 2763 | extern "C" { | |
| 2764 | extern void *__gCommPageAddress; | |
| 2861 | _info = {}; | |
| 2862 | _info.start_ip = pc; | |
| 2863 | _info.end_ip = pc + 4; | |
| 2864 | _isSigReturn = true; | |
| 2865 | return true; | |
| 2765 | 2866 | } |
| 2766 | 2867 | |
| 2767 | 2868 | template <typename A, typename R> |
| 2768 | bool UnwindCursor<A, R>::setInfoForSigReturn() { | |
| 2769 | #if defined(_LIBUNWIND_TARGET_X86_64) | |
| 2770 | addr_t signal_handler = | |
| 2771 | (((addr_t *)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] + | |
| 2772 | (addr_t)__gCommPageAddress); | |
| 2773 | addr_t signal_handler_ret = signal_handler + 45; | |
| 2774 | #endif | |
| 2775 | pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); | |
| 2776 | if (pc == signal_handler_ret) { | |
| 2777 | _info = {}; | |
| 2778 | _info.start_ip = signal_handler; | |
| 2779 | _info.end_ip = signal_handler_ret; | |
| 2780 | _isSigReturn = true; | |
| 2781 | return true; | |
| 2782 | } | |
| 2783 | return false; | |
| 2784 | } | |
| 2869 | int UnwindCursor<A, R>::stepThroughSigReturn(Registers_loongarch &) { | |
| 2870 | // In the signal trampoline frame, sp points to an rt_sigframe[1], which is: | |
| 2871 | // - 128-byte siginfo struct | |
| 2872 | // - ucontext_t struct: | |
| 2873 | // - 8-byte long (__uc_flags) | |
| 2874 | // - 8-byte pointer (*uc_link) | |
| 2875 | // - 24-byte uc_stack | |
| 2876 | // - 8-byte uc_sigmask | |
| 2877 | // - 120-byte of padding to allow sigset_t to be expanded in the future | |
| 2878 | // - 8 bytes of padding because sigcontext has 16-byte alignment | |
| 2879 | // - struct sigcontext uc_mcontext | |
| 2880 | // [1] | |
| 2881 | // https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c | |
| 2882 | const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128; | |
| 2785 | 2883 | |
| 2786 | template <typename A, typename R> | |
| 2787 | int UnwindCursor<A, R>::stepThroughSigReturn() { | |
| 2884 | const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext; | |
| 2885 | _registers.setIP(_addressSpace.get64(sigctx)); | |
| 2886 | for (int i = UNW_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) { | |
| 2887 | // skip R0 | |
| 2888 | uint64_t value = | |
| 2889 | _addressSpace.get64(sigctx + static_cast<pint_t>((i + 1) * 8)); | |
| 2890 | _registers.setRegister(i, value); | |
| 2891 | } | |
| 2788 | 2892 | _isSignalFrame = true; |
| 2789 | pint_t sp = _registers.getSP(); | |
| 2790 | #if defined(_LIBUNWIND_TARGET_X86_64) | |
| 2791 | vregs *regs = (vregs *)(sp + 0x70); | |
| 2792 | ||
| 2793 | _registers.setRegister(UNW_REG_IP, regs->rip); | |
| 2794 | _registers.setRegister(UNW_REG_SP, regs->rsp); | |
| 2795 | _registers.setRegister(UNW_X86_64_RAX, regs->rax); | |
| 2796 | _registers.setRegister(UNW_X86_64_RDX, regs->rdx); | |
| 2797 | _registers.setRegister(UNW_X86_64_RCX, regs->rcx); | |
| 2798 | _registers.setRegister(UNW_X86_64_RBX, regs->rbx); | |
| 2799 | _registers.setRegister(UNW_X86_64_RSI, regs->rsi); | |
| 2800 | _registers.setRegister(UNW_X86_64_RDI, regs->rdi); | |
| 2801 | _registers.setRegister(UNW_X86_64_RBP, regs->rbp); | |
| 2802 | _registers.setRegister(UNW_X86_64_R8, regs->r8); | |
| 2803 | _registers.setRegister(UNW_X86_64_R9, regs->r9); | |
| 2804 | _registers.setRegister(UNW_X86_64_R10, regs->r10); | |
| 2805 | _registers.setRegister(UNW_X86_64_R11, regs->r11); | |
| 2806 | _registers.setRegister(UNW_X86_64_R12, regs->r12); | |
| 2807 | _registers.setRegister(UNW_X86_64_R13, regs->r13); | |
| 2808 | _registers.setRegister(UNW_X86_64_R14, regs->r14); | |
| 2809 | _registers.setRegister(UNW_X86_64_R15, regs->r15); | |
| 2810 | // TODO: XMM | |
| 2811 | #endif | |
| 2812 | ||
| 2813 | 2893 | return UNW_STEP_SUCCESS; |
| 2814 | 2894 | } |
| 2815 | 2895 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && |
| 2816 | // defined(_LIBUNWIND_TARGET_AARCH64) | |
| 2896 | // defined(_LIBUNWIND_TARGET_LOONGARCH) | |
| 2817 | 2897 | |
| 2818 | 2898 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ |
| 2819 | 2899 | defined(_LIBUNWIND_TARGET_RISCV) |
| ... | ... | @@ -2972,6 +3052,96 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) { |
| 2972 | 3052 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && |
| 2973 | 3053 | // defined(_LIBUNWIND_TARGET_S390X) |
| 2974 | 3054 | |
| 3055 | #if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) | |
| 3056 | template <typename A, typename R> | |
| 3057 | bool UnwindCursor<A, R>::setInfoForSigReturn() { | |
| 3058 | Dl_info dlinfo; | |
| 3059 | const auto isSignalHandler = [&](pint_t addr) { | |
| 3060 | if (!dladdr(reinterpret_cast<void *>(addr), &dlinfo)) | |
| 3061 | return false; | |
| 3062 | if (strcmp(dlinfo.dli_fname, "commpage")) | |
| 3063 | return false; | |
| 3064 | if (dlinfo.dli_sname == NULL || | |
| 3065 | strcmp(dlinfo.dli_sname, "commpage_signal_handler")) | |
| 3066 | return false; | |
| 3067 | return true; | |
| 3068 | }; | |
| 3069 | ||
| 3070 | pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); | |
| 3071 | if (!isSignalHandler(pc)) | |
| 3072 | return false; | |
| 3073 | ||
| 3074 | pint_t start = reinterpret_cast<pint_t>(dlinfo.dli_saddr); | |
| 3075 | ||
| 3076 | static size_t signalHandlerSize = 0; | |
| 3077 | if (signalHandlerSize == 0) { | |
| 3078 | size_t boundLow = 0; | |
| 3079 | size_t boundHigh = static_cast<size_t>(-1); | |
| 3080 | ||
| 3081 | area_info areaInfo; | |
| 3082 | if (get_area_info(area_for(dlinfo.dli_saddr), &areaInfo) == B_OK) | |
| 3083 | boundHigh = areaInfo.size; | |
| 3084 | ||
| 3085 | while (boundLow < boundHigh) { | |
| 3086 | size_t boundMid = boundLow + ((boundHigh - boundLow) / 2); | |
| 3087 | pint_t test = start + boundMid; | |
| 3088 | if (test >= start && isSignalHandler(test)) | |
| 3089 | boundLow = boundMid + 1; | |
| 3090 | else | |
| 3091 | boundHigh = boundMid; | |
| 3092 | } | |
| 3093 | ||
| 3094 | signalHandlerSize = boundHigh; | |
| 3095 | } | |
| 3096 | ||
| 3097 | _info = {}; | |
| 3098 | _info.start_ip = start; | |
| 3099 | _info.end_ip = start + signalHandlerSize; | |
| 3100 | _isSigReturn = true; | |
| 3101 | ||
| 3102 | return true; | |
| 3103 | } | |
| 3104 | ||
| 3105 | template <typename A, typename R> | |
| 3106 | int UnwindCursor<A, R>::stepThroughSigReturn() { | |
| 3107 | _isSignalFrame = true; | |
| 3108 | ||
| 3109 | #if defined(_LIBUNWIND_TARGET_X86_64) | |
| 3110 | // Layout of the stack before function call: | |
| 3111 | // - signal_frame_data | |
| 3112 | // + siginfo_t (public struct, fairly stable) | |
| 3113 | // + ucontext_t (public struct, fairly stable) | |
| 3114 | // - mcontext_t -> Offset 0x70, this is what we want. | |
| 3115 | // - frame->ip (8 bytes) | |
| 3116 | // - frame->bp (8 bytes). Not written by the kernel, | |
| 3117 | // but the signal handler has a "push %rbp" instruction. | |
| 3118 | pint_t bp = this->getReg(UNW_X86_64_RBP); | |
| 3119 | vregs *regs = (vregs *)(bp + 0x70); | |
| 3120 | ||
| 3121 | _registers.setRegister(UNW_REG_IP, regs->rip); | |
| 3122 | _registers.setRegister(UNW_REG_SP, regs->rsp); | |
| 3123 | _registers.setRegister(UNW_X86_64_RAX, regs->rax); | |
| 3124 | _registers.setRegister(UNW_X86_64_RDX, regs->rdx); | |
| 3125 | _registers.setRegister(UNW_X86_64_RCX, regs->rcx); | |
| 3126 | _registers.setRegister(UNW_X86_64_RBX, regs->rbx); | |
| 3127 | _registers.setRegister(UNW_X86_64_RSI, regs->rsi); | |
| 3128 | _registers.setRegister(UNW_X86_64_RDI, regs->rdi); | |
| 3129 | _registers.setRegister(UNW_X86_64_RBP, regs->rbp); | |
| 3130 | _registers.setRegister(UNW_X86_64_R8, regs->r8); | |
| 3131 | _registers.setRegister(UNW_X86_64_R9, regs->r9); | |
| 3132 | _registers.setRegister(UNW_X86_64_R10, regs->r10); | |
| 3133 | _registers.setRegister(UNW_X86_64_R11, regs->r11); | |
| 3134 | _registers.setRegister(UNW_X86_64_R12, regs->r12); | |
| 3135 | _registers.setRegister(UNW_X86_64_R13, regs->r13); | |
| 3136 | _registers.setRegister(UNW_X86_64_R14, regs->r14); | |
| 3137 | _registers.setRegister(UNW_X86_64_R15, regs->r15); | |
| 3138 | // TODO: XMM | |
| 3139 | #endif // defined(_LIBUNWIND_TARGET_X86_64) | |
| 3140 | ||
| 3141 | return UNW_STEP_SUCCESS; | |
| 3142 | } | |
| 3143 | #endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) | |
| 3144 | ||
| 2975 | 3145 | template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { |
| 2976 | 3146 | (void)stage2; |
| 2977 | 3147 | // Bottom of stack is defined is when unwind info cannot be found. |
| ... | ... | @@ -2981,7 +3151,7 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { |
| 2981 | 3151 | // Use unwinding info to modify register set as if function returned. |
| 2982 | 3152 | int result; |
| 2983 | 3153 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ |
| 2984 | defined(_LIBUNWIND_TARGET_HAIKU) | |
| 3154 | defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN) | |
| 2985 | 3155 | if (_isSigReturn) { |
| 2986 | 3156 | result = this->stepThroughSigReturn(); |
| 2987 | 3157 | } else |
| ... | ... | @@ -3062,7 +3232,7 @@ bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const { |
| 3062 | 3232 | #endif |
| 3063 | 3233 | |
| 3064 | 3234 | #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) |
| 3065 | extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { | |
| 3235 | extern "C" void *__libunwind_shstk_get_registers(unw_cursor_t *cursor) { | |
| 3066 | 3236 | AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; |
| 3067 | 3237 | return co->get_registers(); |
| 3068 | 3238 | } |
lib/libunwind/src/UnwindLevel1.c+39-36| ... | ... | @@ -25,10 +25,10 @@ |
| 25 | 25 | #include <stdio.h> |
| 26 | 26 | #include <string.h> |
| 27 | 27 | |
| 28 | #include "cet_unwind.h" | |
| 29 | 28 | #include "config.h" |
| 30 | 29 | #include "libunwind.h" |
| 31 | 30 | #include "libunwind_ext.h" |
| 31 | #include "shadow_stack_unwind.h" | |
| 32 | 32 | #include "unwind.h" |
| 33 | 33 | |
| 34 | 34 | #if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ |
| ... | ... | @@ -36,14 +36,17 @@ |
| 36 | 36 | |
| 37 | 37 | #ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND |
| 38 | 38 | |
| 39 | // When CET is enabled, each "call" instruction will push return address to | |
| 40 | // CET shadow stack, each "ret" instruction will pop current CET shadow stack | |
| 41 | // top and compare it with target address which program will return. | |
| 42 | // In exception handing, some stack frames will be skipped before jumping to | |
| 43 | // landing pad and we must adjust CET shadow stack accordingly. | |
| 44 | // _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we | |
| 45 | // directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using | |
| 46 | // a regular function call to avoid pushing to CET shadow stack again. | |
| 39 | // When shadow stack is enabled, a separate stack containing only return | |
| 40 | // addresses would be maintained. On function return, the return address would | |
| 41 | // be compared to the popped address from shadow stack to ensure the return | |
| 42 | // target is not tempered with. When unwinding, we're skipping the normal return | |
| 43 | // procedure for multiple frames and thus need to pop the return addresses of | |
| 44 | // the skipped frames from shadow stack to avoid triggering an exception (using | |
| 45 | // `_LIBUNWIND_POP_SHSTK_SSP()`). Also, some architectures, like the x86-family | |
| 46 | // CET, push the return adddresses onto shadow stack with common call | |
| 47 | // instructions, so for these architectures, normal function calls should be | |
| 48 | // avoided when invoking the `jumpto()` function. To do this, we use inline | |
| 49 | // assemblies to "goto" the `jumpto()` for these architectures. | |
| 47 | 50 | #if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS) |
| 48 | 51 | #define __unw_phase2_resume(cursor, fn) \ |
| 49 | 52 | do { \ |
| ... | ... | @@ -51,38 +54,38 @@ |
| 51 | 54 | __unw_resume((cursor)); \ |
| 52 | 55 | } while (0) |
| 53 | 56 | #elif defined(_LIBUNWIND_TARGET_I386) |
| 54 | #define __cet_ss_step_size 4 | |
| 57 | #define __shstk_step_size (4) | |
| 55 | 58 | #define __unw_phase2_resume(cursor, fn) \ |
| 56 | 59 | do { \ |
| 57 | _LIBUNWIND_POP_CET_SSP((fn)); \ | |
| 58 | void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ | |
| 59 | void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ | |
| 60 | _LIBUNWIND_POP_SHSTK_SSP((fn)); \ | |
| 61 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ | |
| 62 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ | |
| 60 | 63 | __asm__ volatile("push %%edi\n\t" \ |
| 61 | 64 | "sub $4, %%esp\n\t" \ |
| 62 | "jmp *%%edx\n\t" :: "D"(cetRegContext), \ | |
| 63 | "d"(cetJumpAddress)); \ | |
| 65 | "jmp *%%edx\n\t" ::"D"(shstkRegContext), \ | |
| 66 | "d"(shstkJumpAddress)); \ | |
| 64 | 67 | } while (0) |
| 65 | 68 | #elif defined(_LIBUNWIND_TARGET_X86_64) |
| 66 | #define __cet_ss_step_size 8 | |
| 69 | #define __shstk_step_size (8) | |
| 67 | 70 | #define __unw_phase2_resume(cursor, fn) \ |
| 68 | 71 | do { \ |
| 69 | _LIBUNWIND_POP_CET_SSP((fn)); \ | |
| 70 | void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ | |
| 71 | void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ | |
| 72 | __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \ | |
| 73 | "d"(cetJumpAddress)); \ | |
| 72 | _LIBUNWIND_POP_SHSTK_SSP((fn)); \ | |
| 73 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ | |
| 74 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ | |
| 75 | __asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \ | |
| 76 | "d"(shstkJumpAddress)); \ | |
| 74 | 77 | } while (0) |
| 75 | 78 | #elif defined(_LIBUNWIND_TARGET_AARCH64) |
| 76 | #define __cet_ss_step_size 8 | |
| 79 | #define __shstk_step_size (8) | |
| 77 | 80 | #define __unw_phase2_resume(cursor, fn) \ |
| 78 | 81 | do { \ |
| 79 | _LIBUNWIND_POP_CET_SSP((fn)); \ | |
| 80 | void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ | |
| 81 | void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ | |
| 82 | _LIBUNWIND_POP_SHSTK_SSP((fn)); \ | |
| 83 | void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \ | |
| 84 | void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \ | |
| 82 | 85 | __asm__ volatile("mov x0, %0\n\t" \ |
| 83 | 86 | "br %1\n\t" \ |
| 84 | 87 | : \ |
| 85 | : "r"(cetRegContext), "r"(cetJumpAddress) \ | |
| 88 | : "r"(shstkRegContext), "r"(shstkJumpAddress) \ | |
| 86 | 89 | : "x0"); \ |
| 87 | 90 | } while (0) |
| 88 | 91 | #endif |
| ... | ... | @@ -185,10 +188,11 @@ extern int __unw_step_stage2(unw_cursor_t *); |
| 185 | 188 | |
| 186 | 189 | #if defined(_LIBUNWIND_USE_GCS) |
| 187 | 190 | // Enable the GCS target feature to permit gcspop instructions to be used. |
| 188 | __attribute__((target("gcs"))) | |
| 191 | __attribute__((target("+gcs"))) | |
| 189 | 192 | #endif |
| 190 | 193 | static _Unwind_Reason_Code |
| 191 | unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { | |
| 194 | unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, | |
| 195 | _Unwind_Exception *exception_object) { | |
| 192 | 196 | __unw_init_local(cursor, uc); |
| 193 | 197 | |
| 194 | 198 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)", |
| ... | ... | @@ -255,16 +259,16 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 255 | 259 | } |
| 256 | 260 | #endif |
| 257 | 261 | |
| 258 | // In CET enabled environment, we check return address stored in normal stack | |
| 259 | // against return address stored in CET shadow stack, if the 2 addresses don't | |
| 262 | // In shadow stack enabled environment, we check return address stored in normal | |
| 263 | // stack against return address stored in shadow stack, if the 2 addresses don't | |
| 260 | 264 | // match, it means return address in normal stack has been corrupted, we return |
| 261 | 265 | // _URC_FATAL_PHASE2_ERROR. |
| 262 | 266 | #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS) |
| 263 | 267 | if (shadowStackTop != 0) { |
| 264 | 268 | unw_word_t retInNormalStack; |
| 265 | 269 | __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack); |
| 266 | unsigned long retInShadowStack = *( | |
| 267 | unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked); | |
| 270 | unsigned long retInShadowStack = | |
| 271 | *(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked); | |
| 268 | 272 | if (retInNormalStack != retInShadowStack) |
| 269 | 273 | return _URC_FATAL_PHASE2_ERROR; |
| 270 | 274 | } |
| ... | ... | @@ -329,12 +333,12 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 329 | 333 | |
| 330 | 334 | #if defined(_LIBUNWIND_USE_GCS) |
| 331 | 335 | // Enable the GCS target feature to permit gcspop instructions to be used. |
| 332 | __attribute__((target("gcs"))) | |
| 336 | __attribute__((target("+gcs"))) | |
| 333 | 337 | #endif |
| 334 | 338 | static _Unwind_Reason_Code |
| 335 | 339 | unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 336 | _Unwind_Exception *exception_object, | |
| 337 | _Unwind_Stop_Fn stop, void *stop_parameter) { | |
| 340 | _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, | |
| 341 | void *stop_parameter) { | |
| 338 | 342 | __unw_init_local(cursor, uc); |
| 339 | 343 | |
| 340 | 344 | // uc is initialized by __unw_getcontext in the parent frame. The first stack |
| ... | ... | @@ -440,7 +444,6 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 440 | 444 | return _URC_FATAL_PHASE2_ERROR; |
| 441 | 445 | } |
| 442 | 446 | |
| 443 | ||
| 444 | 447 | /// Called by __cxa_throw. Only returns if there is a fatal error. |
| 445 | 448 | _LIBUNWIND_EXPORT _Unwind_Reason_Code |
| 446 | 449 | _Unwind_RaiseException(_Unwind_Exception *exception_object) { |
lib/libunwind/src/UnwindRegistersRestore.S+1-1| ... | ... | @@ -66,7 +66,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) |
| 66 | 66 | # skip fs |
| 67 | 67 | # skip gs |
| 68 | 68 | |
| 69 | #elif defined(__x86_64__) | |
| 69 | #elif defined(__x86_64__) && !defined(__arm64ec__) | |
| 70 | 70 | |
| 71 | 71 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) |
| 72 | 72 | # |
lib/libunwind/src/UnwindRegistersSave.S+49| ... | ... | @@ -65,6 +65,47 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 65 | 65 | xorl %eax, %eax # return UNW_ESUCCESS |
| 66 | 66 | ret |
| 67 | 67 | |
| 68 | #elif defined(__arm64ec__) | |
| 69 | ||
| 70 | // | |
| 71 | // extern int __unw_getcontext(unw_context_t* thread_state) | |
| 72 | // | |
| 73 | // On entry: | |
| 74 | // thread_state pointer is in x0 | |
| 75 | // | |
| 76 | .section .text,"xr",discard,"#__unw_getcontext" | |
| 77 | .p2align 2 | |
| 78 | DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext") | |
| 79 | stp x8, x27, [x0, #0x000] // rax, rbx | |
| 80 | stp x0, x1, [x0, #0x010] // rcx, rdx | |
| 81 | stp x26,x25, [x0, #0x020] // rdi, rsi | |
| 82 | mov x1, sp | |
| 83 | stp fp, x1, [x0, #0x030] // rbp, rsp | |
| 84 | stp x2, x3, [x0, #0x040] // r8, r9 | |
| 85 | stp x4, x5, [x0, #0x050] // r10, r11 | |
| 86 | stp x19,x20, [x0, #0x060] // r12, r13 | |
| 87 | stp x21,x22, [x0, #0x070] // r14, r15 | |
| 88 | str x30, [x0, #0x080] // store return address as pc | |
| 89 | stp q0, q1, [x0, #0x0b0] // xmm0, xmm1 | |
| 90 | stp q2, q3, [x0, #0x0d0] // xmm2, xmm3 | |
| 91 | stp q4, q5, [x0, #0x0f0] // xmm4, xmm5 | |
| 92 | stp q6, q7, [x0, #0x110] // xmm6, xmm7 | |
| 93 | stp q8, q9, [x0, #0x130] // xmm8, xmm9 | |
| 94 | stp q10,q11, [x0, #0x150] // xmm10,xmm11 | |
| 95 | stp q12,q13, [x0, #0x170] // xmm12,xmm13 | |
| 96 | stp q14,q15, [x0, #0x190] // xmm14,xmm15 | |
| 97 | mov x0, #0 // return UNW_ESUCCESS | |
| 98 | ret | |
| 99 | ||
| 100 | .weak_anti_dep __unw_getcontext | |
| 101 | .set __unw_getcontext, "#__unw_getcontext" | |
| 102 | ||
| 103 | .section .hybmp$x,"yi" | |
| 104 | .symidx "#__unw_getcontext" | |
| 105 | .symidx $ientry_thunk$cdecl$i8$i8 | |
| 106 | .word 1 | |
| 107 | .text | |
| 108 | ||
| 68 | 109 | #elif defined(__x86_64__) |
| 69 | 110 | |
| 70 | 111 | # |
| ... | ... | @@ -1181,7 +1222,15 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1181 | 1222 | |
| 1182 | 1223 | #endif |
| 1183 | 1224 | |
| 1225 | #ifdef __arm64ec__ | |
| 1226 | .globl "#unw_getcontext" | |
| 1227 | .set "#unw_getcontext", "#__unw_getcontext" | |
| 1228 | .weak_anti_dep unw_getcontext | |
| 1229 | .set unw_getcontext, "#unw_getcontext" | |
| 1230 | EXPORT_SYMBOL(unw_getcontext) | |
| 1231 | #else | |
| 1184 | 1232 | WEAK_ALIAS(__unw_getcontext, unw_getcontext) |
| 1233 | #endif | |
| 1185 | 1234 | |
| 1186 | 1235 | #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */ |
| 1187 | 1236 |
lib/libunwind/src/cet_unwind.h deleted-63| ... | ... | @@ -1,63 +0,0 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef LIBUNWIND_CET_UNWIND_H | |
| 11 | #define LIBUNWIND_CET_UNWIND_H | |
| 12 | ||
| 13 | #include "libunwind.h" | |
| 14 | ||
| 15 | // Currently, CET is implemented on Linux x86 platforms. | |
| 16 | #if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__) | |
| 17 | #define _LIBUNWIND_USE_CET 1 | |
| 18 | #endif | |
| 19 | ||
| 20 | #if defined(_LIBUNWIND_USE_CET) | |
| 21 | #include <cet.h> | |
| 22 | #include <immintrin.h> | |
| 23 | ||
| 24 | #define _LIBUNWIND_POP_CET_SSP(x) \ | |
| 25 | do { \ | |
| 26 | unsigned long ssp = _get_ssp(); \ | |
| 27 | if (ssp != 0) { \ | |
| 28 | unsigned int tmp = (x); \ | |
| 29 | while (tmp > 255) { \ | |
| 30 | _inc_ssp(255); \ | |
| 31 | tmp -= 255; \ | |
| 32 | } \ | |
| 33 | _inc_ssp(tmp); \ | |
| 34 | } \ | |
| 35 | } while (0) | |
| 36 | #endif | |
| 37 | ||
| 38 | // On AArch64 we use _LIBUNWIND_USE_GCS to indicate that GCS is supported. We | |
| 39 | // need to guard any use of GCS instructions with __chkfeat though, as GCS may | |
| 40 | // not be enabled. | |
| 41 | #if defined(_LIBUNWIND_TARGET_AARCH64) && defined(__ARM_FEATURE_GCS_DEFAULT) | |
| 42 | #include <arm_acle.h> | |
| 43 | ||
| 44 | // We can only use GCS if arm_acle.h defines the GCS intrinsics. | |
| 45 | #ifdef _CHKFEAT_GCS | |
| 46 | #define _LIBUNWIND_USE_GCS 1 | |
| 47 | #endif | |
| 48 | ||
| 49 | #define _LIBUNWIND_POP_CET_SSP(x) \ | |
| 50 | do { \ | |
| 51 | if (__chkfeat(_CHKFEAT_GCS)) { \ | |
| 52 | unsigned tmp = (x); \ | |
| 53 | while (tmp--) \ | |
| 54 | __gcspopm(); \ | |
| 55 | } \ | |
| 56 | } while (0) | |
| 57 | ||
| 58 | #endif | |
| 59 | ||
| 60 | extern void *__libunwind_cet_get_registers(unw_cursor_t *); | |
| 61 | extern void *__libunwind_cet_get_jump_target(void); | |
| 62 | ||
| 63 | #endif |
lib/libunwind/src/gcc_personality_v0.c+2| ... | ... | @@ -6,6 +6,7 @@ |
| 6 | 6 | // |
| 7 | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | |
| 9 | /* zig patch: remove compiler-rt int_lib.h dependency */ | |
| 9 | 10 | #if __ARM_EABI__ |
| 10 | 11 | #ifdef COMPILER_RT_ARMHF_TARGET |
| 11 | 12 | #define COMPILER_RT_ABI |
| ... | ... | @@ -19,6 +20,7 @@ |
| 19 | 20 | #define compilerrt_abort() __builtin_unreachable() |
| 20 | 21 | |
| 21 | 22 | #include <unwind.h> |
| 23 | /* zig patch: remove unwind-ehabi-helpers.h dependency */ | |
| 22 | 24 | |
| 23 | 25 | #if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) |
| 24 | 26 | #include <windows.h> |
lib/libunwind/src/shadow_stack_unwind.h created+63| ... | ... | @@ -0,0 +1,63 @@ |
| 1 | //===----------------------------------------------------------------------===// | |
| 2 | // | |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| 4 | // See https://llvm.org/LICENSE.txt for license information. | |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| 6 | // | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef LIBUNWIND_SHADOW_STACK_UNWIND_H | |
| 11 | #define LIBUNWIND_SHADOW_STACK_UNWIND_H | |
| 12 | ||
| 13 | #include "libunwind.h" | |
| 14 | ||
| 15 | // Currently, CET is implemented on Linux x86 platforms. | |
| 16 | #if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__) | |
| 17 | #define _LIBUNWIND_USE_CET 1 | |
| 18 | #endif | |
| 19 | ||
| 20 | #if defined(_LIBUNWIND_USE_CET) | |
| 21 | #include <cet.h> | |
| 22 | #include <immintrin.h> | |
| 23 | ||
| 24 | #define _LIBUNWIND_POP_SHSTK_SSP(x) \ | |
| 25 | do { \ | |
| 26 | unsigned long ssp = _get_ssp(); \ | |
| 27 | if (ssp != 0) { \ | |
| 28 | unsigned int tmp = (x); \ | |
| 29 | while (tmp > 255) { \ | |
| 30 | _inc_ssp(255); \ | |
| 31 | tmp -= 255; \ | |
| 32 | } \ | |
| 33 | _inc_ssp(tmp); \ | |
| 34 | } \ | |
| 35 | } while (0) | |
| 36 | #endif | |
| 37 | ||
| 38 | // On AArch64 we use _LIBUNWIND_USE_GCS to indicate that GCS is supported. We | |
| 39 | // need to guard any use of GCS instructions with __chkfeat though, as GCS may | |
| 40 | // not be enabled. | |
| 41 | #if defined(_LIBUNWIND_TARGET_AARCH64) && defined(__ARM_FEATURE_GCS_DEFAULT) | |
| 42 | #include <arm_acle.h> | |
| 43 | ||
| 44 | // We can only use GCS if arm_acle.h defines the GCS intrinsics. | |
| 45 | #ifdef _CHKFEAT_GCS | |
| 46 | #define _LIBUNWIND_USE_GCS 1 | |
| 47 | #endif | |
| 48 | ||
| 49 | #define _LIBUNWIND_POP_SHSTK_SSP(x) \ | |
| 50 | do { \ | |
| 51 | if (__chkfeat(_CHKFEAT_GCS)) { \ | |
| 52 | unsigned tmp = (x); \ | |
| 53 | while (tmp--) \ | |
| 54 | __gcspopm(); \ | |
| 55 | } \ | |
| 56 | } while (0) | |
| 57 | ||
| 58 | #endif | |
| 59 | ||
| 60 | extern void *__libunwind_shstk_get_registers(unw_cursor_t *); | |
| 61 | extern void *__libunwind_shstk_get_jump_target(void); | |
| 62 | ||
| 63 | #endif |