| author | |
| committer | |
| log | a89b3432563c20b344bdf3f5ec686021e7de5e23 |
| tree | 12b67346724f57624e181955c067ffe0572ee5c0 |
| parent | ce754724b31e141688e1203ba7bb0a2538f2b544 |
| signature |
7 files changed, 201 insertions(+), 79 deletions(-)
lib/libunwind/src/DwarfInstructions.hpp+47-12| ... | ... | @@ -74,8 +74,10 @@ private: |
| 74 | 74 | __builtin_unreachable(); |
| 75 | 75 | } |
| 76 | 76 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 77 | static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa, | |
| 78 | PrologInfo &prolog); | |
| 77 | static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa, | |
| 78 | PrologInfo &prolog); | |
| 79 | static bool isReturnAddressSignedWithPC(A &addressSpace, R registers, | |
| 80 | pint_t cfa, PrologInfo &prolog); | |
| 79 | 81 | #endif |
| 80 | 82 | }; |
| 81 | 83 | |
| ... | ... | @@ -173,8 +175,9 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( |
| 173 | 175 | } |
| 174 | 176 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 175 | 177 | template <typename A, typename R> |
| 176 | bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers, | |
| 177 | pint_t cfa, PrologInfo &prolog) { | |
| 178 | bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace, | |
| 179 | R registers, pint_t cfa, | |
| 180 | PrologInfo &prolog) { | |
| 178 | 181 | pint_t raSignState; |
| 179 | 182 | auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; |
| 180 | 183 | if (regloc.location == CFI_Parser<A>::kRegisterUnused) |
| ... | ... | @@ -185,6 +188,22 @@ bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers, |
| 185 | 188 | // Only bit[0] is meaningful. |
| 186 | 189 | return raSignState & 0x01; |
| 187 | 190 | } |
| 191 | ||
| 192 | template <typename A, typename R> | |
| 193 | bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace, | |
| 194 | R registers, | |
| 195 | pint_t cfa, | |
| 196 | PrologInfo &prolog) { | |
| 197 | pint_t raSignState; | |
| 198 | auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE]; | |
| 199 | if (regloc.location == CFI_Parser<A>::kRegisterUnused) | |
| 200 | raSignState = static_cast<pint_t>(regloc.value); | |
| 201 | else | |
| 202 | raSignState = getSavedRegister(addressSpace, registers, cfa, regloc); | |
| 203 | ||
| 204 | // Only bit[1] is meaningful. | |
| 205 | return raSignState & 0x02; | |
| 206 | } | |
| 188 | 207 | #endif |
| 189 | 208 | |
| 190 | 209 | template <typename A, typename R> |
| ... | ... | @@ -288,7 +307,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 288 | 307 | // restored. autia1716 is used instead of autia as autia1716 assembles |
| 289 | 308 | // to a NOP on pre-v8.3a architectures. |
| 290 | 309 | if ((R::getArch() == REGISTERS_ARM64) && |
| 291 | getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) && | |
| 310 | isReturnAddressSigned(addressSpace, registers, cfa, prolog) && | |
| 292 | 311 | returnAddress != 0) { |
| 293 | 312 | #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) |
| 294 | 313 | return UNW_ECROSSRASIGNING; |
| ... | ... | @@ -296,13 +315,29 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 296 | 315 | register unsigned long long x17 __asm("x17") = returnAddress; |
| 297 | 316 | register unsigned long long x16 __asm("x16") = cfa; |
| 298 | 317 | |
| 299 | // These are the autia1716/autib1716 instructions. The hint instructions | |
| 300 | // are used here as gcc does not assemble autia1716/autib1716 for pre | |
| 301 | // armv8.3a targets. | |
| 302 | if (cieInfo.addressesSignedWithBKey) | |
| 303 | asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 | |
| 304 | else | |
| 305 | asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 | |
| 318 | // We use the hint versions of the authentication instructions below to | |
| 319 | // ensure they're assembled by the compiler even for targets with no | |
| 320 | // FEAT_PAuth/FEAT_PAuth_LR support. | |
| 321 | if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) { | |
| 322 | register unsigned long long x15 __asm("x15") = | |
| 323 | prolog.ptrAuthDiversifier; | |
| 324 | if (cieInfo.addressesSignedWithBKey) { | |
| 325 | asm("hint 0x27\n\t" // pacm | |
| 326 | "hint 0xe" | |
| 327 | : "+r"(x17) | |
| 328 | : "r"(x16), "r"(x15)); // autib1716 | |
| 329 | } else { | |
| 330 | asm("hint 0x27\n\t" // pacm | |
| 331 | "hint 0xc" | |
| 332 | : "+r"(x17) | |
| 333 | : "r"(x16), "r"(x15)); // autia1716 | |
| 334 | } | |
| 335 | } else { | |
| 336 | if (cieInfo.addressesSignedWithBKey) | |
| 337 | asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716 | |
| 338 | else | |
| 339 | asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716 | |
| 340 | } | |
| 306 | 341 | returnAddress = x17; |
| 307 | 342 | #endif |
| 308 | 343 | } |
lib/libunwind/src/DwarfParser.hpp+21| ... | ... | @@ -91,6 +91,9 @@ public: |
| 91 | 91 | int64_t cfaExpression; // CFA = expression |
| 92 | 92 | uint32_t spExtraArgSize; |
| 93 | 93 | RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; |
| 94 | #if defined(_LIBUNWIND_TARGET_AARCH64) | |
| 95 | pint_t ptrAuthDiversifier; | |
| 96 | #endif | |
| 94 | 97 | enum class InitializeTime { kLazy, kNormal }; |
| 95 | 98 | |
| 96 | 99 | // When saving registers, this data structure is lazily initialized. |
| ... | ... | @@ -799,6 +802,24 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 799 | 802 | } |
| 800 | 803 | break; |
| 801 | 804 | |
| 805 | #if defined(_LIBUNWIND_TARGET_AARCH64) | |
| 806 | case DW_CFA_AARCH64_negate_ra_state_with_pc: { | |
| 807 | int64_t value = | |
| 808 | results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x3; | |
| 809 | results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, | |
| 810 | initialState); | |
| 811 | // When calculating the value of the PC, it is assumed that the CFI | |
| 812 | // instruction is placed before the signing instruction, however it is | |
| 813 | // placed after. Because of this, we need to take into account the CFI | |
| 814 | // instruction is one instruction call later than expected, and reduce | |
| 815 | // the PC value by 4 bytes to compensate. | |
| 816 | results->ptrAuthDiversifier = fdeInfo.pcStart + codeOffset - 0x4; | |
| 817 | _LIBUNWIND_TRACE_DWARF( | |
| 818 | "DW_CFA_AARCH64_negate_ra_state_with_pc(pc=0x%" PRIx64 ")\n", | |
| 819 | static_cast<uint64_t>(results->ptrAuthDiversifier)); | |
| 820 | } break; | |
| 821 | #endif | |
| 822 | ||
| 802 | 823 | #else |
| 803 | 824 | (void)arch; |
| 804 | 825 | #endif |
lib/libunwind/src/Unwind-sjlj.c+1-1| ... | ... | @@ -408,7 +408,7 @@ _LIBUNWIND_EXPORT uintptr_t |
| 408 | 408 | _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) { |
| 409 | 409 | _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; |
| 410 | 410 | _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) " |
| 411 | "=> 0x%" PRIuPTR, | |
| 411 | "=> 0x%" PRIxPTR, | |
| 412 | 412 | (void *)context, ufc->lsda); |
| 413 | 413 | return ufc->lsda; |
| 414 | 414 | } |
lib/libunwind/src/UnwindCursor.hpp+91-35| ... | ... | @@ -230,8 +230,8 @@ void DwarfFDECache<A>::iterateCacheEntries(void (*func)( |
| 230 | 230 | } |
| 231 | 231 | #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 232 | 232 | |
| 233 | ||
| 234 | #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) | |
| 233 | #define arrayoffsetof(type, index, field) \ | |
| 234 | (sizeof(type) * (index) + offsetof(type, field)) | |
| 235 | 235 | |
| 236 | 236 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
| 237 | 237 | template <typename A> class UnwindSectionHeader { |
| ... | ... | @@ -1010,6 +1010,9 @@ private: |
| 1010 | 1010 | template <typename Registers> int stepThroughSigReturn(Registers &) { |
| 1011 | 1011 | return UNW_STEP_END; |
| 1012 | 1012 | } |
| 1013 | #elif defined(_LIBUNWIND_TARGET_HAIKU) | |
| 1014 | bool setInfoForSigReturn(); | |
| 1015 | int stepThroughSigReturn(); | |
| 1013 | 1016 | #endif |
| 1014 | 1017 | |
| 1015 | 1018 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| ... | ... | @@ -1313,7 +1316,8 @@ private: |
| 1313 | 1316 | unw_proc_info_t _info; |
| 1314 | 1317 | bool _unwindInfoMissing; |
| 1315 | 1318 | bool _isSignalFrame; |
| 1316 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) | |
| 1319 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ | |
| 1320 | defined(_LIBUNWIND_TARGET_HAIKU) | |
| 1317 | 1321 | bool _isSigReturn = false; |
| 1318 | 1322 | #endif |
| 1319 | 1323 | }; |
| ... | ... | @@ -2033,7 +2037,6 @@ typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action, |
| 2033 | 2037 | uint64_t, |
| 2034 | 2038 | _Unwind_Exception *, |
| 2035 | 2039 | struct _Unwind_Context *); |
| 2036 | __attribute__((__weak__)) __xlcxx_personality_v0_t __xlcxx_personality_v0; | |
| 2037 | 2040 | } |
| 2038 | 2041 | |
| 2039 | 2042 | static __xlcxx_personality_v0_t *xlcPersonalityV0; |
| ... | ... | @@ -2126,42 +2129,35 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) { |
| 2126 | 2129 | // function __xlcxx_personality_v0(), which is the personality for the state |
| 2127 | 2130 | // table and is exported from libc++abi, is directly assigned as the |
| 2128 | 2131 | // handler here. When a legacy XLC++ frame is encountered, the symbol |
| 2129 | // is resolved dynamically using dlopen() to avoid hard dependency from | |
| 2130 | // libunwind on libc++abi. | |
| 2132 | // is resolved dynamically using dlopen() to avoid a hard dependency of | |
| 2133 | // libunwind on libc++abi in cases such as non-C++ applications. | |
| 2131 | 2134 | |
| 2132 | 2135 | // Resolve the function pointer to the state table personality if it has |
| 2133 | // not already. | |
| 2136 | // not already been done. | |
| 2134 | 2137 | if (xlcPersonalityV0 == NULL) { |
| 2135 | 2138 | xlcPersonalityV0InitLock.lock(); |
| 2136 | 2139 | if (xlcPersonalityV0 == NULL) { |
| 2137 | // If libc++abi is statically linked in, symbol __xlcxx_personality_v0 | |
| 2138 | // has been resolved at the link time. | |
| 2139 | xlcPersonalityV0 = &__xlcxx_personality_v0; | |
| 2140 | // Resolve __xlcxx_personality_v0 using dlopen(). | |
| 2141 | const char *libcxxabi = "libc++abi.a(libc++abi.so.1)"; | |
| 2142 | void *libHandle; | |
| 2143 | // The AIX dlopen() sets errno to 0 when it is successful, which | |
| 2144 | // clobbers the value of errno from the user code. This is an AIX | |
| 2145 | // bug because according to POSIX it should not set errno to 0. To | |
| 2146 | // workaround before AIX fixes the bug, errno is saved and restored. | |
| 2147 | int saveErrno = errno; | |
| 2148 | libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW); | |
| 2149 | if (libHandle == NULL) { | |
| 2150 | _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno); | |
| 2151 | assert(0 && "dlopen() failed"); | |
| 2152 | } | |
| 2153 | xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>( | |
| 2154 | dlsym(libHandle, "__xlcxx_personality_v0")); | |
| 2140 | 2155 | if (xlcPersonalityV0 == NULL) { |
| 2141 | // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0 | |
| 2142 | // using dlopen(). | |
| 2143 | const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)"; | |
| 2144 | void *libHandle; | |
| 2145 | // The AIX dlopen() sets errno to 0 when it is successful, which | |
| 2146 | // clobbers the value of errno from the user code. This is an AIX | |
| 2147 | // bug because according to POSIX it should not set errno to 0. To | |
| 2148 | // workaround before AIX fixes the bug, errno is saved and restored. | |
| 2149 | int saveErrno = errno; | |
| 2150 | libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW); | |
| 2151 | if (libHandle == NULL) { | |
| 2152 | _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", | |
| 2153 | errno); | |
| 2154 | assert(0 && "dlopen() failed"); | |
| 2155 | } | |
| 2156 | xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>( | |
| 2157 | dlsym(libHandle, "__xlcxx_personality_v0")); | |
| 2158 | if (xlcPersonalityV0 == NULL) { | |
| 2159 | _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno); | |
| 2160 | assert(0 && "dlsym() failed"); | |
| 2161 | } | |
| 2156 | _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno); | |
| 2162 | 2157 | dlclose(libHandle); |
| 2163 | errno = saveErrno; | |
| 2158 | assert(0 && "dlsym() failed"); | |
| 2164 | 2159 | } |
| 2160 | errno = saveErrno; | |
| 2165 | 2161 | } |
| 2166 | 2162 | xlcPersonalityV0InitLock.unlock(); |
| 2167 | 2163 | } |
| ... | ... | @@ -2557,7 +2553,8 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
| 2557 | 2553 | |
| 2558 | 2554 | template <typename A, typename R> |
| 2559 | 2555 | void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2560 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) | |
| 2556 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ | |
| 2557 | defined(_LIBUNWIND_TARGET_HAIKU) | |
| 2561 | 2558 | _isSigReturn = false; |
| 2562 | 2559 | #endif |
| 2563 | 2560 | |
| ... | ... | @@ -2681,7 +2678,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 2681 | 2678 | } |
| 2682 | 2679 | #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 2683 | 2680 | |
| 2684 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) | |
| 2681 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ | |
| 2682 | defined(_LIBUNWIND_TARGET_HAIKU) | |
| 2685 | 2683 | if (setInfoForSigReturn()) |
| 2686 | 2684 | return; |
| 2687 | 2685 | #endif |
| ... | ... | @@ -2757,6 +2755,63 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) { |
| 2757 | 2755 | _isSignalFrame = true; |
| 2758 | 2756 | return UNW_STEP_SUCCESS; |
| 2759 | 2757 | } |
| 2758 | ||
| 2759 | #elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64) | |
| 2760 | #include <commpage_defs.h> | |
| 2761 | #include <signal.h> | |
| 2762 | ||
| 2763 | extern "C" { | |
| 2764 | extern void *__gCommPageAddress; | |
| 2765 | } | |
| 2766 | ||
| 2767 | 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 | } | |
| 2785 | ||
| 2786 | template <typename A, typename R> | |
| 2787 | int UnwindCursor<A, R>::stepThroughSigReturn() { | |
| 2788 | _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 | return UNW_STEP_SUCCESS; | |
| 2814 | } | |
| 2760 | 2815 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && |
| 2761 | 2816 | // defined(_LIBUNWIND_TARGET_AARCH64) |
| 2762 | 2817 | |
| ... | ... | @@ -2925,7 +2980,8 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { |
| 2925 | 2980 | |
| 2926 | 2981 | // Use unwinding info to modify register set as if function returned. |
| 2927 | 2982 | int result; |
| 2928 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) | |
| 2983 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \ | |
| 2984 | defined(_LIBUNWIND_TARGET_HAIKU) | |
| 2929 | 2985 | if (_isSigReturn) { |
| 2930 | 2986 | result = this->stepThroughSigReturn(); |
| 2931 | 2987 | } else |
lib/libunwind/src/UnwindRegistersRestore.S+6-2| ... | ... | @@ -658,7 +658,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 658 | 658 | ldp x26,x27, [x0, #0x0D0] |
| 659 | 659 | ldp x28,x29, [x0, #0x0E0] |
| 660 | 660 | ldr x30, [x0, #0x100] // restore pc into lr |
| 661 | ||
| 661 | #if defined(__ARM_FP) && __ARM_FP != 0 | |
| 662 | 662 | ldp d0, d1, [x0, #0x110] |
| 663 | 663 | ldp d2, d3, [x0, #0x120] |
| 664 | 664 | ldp d4, d5, [x0, #0x130] |
| ... | ... | @@ -676,7 +676,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 676 | 676 | ldp d28,d29, [x0, #0x1F0] |
| 677 | 677 | ldr d30, [x0, #0x200] |
| 678 | 678 | ldr d31, [x0, #0x208] |
| 679 | ||
| 679 | #endif | |
| 680 | 680 | // Finally, restore sp. This must be done after the last read from the |
| 681 | 681 | // context struct, because it is allocated on the stack, and an exception |
| 682 | 682 | // could clobber the de-allocated portion of the stack after sp has been |
| ... | ... | @@ -1183,7 +1183,11 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) |
| 1183 | 1183 | ILOAD x\i, (RISCV_ISIZE * \i)(a0) |
| 1184 | 1184 | .endr |
| 1185 | 1185 | // skip a0 for now |
| 1186 | #if defined(__riscv_32e) | |
| 1187 | .irp i,11,12,13,14,15 | |
| 1188 | #else | |
| 1186 | 1189 | .irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 |
| 1190 | #endif | |
| 1187 | 1191 | ILOAD x\i, (RISCV_ISIZE * \i)(a0) |
| 1188 | 1192 | .endr |
| 1189 | 1193 | ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0 |
lib/libunwind/src/UnwindRegistersSave.S+6| ... | ... | @@ -746,6 +746,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 746 | 746 | str x1, [x0, #0x0F8] |
| 747 | 747 | str x30, [x0, #0x100] // store return address as pc |
| 748 | 748 | // skip cpsr |
| 749 | #if defined(__ARM_FP) && __ARM_FP != 0 | |
| 749 | 750 | stp d0, d1, [x0, #0x110] |
| 750 | 751 | stp d2, d3, [x0, #0x120] |
| 751 | 752 | stp d4, d5, [x0, #0x130] |
| ... | ... | @@ -763,6 +764,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 763 | 764 | stp d28,d29, [x0, #0x1F0] |
| 764 | 765 | str d30, [x0, #0x200] |
| 765 | 766 | str d31, [x0, #0x208] |
| 767 | #endif | |
| 766 | 768 | mov x0, #0 // return UNW_ESUCCESS |
| 767 | 769 | ret |
| 768 | 770 | |
| ... | ... | @@ -1108,7 +1110,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1108 | 1110 | # |
| 1109 | 1111 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1110 | 1112 | ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc |
| 1113 | #if defined(__riscv_32e) | |
| 1114 | .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | |
| 1115 | #else | |
| 1111 | 1116 | .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 |
| 1117 | #endif | |
| 1112 | 1118 | ISTORE x\i, (RISCV_ISIZE * \i)(a0) |
| 1113 | 1119 | .endr |
| 1114 | 1120 |
lib/libunwind/src/dwarf2.h+29-29| ... | ... | @@ -18,43 +18,43 @@ |
| 18 | 18 | |
| 19 | 19 | // DWARF unwind instructions |
| 20 | 20 | enum { |
| 21 | DW_CFA_nop = 0x0, | |
| 22 | DW_CFA_set_loc = 0x1, | |
| 23 | DW_CFA_advance_loc1 = 0x2, | |
| 24 | DW_CFA_advance_loc2 = 0x3, | |
| 25 | DW_CFA_advance_loc4 = 0x4, | |
| 26 | DW_CFA_offset_extended = 0x5, | |
| 27 | DW_CFA_restore_extended = 0x6, | |
| 28 | DW_CFA_undefined = 0x7, | |
| 29 | DW_CFA_same_value = 0x8, | |
| 30 | DW_CFA_register = 0x9, | |
| 31 | DW_CFA_remember_state = 0xA, | |
| 32 | DW_CFA_restore_state = 0xB, | |
| 33 | DW_CFA_def_cfa = 0xC, | |
| 34 | DW_CFA_def_cfa_register = 0xD, | |
| 35 | DW_CFA_def_cfa_offset = 0xE, | |
| 36 | DW_CFA_def_cfa_expression = 0xF, | |
| 37 | DW_CFA_expression = 0x10, | |
| 21 | DW_CFA_nop = 0x0, | |
| 22 | DW_CFA_set_loc = 0x1, | |
| 23 | DW_CFA_advance_loc1 = 0x2, | |
| 24 | DW_CFA_advance_loc2 = 0x3, | |
| 25 | DW_CFA_advance_loc4 = 0x4, | |
| 26 | DW_CFA_offset_extended = 0x5, | |
| 27 | DW_CFA_restore_extended = 0x6, | |
| 28 | DW_CFA_undefined = 0x7, | |
| 29 | DW_CFA_same_value = 0x8, | |
| 30 | DW_CFA_register = 0x9, | |
| 31 | DW_CFA_remember_state = 0xA, | |
| 32 | DW_CFA_restore_state = 0xB, | |
| 33 | DW_CFA_def_cfa = 0xC, | |
| 34 | DW_CFA_def_cfa_register = 0xD, | |
| 35 | DW_CFA_def_cfa_offset = 0xE, | |
| 36 | DW_CFA_def_cfa_expression = 0xF, | |
| 37 | DW_CFA_expression = 0x10, | |
| 38 | 38 | DW_CFA_offset_extended_sf = 0x11, |
| 39 | DW_CFA_def_cfa_sf = 0x12, | |
| 40 | DW_CFA_def_cfa_offset_sf = 0x13, | |
| 41 | DW_CFA_val_offset = 0x14, | |
| 42 | DW_CFA_val_offset_sf = 0x15, | |
| 43 | DW_CFA_val_expression = 0x16, | |
| 44 | DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta | |
| 45 | DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register | |
| 46 | DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register | |
| 39 | DW_CFA_def_cfa_sf = 0x12, | |
| 40 | DW_CFA_def_cfa_offset_sf = 0x13, | |
| 41 | DW_CFA_val_offset = 0x14, | |
| 42 | DW_CFA_val_offset_sf = 0x15, | |
| 43 | DW_CFA_val_expression = 0x16, | |
| 44 | DW_CFA_advance_loc = 0x40, // high 2 bits are 0x1, lower 6 bits are delta | |
| 45 | DW_CFA_offset = 0x80, // high 2 bits are 0x2, lower 6 bits are register | |
| 46 | DW_CFA_restore = 0xC0, // high 2 bits are 0x3, lower 6 bits are register | |
| 47 | 47 | |
| 48 | 48 | // GNU extensions |
| 49 | DW_CFA_GNU_window_save = 0x2D, | |
| 50 | DW_CFA_GNU_args_size = 0x2E, | |
| 49 | DW_CFA_GNU_window_save = 0x2D, | |
| 50 | DW_CFA_GNU_args_size = 0x2E, | |
| 51 | 51 | DW_CFA_GNU_negative_offset_extended = 0x2F, |
| 52 | 52 | |
| 53 | 53 | // AARCH64 extensions |
| 54 | DW_CFA_AARCH64_negate_ra_state = 0x2D | |
| 54 | DW_CFA_AARCH64_negate_ra_state_with_pc = 0x2C, | |
| 55 | DW_CFA_AARCH64_negate_ra_state = 0x2D | |
| 55 | 56 | }; |
| 56 | 57 | |
| 57 | ||
| 58 | 58 | // FSF exception handling Pointer-Encoding constants |
| 59 | 59 | // Used in CFI augmentation by GCC |
| 60 | 60 | enum { |