diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-07-10 03:06:05 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-10 03:06:05 -0400 |
| commit | b88151e0e1553607cbebc197e1111ec4bf53a595 (patch) | |
| tree | cd4f57feae521500fe4eb99a98a798241256d341 /lib/libunwind/src | |
| parent | 3f11d1d56d9747de974b00eab1c880bea7972c01 (diff) | |
| parent | f9bf4889264aee387639bb8a35fdf594236b1283 (diff) | |
| download | zig-b88151e0e1553607cbebc197e1111ec4bf53a595.tar.gz zig-b88151e0e1553607cbebc197e1111ec4bf53a595.zip | |
Merge pull request #12001 from ziglang/llvm14
Upgrade to LLVM 14
Diffstat (limited to 'lib/libunwind/src')
23 files changed, 699 insertions, 271 deletions
diff --git a/lib/libunwind/src/AddressSpace.hpp b/lib/libunwind/src/AddressSpace.hpp index 171318ff63..0c4dfeb4e6 100644 --- a/lib/libunwind/src/AddressSpace.hpp +++ b/lib/libunwind/src/AddressSpace.hpp @@ -1,4 +1,4 @@ -//===------------------------- AddressSpace.hpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -121,23 +121,23 @@ struct UnwindInfoSections { uintptr_t dso_base; #endif #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) - uintptr_t text_segment_length; + size_t text_segment_length; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) uintptr_t dwarf_section; - uintptr_t dwarf_section_length; + size_t dwarf_section_length; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) uintptr_t dwarf_index_section; - uintptr_t dwarf_index_section_length; + size_t dwarf_index_section_length; #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) uintptr_t compact_unwind_section; - uintptr_t compact_unwind_section_length; + size_t compact_unwind_section_length; #endif #if defined(_LIBUNWIND_ARM_EHABI) uintptr_t arm_section; - uintptr_t arm_section_length; + size_t arm_section_length; #endif }; @@ -430,7 +430,7 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base, // .eh_frame_hdr records the start of .eh_frame, but not its size. // Rely on a zero terminator to find the end of the section. cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; - cbdata->sects->dwarf_section_length = UINTPTR_MAX; + cbdata->sects->dwarf_section_length = SIZE_MAX; return true; } } @@ -506,22 +506,22 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, info.dso_base = (uintptr_t)dyldInfo.mh; #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; - info.dwarf_section_length = dyldInfo.dwarf_section_length; + info.dwarf_section_length = (size_t)dyldInfo.dwarf_section_length; #endif info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; - info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; + info.compact_unwind_section_length = (size_t)dyldInfo.compact_unwind_section_length; return true; } #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) info.dso_base = 0; // Bare metal is statically linked, so no need to ask the dynamic loader - info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); + info.dwarf_section_length = (size_t)(&__eh_frame_end - &__eh_frame_start); info.dwarf_section = (uintptr_t)(&__eh_frame_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", (void *)info.dwarf_section, (void *)info.dwarf_section_length); #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); - info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); + info.dwarf_index_section_length = (size_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); #endif @@ -530,7 +530,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) // Bare metal is statically linked, so no need to ask the dynamic loader info.arm_section = (uintptr_t)(&__exidx_start); - info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); + info.arm_section_length = (size_t)(&__exidx_end - &__exidx_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", (void *)info.arm_section, (void *)info.arm_section_length); if (info.arm_section && info.arm_section_length) @@ -584,7 +584,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, int length = 0; info.arm_section = (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); - info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); + info.arm_section_length = (size_t)length * sizeof(EHABIIndexEntry); if (info.arm_section && info.arm_section_length) return true; #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) diff --git a/lib/libunwind/src/CompactUnwinder.hpp b/lib/libunwind/src/CompactUnwinder.hpp index 1c3175dff5..0b2b5e111b 100644 --- a/lib/libunwind/src/CompactUnwinder.hpp +++ b/lib/libunwind/src/CompactUnwinder.hpp @@ -1,4 +1,4 @@ -//===-------------------------- CompactUnwinder.hpp -----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -537,65 +537,65 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( uint64_t savedRegisterLoc = registers.getSP() + stackSize; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_ARM64_D8, + registers.setFloatRegister(UNW_AARCH64_V8, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D9, + registers.setFloatRegister(UNW_AARCH64_V9, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_ARM64_D10, + registers.setFloatRegister(UNW_AARCH64_V10, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D11, + registers.setFloatRegister(UNW_AARCH64_V11, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_ARM64_D12, + registers.setFloatRegister(UNW_AARCH64_V12, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D13, + registers.setFloatRegister(UNW_AARCH64_V13, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_ARM64_D14, + registers.setFloatRegister(UNW_AARCH64_V14, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D15, + registers.setFloatRegister(UNW_AARCH64_V15, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } @@ -604,7 +604,7 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( registers.setSP(savedRegisterLoc); // set pc to be value in lr - registers.setIP(registers.getRegister(UNW_ARM64_LR)); + registers.setIP(registers.getRegister(UNW_AARCH64_LR)); return UNW_STEP_SUCCESS; } @@ -616,65 +616,65 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( uint64_t savedRegisterLoc = registers.getFP() - 8; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_ARM64_D8, + registers.setFloatRegister(UNW_AARCH64_V8, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D9, + registers.setFloatRegister(UNW_AARCH64_V9, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_ARM64_D10, + registers.setFloatRegister(UNW_AARCH64_V10, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D11, + registers.setFloatRegister(UNW_AARCH64_V11, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_ARM64_D12, + registers.setFloatRegister(UNW_AARCH64_V12, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D13, + registers.setFloatRegister(UNW_AARCH64_V13, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_ARM64_D14, + registers.setFloatRegister(UNW_AARCH64_V14, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D15, + registers.setFloatRegister(UNW_AARCH64_V15, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } diff --git a/lib/libunwind/src/DwarfInstructions.hpp b/lib/libunwind/src/DwarfInstructions.hpp index 60182e4fef..ab83b0c87a 100644 --- a/lib/libunwind/src/DwarfInstructions.hpp +++ b/lib/libunwind/src/DwarfInstructions.hpp @@ -1,4 +1,4 @@ -//===-------------------------- DwarfInstructions.hpp ---------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -67,14 +67,13 @@ private: return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + prolog.cfaRegisterOffset); if (prolog.cfaExpression != 0) - return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, + return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, registers, 0); assert(0 && "getCFA(): unknown location"); __builtin_unreachable(); } }; - template <typename R> auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) { return r.getWCookie(); @@ -92,8 +91,8 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); case CFI_Parser<A>::kRegisterInCFADecrypt: // sparc64 specific - return addressSpace.getP(cfa + (pint_t)savedReg.value) ^ - getSparcWCookie(registers, 0); + return (pint_t)(addressSpace.getP(cfa + (pint_t)savedReg.value) ^ + getSparcWCookie(registers, 0)); case CFI_Parser<A>::kRegisterAtExpression: return (pint_t)addressSpace.getRegister(evaluateExpression( @@ -127,12 +126,15 @@ double DwarfInstructions<A, R>::getSavedFloatRegister( return addressSpace.getDouble( evaluateExpression((pint_t)savedReg.value, addressSpace, registers, cfa)); - + case CFI_Parser<A>::kRegisterUndefined: + return 0.0; + case CFI_Parser<A>::kRegisterInRegister: +#ifndef _LIBUNWIND_TARGET_ARM + return registers.getFloatRegister((int)savedReg.value); +#endif case CFI_Parser<A>::kRegisterIsExpression: case CFI_Parser<A>::kRegisterUnused: - case CFI_Parser<A>::kRegisterUndefined: case CFI_Parser<A>::kRegisterOffsetFromCFA: - case CFI_Parser<A>::kRegisterInRegister: case CFI_Parser<A>::kRegisterInCFADecrypt: // FIX ME break; @@ -233,7 +235,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, // restored. autia1716 is used instead of autia as autia1716 assembles // to a NOP on pre-v8.3a architectures. if ((R::getArch() == REGISTERS_ARM64) && - prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value && + prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value && returnAddress != 0) { #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) return UNW_ECROSSRASIGNING; @@ -253,6 +255,20 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, } #endif +#if defined(_LIBUNWIND_IS_NATIVE_ONLY) && defined(_LIBUNWIND_TARGET_ARM) && \ + defined(__ARM_FEATURE_PAUTH) + if ((R::getArch() == REGISTERS_ARM) && + prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE].value) { + pint_t pac = + getSavedRegister(addressSpace, registers, cfa, + prolog.savedRegisters[UNW_ARM_RA_AUTH_CODE]); + __asm__ __volatile__("autg %0, %1, %2" + : + : "r"(pac), "r"(returnAddress), "r"(cfa) + :); + } +#endif + #if defined(_LIBUNWIND_TARGET_SPARC) if (R::getArch() == REGISTERS_SPARC) { // Skip call site instruction and delay slot @@ -264,7 +280,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, #endif #if defined(_LIBUNWIND_TARGET_SPARC64) - // Skip call site instruction and delay slot + // Skip call site instruction and delay slot. if (R::getArch() == REGISTERS_SPARC64) returnAddress += 8; #endif diff --git a/lib/libunwind/src/DwarfParser.hpp b/lib/libunwind/src/DwarfParser.hpp index f0aa4085d3..b5a53166fc 100644 --- a/lib/libunwind/src/DwarfParser.hpp +++ b/lib/libunwind/src/DwarfParser.hpp @@ -1,4 +1,4 @@ -//===--------------------------- DwarfParser.hpp --------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -152,10 +152,11 @@ public: }; static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uintptr_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, + size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo); static const char *decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo); + FDE_Info *fdeInfo, CIE_Info *cieInfo, + bool useCIEInfo = false); static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo, pint_t upToPC, int arch, PrologInfo *results); @@ -163,10 +164,14 @@ public: static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); }; -/// Parse a FDE into a CIE_Info and an FDE_Info +/// Parse a FDE into a CIE_Info and an FDE_Info. If useCIEInfo is +/// true, treat cieInfo as already-parsed CIE_Info (whose start offset +/// must match the one specified by the FDE) rather than parsing the +/// one indicated within the FDE. template <typename A> const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { + FDE_Info *fdeInfo, CIE_Info *cieInfo, + bool useCIEInfo) { pint_t p = fdeStart; pint_t cfiLength = (pint_t)addressSpace.get32(p); p += 4; @@ -182,9 +187,14 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, return "FDE is really a CIE"; // this is a CIE not an FDE pint_t nextCFI = p + cfiLength; pint_t cieStart = p - ciePointer; - const char *err = parseCIE(addressSpace, cieStart, cieInfo); - if (err != NULL) - return err; + if (useCIEInfo) { + if (cieInfo->cieStart != cieStart) + return "CIE start does not match"; + } else { + const char *err = parseCIE(addressSpace, cieStart, cieInfo); + if (err != NULL) + return err; + } p += 4; // Parse pc begin and range. pint_t pcStart = @@ -221,11 +231,11 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, /// Scan an eh_frame section to find an FDE for a pc template <typename A> bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, - uintptr_t sectionLength, pint_t fdeHint, + size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo) { //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; - const pint_t ehSectionEnd = (sectionLength == UINTPTR_MAX) + const pint_t ehSectionEnd = (sectionLength == SIZE_MAX) ? static_cast<pint_t>(-1) : (ehSectionStart + sectionLength); while (p < ehSectionEnd) { @@ -735,8 +745,8 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, #if defined(_LIBUNWIND_TARGET_AARCH64) case REGISTERS_ARM64: { int64_t value = - results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^ 0x1; - results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value, + results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x1; + results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, initialState); _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); } break; @@ -770,11 +780,13 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, if (reg == UNW_SPARC_I7) results->setRegister( reg, kRegisterInCFADecrypt, - ((int64_t)reg - UNW_SPARC_L0) * sizeof(pint_t), initialState); + static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)), + initialState); else results->setRegister( reg, kRegisterInCFA, - ((int64_t)reg - UNW_SPARC_L0) * sizeof(pint_t), initialState); + static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)), + initialState); } _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n"); break; diff --git a/lib/libunwind/src/EHHeaderParser.hpp b/lib/libunwind/src/EHHeaderParser.hpp index f97cca5482..9a38070fab 100644 --- a/lib/libunwind/src/EHHeaderParser.hpp +++ b/lib/libunwind/src/EHHeaderParser.hpp @@ -1,4 +1,4 @@ -//===------------------------- EHHeaderParser.hpp -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libunwind/src/RWMutex.hpp b/lib/libunwind/src/RWMutex.hpp index fcd3f4967d..344d35641f 100644 --- a/lib/libunwind/src/RWMutex.hpp +++ b/lib/libunwind/src/RWMutex.hpp @@ -1,4 +1,4 @@ -//===----------------------------- Registers.hpp --------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libunwind/src/Registers.hpp b/lib/libunwind/src/Registers.hpp index e37021a7c7..cbc3876d67 100644 --- a/lib/libunwind/src/Registers.hpp +++ b/lib/libunwind/src/Registers.hpp @@ -1,4 +1,4 @@ -//===----------------------------- Registers.hpp --------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,8 +15,9 @@ #include <stdint.h> #include <string.h> -#include "libunwind.h" +#include "cet_unwind.h" #include "config.h" +#include "libunwind.h" namespace libunwind { @@ -43,6 +44,13 @@ enum { #if defined(_LIBUNWIND_TARGET_I386) class _LIBUNWIND_HIDDEN Registers_x86; extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); + +#if defined(_LIBUNWIND_USE_CET) +extern "C" void *__libunwind_cet_get_jump_target() { + return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto); +} +#endif + /// Registers_x86 holds the register state of a thread in a 32-bit intel /// process. class _LIBUNWIND_HIDDEN Registers_x86 { @@ -254,6 +262,13 @@ inline void Registers_x86::setVectorRegister(int, v128) { /// process. class _LIBUNWIND_HIDDEN Registers_x86_64; extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); + +#if defined(_LIBUNWIND_USE_CET) +extern "C" void *__libunwind_cet_get_jump_target() { + return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto); +} +#endif + class _LIBUNWIND_HIDDEN Registers_x86_64 { public: Registers_x86_64(); @@ -340,7 +355,7 @@ inline bool Registers_x86_64::validRegister(int regNum) const { return true; if (regNum < 0) return false; - if (regNum > 15) + if (regNum > 16) return false; return true; } @@ -348,6 +363,7 @@ inline bool Registers_x86_64::validRegister(int regNum) const { inline uint64_t Registers_x86_64::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: return _registers.__rip; case UNW_REG_SP: return _registers.__rsp; @@ -390,6 +406,7 @@ inline uint64_t Registers_x86_64::getRegister(int regNum) const { inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: _registers.__rip = value; return; case UNW_REG_SP: @@ -450,6 +467,7 @@ inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { inline const char *Registers_x86_64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: return "rip"; case UNW_REG_SP: return "rsp"; @@ -1848,7 +1866,7 @@ inline bool Registers_arm64::validRegister(int regNum) const { return false; if (regNum > 95) return false; - if (regNum == UNW_ARM64_RA_SIGN_STATE) + if (regNum == UNW_AARCH64_RA_SIGN_STATE) return true; if ((regNum > 32) && (regNum < 64)) return false; @@ -1856,15 +1874,15 @@ inline bool Registers_arm64::validRegister(int regNum) const { } inline uint64_t Registers_arm64::getRegister(int regNum) const { - if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC) + if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) return _registers.__pc; - if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP) + if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) return _registers.__sp; - if (regNum == UNW_ARM64_RA_SIGN_STATE) + if (regNum == UNW_AARCH64_RA_SIGN_STATE) return _registers.__ra_sign_state; - if (regNum == UNW_ARM64_FP) + if (regNum == UNW_AARCH64_FP) return _registers.__fp; - if (regNum == UNW_ARM64_LR) + if (regNum == UNW_AARCH64_LR) return _registers.__lr; if ((regNum >= 0) && (regNum < 29)) return _registers.__x[regNum]; @@ -1872,15 +1890,15 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const { } inline void Registers_arm64::setRegister(int regNum, uint64_t value) { - if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC) + if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) _registers.__pc = value; - else if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP) + else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) _registers.__sp = value; - else if (regNum == UNW_ARM64_RA_SIGN_STATE) + else if (regNum == UNW_AARCH64_RA_SIGN_STATE) _registers.__ra_sign_state = value; - else if (regNum == UNW_ARM64_FP) + else if (regNum == UNW_AARCH64_FP) _registers.__fp = value; - else if (regNum == UNW_ARM64_LR) + else if (regNum == UNW_AARCH64_LR) _registers.__lr = value; else if ((regNum >= 0) && (regNum < 29)) _registers.__x[regNum] = value; @@ -1894,135 +1912,135 @@ inline const char *Registers_arm64::getRegisterName(int regNum) { return "pc"; case UNW_REG_SP: return "sp"; - case UNW_ARM64_X0: + case UNW_AARCH64_X0: return "x0"; - case UNW_ARM64_X1: + case UNW_AARCH64_X1: return "x1"; - case UNW_ARM64_X2: + case UNW_AARCH64_X2: return "x2"; - case UNW_ARM64_X3: + case UNW_AARCH64_X3: return "x3"; - case UNW_ARM64_X4: + case UNW_AARCH64_X4: return "x4"; - case UNW_ARM64_X5: + case UNW_AARCH64_X5: return "x5"; - case UNW_ARM64_X6: + case UNW_AARCH64_X6: return "x6"; - case UNW_ARM64_X7: + case UNW_AARCH64_X7: return "x7"; - case UNW_ARM64_X8: + case UNW_AARCH64_X8: return "x8"; - case UNW_ARM64_X9: + case UNW_AARCH64_X9: return "x9"; - case UNW_ARM64_X10: + case UNW_AARCH64_X10: return "x10"; - case UNW_ARM64_X11: + case UNW_AARCH64_X11: return "x11"; - case UNW_ARM64_X12: + case UNW_AARCH64_X12: return "x12"; - case UNW_ARM64_X13: + case UNW_AARCH64_X13: return "x13"; - case UNW_ARM64_X14: + case UNW_AARCH64_X14: return "x14"; - case UNW_ARM64_X15: + case UNW_AARCH64_X15: return "x15"; - case UNW_ARM64_X16: + case UNW_AARCH64_X16: return "x16"; - case UNW_ARM64_X17: + case UNW_AARCH64_X17: return "x17"; - case UNW_ARM64_X18: + case UNW_AARCH64_X18: return "x18"; - case UNW_ARM64_X19: + case UNW_AARCH64_X19: return "x19"; - case UNW_ARM64_X20: + case UNW_AARCH64_X20: return "x20"; - case UNW_ARM64_X21: + case UNW_AARCH64_X21: return "x21"; - case UNW_ARM64_X22: + case UNW_AARCH64_X22: return "x22"; - case UNW_ARM64_X23: + case UNW_AARCH64_X23: return "x23"; - case UNW_ARM64_X24: + case UNW_AARCH64_X24: return "x24"; - case UNW_ARM64_X25: + case UNW_AARCH64_X25: return "x25"; - case UNW_ARM64_X26: + case UNW_AARCH64_X26: return "x26"; - case UNW_ARM64_X27: + case UNW_AARCH64_X27: return "x27"; - case UNW_ARM64_X28: + case UNW_AARCH64_X28: return "x28"; - case UNW_ARM64_FP: + case UNW_AARCH64_FP: return "fp"; - case UNW_ARM64_LR: + case UNW_AARCH64_LR: return "lr"; - case UNW_ARM64_SP: + case UNW_AARCH64_SP: return "sp"; - case UNW_ARM64_PC: + case UNW_AARCH64_PC: return "pc"; - case UNW_ARM64_D0: + case UNW_AARCH64_V0: return "d0"; - case UNW_ARM64_D1: + case UNW_AARCH64_V1: return "d1"; - case UNW_ARM64_D2: + case UNW_AARCH64_V2: return "d2"; - case UNW_ARM64_D3: + case UNW_AARCH64_V3: return "d3"; - case UNW_ARM64_D4: + case UNW_AARCH64_V4: return "d4"; - case UNW_ARM64_D5: + case UNW_AARCH64_V5: return "d5"; - case UNW_ARM64_D6: + case UNW_AARCH64_V6: return "d6"; - case UNW_ARM64_D7: + case UNW_AARCH64_V7: return "d7"; - case UNW_ARM64_D8: + case UNW_AARCH64_V8: return "d8"; - case UNW_ARM64_D9: + case UNW_AARCH64_V9: return "d9"; - case UNW_ARM64_D10: + case UNW_AARCH64_V10: return "d10"; - case UNW_ARM64_D11: + case UNW_AARCH64_V11: return "d11"; - case UNW_ARM64_D12: + case UNW_AARCH64_V12: return "d12"; - case UNW_ARM64_D13: + case UNW_AARCH64_V13: return "d13"; - case UNW_ARM64_D14: + case UNW_AARCH64_V14: return "d14"; - case UNW_ARM64_D15: + case UNW_AARCH64_V15: return "d15"; - case UNW_ARM64_D16: + case UNW_AARCH64_V16: return "d16"; - case UNW_ARM64_D17: + case UNW_AARCH64_V17: return "d17"; - case UNW_ARM64_D18: + case UNW_AARCH64_V18: return "d18"; - case UNW_ARM64_D19: + case UNW_AARCH64_V19: return "d19"; - case UNW_ARM64_D20: + case UNW_AARCH64_V20: return "d20"; - case UNW_ARM64_D21: + case UNW_AARCH64_V21: return "d21"; - case UNW_ARM64_D22: + case UNW_AARCH64_V22: return "d22"; - case UNW_ARM64_D23: + case UNW_AARCH64_V23: return "d23"; - case UNW_ARM64_D24: + case UNW_AARCH64_V24: return "d24"; - case UNW_ARM64_D25: + case UNW_AARCH64_V25: return "d25"; - case UNW_ARM64_D26: + case UNW_AARCH64_V26: return "d26"; - case UNW_ARM64_D27: + case UNW_AARCH64_V27: return "d27"; - case UNW_ARM64_D28: + case UNW_AARCH64_V28: return "d28"; - case UNW_ARM64_D29: + case UNW_AARCH64_V29: return "d29"; - case UNW_ARM64_D30: + case UNW_AARCH64_V30: return "d30"; - case UNW_ARM64_D31: + case UNW_AARCH64_V31: return "d31"; default: return "unknown register"; @@ -2030,21 +2048,21 @@ inline const char *Registers_arm64::getRegisterName(int regNum) { } inline bool Registers_arm64::validFloatRegister(int regNum) const { - if (regNum < UNW_ARM64_D0) + if (regNum < UNW_AARCH64_V0) return false; - if (regNum > UNW_ARM64_D31) + if (regNum > UNW_AARCH64_V31) return false; return true; } inline double Registers_arm64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); - return _vectorHalfRegisters[regNum - UNW_ARM64_D0]; + return _vectorHalfRegisters[regNum - UNW_AARCH64_V0]; } inline void Registers_arm64::setFloatRegister(int regNum, double value) { assert(validFloatRegister(regNum)); - _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value; + _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value; } inline bool Registers_arm64::validVectorRegister(int) const { @@ -2123,6 +2141,10 @@ private: uint32_t __pc; // Program counter r15 }; + struct PseudoRegisters { + uint32_t __pac; // Return Authentication Code (PAC) + }; + static void saveVFPWithFSTMD(void*); static void saveVFPWithFSTMX(void*); static void saveVFPv3(void*); @@ -2139,6 +2161,7 @@ private: // ARM registers GPRs _registers; + PseudoRegisters _pseudo_registers; // We save floating point registers lazily because we can't know ahead of // time which ones are used. See EHABI #4.7. @@ -2176,6 +2199,7 @@ inline Registers_arm::Registers_arm(const void *registers) "arm registers do not fit into unw_context_t"); // See __unw_getcontext() note about data. memcpy(&_registers, registers, sizeof(_registers)); + memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2191,6 +2215,7 @@ inline Registers_arm::Registers_arm() _saved_vfp_d0_d15(false), _saved_vfp_d16_d31(false) { memset(&_registers, 0, sizeof(_registers)); + memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2218,6 +2243,11 @@ inline bool Registers_arm::validRegister(int regNum) const { return true; #endif +#ifdef __ARM_FEATURE_PAUTH + if (regNum == UNW_ARM_RA_AUTH_CODE) + return true; +#endif + return false; } @@ -2244,6 +2274,11 @@ inline uint32_t Registers_arm::getRegister(int regNum) const { } #endif +#ifdef __ARM_FEATURE_PAUTH + if (regNum == UNW_ARM_RA_AUTH_CODE) + return _pseudo_registers.__pac; +#endif + _LIBUNWIND_ABORT("unsupported arm register"); } @@ -2279,6 +2314,11 @@ inline void Registers_arm::setRegister(int regNum, uint32_t value) { } #endif + if (regNum == UNW_ARM_RA_AUTH_CODE) { + _pseudo_registers.__pac = value; + return; + } + _LIBUNWIND_ABORT("unsupported arm register"); } @@ -3547,7 +3587,6 @@ inline const char *Registers_sparc::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_SPARC - #if defined(_LIBUNWIND_TARGET_SPARC64) /// Registers_sparc64 holds the register state of a thread in a 64-bit /// sparc process. diff --git a/lib/libunwind/src/Unwind-EHABI.cpp b/lib/libunwind/src/Unwind-EHABI.cpp index 8843db7f54..257db724c2 100644 --- a/lib/libunwind/src/Unwind-EHABI.cpp +++ b/lib/libunwind/src/Unwind-EHABI.cpp @@ -1,4 +1,4 @@ -//===--------------------------- Unwind-EHABI.cpp -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -187,9 +187,14 @@ static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state, if (result != _URC_CONTINUE_UNWIND) return result; - if (__unw_step(reinterpret_cast<unw_cursor_t *>(context)) != UNW_STEP_SUCCESS) + switch (__unw_step(reinterpret_cast<unw_cursor_t *>(context))) { + case UNW_STEP_SUCCESS: + return _URC_CONTINUE_UNWIND; + case UNW_STEP_END: + return _URC_END_OF_STACK; + default: return _URC_FAILURE; - return _URC_CONTINUE_UNWIND; + } } // Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE / @@ -256,6 +261,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, size_t offset, size_t len) { bool wrotePC = false; bool finish = false; + bool hasReturnAddrAuthCode = false; while (offset < len && !finish) { uint8_t byte = getByte(data, offset++); if ((byte & 0x80) == 0) { @@ -342,6 +348,10 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, break; } case 0xb4: + hasReturnAddrAuthCode = true; + _Unwind_VRS_Pop(context, _UVRSC_PSEUDO, + 0 /* Return Address Auth Code */, _UVRSD_UINT32); + break; case 0xb5: case 0xb6: case 0xb7: @@ -417,6 +427,16 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, if (!wrotePC) { uint32_t lr; _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); +#ifdef __ARM_FEATURE_PAUTH + if (hasReturnAddrAuthCode) { + uint32_t sp; + uint32_t pac; + _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + _Unwind_VRS_Get(context, _UVRSC_PSEUDO, UNW_ARM_RA_AUTH_CODE, + _UVRSD_UINT32, &pac); + __asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :); + } +#endif _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); } return _URC_CONTINUE_UNWIND; @@ -463,6 +483,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except return _URC_FATAL_PHASE1_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -481,6 +502,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // If there is a personality routine, ask it if it will want to stop at // this frame. @@ -582,6 +604,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -598,11 +621,12 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor functionName, sp, frameInfo.lsda, frameInfo.handler); } +#endif // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { _Unwind_Personality_Fn p = - (_Unwind_Personality_Fn)(long)(frameInfo.handler); + (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); // EHABI #7.2 exception_object->pr_cache.fnstart = frameInfo.start_ip; @@ -670,6 +694,123 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor return _URC_FATAL_PHASE2_ERROR; } +static _Unwind_Reason_Code +unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, + _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, + void *stop_parameter) { + bool endOfStack = false; + // See comment at the start of unwind_phase1 regarding VRS integrity. + __unw_init_local(cursor, uc); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_force(ex_ojb=%p)", + static_cast<void *>(exception_object)); + // Walk each frame until we reach where search phase said to stop + while (!endOfStack) { + // Update info about this frame. + unw_proc_info_t frameInfo; + if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step " + "failed => _URC_END_OF_STACK", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + +#ifndef NDEBUG + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR + ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, + (void *)exception_object, frameInfo.start_ip, functionName, + frameInfo.lsda, frameInfo.handler); + } +#endif + + // Call stop function at each frame. + _Unwind_Action action = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); + _Unwind_Reason_Code stopResult = + (*stop)(1, action, exception_object->exception_class, exception_object, + (_Unwind_Context *)(cursor), stop_parameter); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", + (void *)exception_object, stopResult); + if (stopResult != _URC_NO_REASON) { + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // If there is a personality routine, tell it we are unwinding. + if (frameInfo.handler != 0) { + _Unwind_Personality_Fn p = + (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); + struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); + // EHABI #7.2 + exception_object->pr_cache.fnstart = frameInfo.start_ip; + exception_object->pr_cache.ehtp = + (_Unwind_EHT_Header *)frameInfo.unwind_info; + exception_object->pr_cache.additional = frameInfo.flags; + _Unwind_Reason_Code personalityResult = + (*p)(_US_FORCE_UNWIND | _US_UNWIND_FRAME_STARTING, exception_object, + context); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_CONTINUE_UNWIND", + (void *)exception_object); + // Destructors called, continue unwinding + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_INSTALL_CONTEXT", + (void *)exception_object); + // We may get control back if landing pad calls _Unwind_Resume(). + __unw_resume(cursor); + break; + case _URC_END_OF_STACK: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_END_OF_STACK", + (void *)exception_object); + // Personalty routine did the step and it can't step forward. + endOfStack = true; + break; + default: + // Personality routine returned an unknown result code. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned %d, " + "_URC_FATAL_PHASE2_ERROR", + (void *)exception_object, personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + } + + // Call stop function one last time and tell it we've reached the end + // of the stack. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " + "function with _UA_END_OF_STACK", + (void *)exception_object); + _Unwind_Action lastAction = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); + (*stop)(1, lastAction, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(cursor), stop_parameter); + + // Clean up phase did not resume at the frame that the search phase said it + // would. + return _URC_FATAL_PHASE2_ERROR; +} + /// Called by __cxa_throw. Only returns if there is a fatal error. _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object) { @@ -717,10 +858,13 @@ _Unwind_Resume(_Unwind_Exception *exception_object) { unw_cursor_t cursor; __unw_getcontext(&uc); - // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, - // which is in the same position as private_1 below. - // TODO(ajwong): Who wronte the above? Why is it true? - unwind_phase2(&uc, &cursor, exception_object, true); + if (exception_object->unwinder_cache.reserved1) + unwind_phase2_forced( + &uc, &cursor, exception_object, + (_Unwind_Stop_Fn)exception_object->unwinder_cache.reserved1, + (void *)exception_object->unwinder_cache.reserved3); + else + unwind_phase2(&uc, &cursor, exception_object, true); // Clients assume _Unwind_Resume() does not return, so all we can do is abort. _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); @@ -812,6 +956,15 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, case _UVRSC_WMMXD: break; #endif + case _UVRSC_PSEUDO: + // There's only one pseudo-register, PAC, with regno == 0. + if (representation != _UVRSD_UINT32 || regno != 0) + return _UVRSR_FAILED; + return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE), + *(unw_word_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; + break; } _LIBUNWIND_ABORT("unsupported register class"); } @@ -866,6 +1019,15 @@ _Unwind_VRS_Get_Internal(_Unwind_Context *context, case _UVRSC_WMMXD: break; #endif + case _UVRSC_PSEUDO: + // There's only one pseudo-register, PAC, with regno == 0. + if (representation != _UVRSD_UINT32 || regno != 0) + return _UVRSR_FAILED; + return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE), + (unw_word_t *)valuep) == UNW_ESUCCESS + ? _UVRSR_OK + : _UVRSR_FAILED; + break; } _LIBUNWIND_ABORT("unsupported register class"); } @@ -963,10 +1125,45 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); } + case _UVRSC_PSEUDO: { + if (representation != _UVRSD_UINT32 || discriminator != 0) + return _UVRSR_FAILED; + // Return Address Authentication code (PAC) - discriminator 0 + uint32_t *sp; + if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, + &sp) != _UVRSR_OK) { + return _UVRSR_FAILED; + } + uint32_t pac = *sp++; + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_RA_AUTH_CODE, + _UVRSD_UINT32, &pac); + } } _LIBUNWIND_ABORT("unsupported register class"); } +/// Not used by C++. +/// Unwinds stack, calling "stop" function at each frame. +/// Could be used to implement longjmp(). +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, + void *stop_parameter) { + _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", + (void *)exception_object, (void *)(uintptr_t)stop); + unw_context_t uc; + unw_cursor_t cursor; + __unw_getcontext(&uc); + + // Mark that this is a forced unwind, so _Unwind_Resume() can do + // the right thing. + exception_object->unwinder_cache.reserved1 = (uintptr_t)stop; + exception_object->unwinder_cache.reserved3 = (uintptr_t)stop_parameter; + + return unwind_phase2_forced(&uc, &cursor, exception_object, stop, + stop_parameter); +} + /// Called by personality handler during phase 2 to find the start of the /// function. _LIBUNWIND_EXPORT uintptr_t @@ -997,9 +1194,14 @@ extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code __gnu_unwind_frame(_Unwind_Exception *exception_object, struct _Unwind_Context *context) { unw_cursor_t *cursor = (unw_cursor_t *)context; - if (__unw_step(cursor) != UNW_STEP_SUCCESS) + switch (__unw_step(cursor)) { + case UNW_STEP_SUCCESS: + return _URC_OK; + case UNW_STEP_END: + return _URC_END_OF_STACK; + default: return _URC_FAILURE; - return _URC_OK; + } } #endif // defined(_LIBUNWIND_ARM_EHABI) diff --git a/lib/libunwind/src/Unwind-EHABI.h b/lib/libunwind/src/Unwind-EHABI.h index 6897082a33..ff3b5fc6fe 100644 --- a/lib/libunwind/src/Unwind-EHABI.h +++ b/lib/libunwind/src/Unwind-EHABI.h @@ -1,4 +1,4 @@ -//===------------------------- Unwind-EHABI.hpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libunwind/src/Unwind-seh.cpp b/lib/libunwind/src/Unwind-seh.cpp index 56a52506e1..f00bc4721b 100644 --- a/lib/libunwind/src/Unwind-seh.cpp +++ b/lib/libunwind/src/Unwind-seh.cpp @@ -1,4 +1,4 @@ -//===--------------------------- Unwind-seh.cpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -28,8 +28,6 @@ #include "libunwind_ext.h" #include "UnwindCursor.hpp" -#pragma clang diagnostic ignored "-Wdll-attribute-on-redeclaration" - using namespace libunwind; #define STATUS_USER_DEFINED (1u << 29) @@ -171,8 +169,8 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, __unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]); #elif defined(__aarch64__) exc->private_[2] = disp->TargetPc; - __unw_get_reg(&cursor, UNW_ARM64_X0, &retval); - __unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]); + __unw_get_reg(&cursor, UNW_AARCH64_X0, &retval); + __unw_get_reg(&cursor, UNW_AARCH64_X1, &exc->private_[3]); #endif __unw_get_reg(&cursor, UNW_REG_IP, &target); ms_exc->ExceptionCode = STATUS_GCC_UNWIND; @@ -246,6 +244,7 @@ unwind_phase2_forced(unw_context_t *uc, return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -261,6 +260,7 @@ unwind_phase2_forced(unw_context_t *uc, (void *)exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // Call stop function at each frame. _Unwind_Action action = diff --git a/lib/libunwind/src/Unwind-sjlj.c b/lib/libunwind/src/Unwind-sjlj.c index fd2a95b74c..d487995bb7 100644 --- a/lib/libunwind/src/Unwind-sjlj.c +++ b/lib/libunwind/src/Unwind-sjlj.c @@ -1,4 +1,4 @@ -//===--------------------------- Unwind-sjlj.c ----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libunwind/src/UnwindCursor.hpp b/lib/libunwind/src/UnwindCursor.hpp index d63dff5e61..1ca842f33a 100644 --- a/lib/libunwind/src/UnwindCursor.hpp +++ b/lib/libunwind/src/UnwindCursor.hpp @@ -1,4 +1,4 @@ -//===------------------------- UnwindCursor.hpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,6 +11,7 @@ #ifndef __UNWINDCURSOR_HPP__ #define __UNWINDCURSOR_HPP__ +#include "cet_unwind.h" #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -449,6 +450,12 @@ public: #ifdef __arm__ virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } #endif + +#if defined(_LIBUNWIND_USE_CET) + virtual void *get_registers() { + _LIBUNWIND_ABORT("get_registers not implemented"); + } +#endif }; #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) @@ -620,12 +627,12 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) _msContext.D[i - UNW_ARM_D0] = d.w; } #elif defined(_LIBUNWIND_TARGET_AARCH64) - for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i) - _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i); + for (int i = UNW_AARCH64_X0; i <= UNW_ARM64_X30; ++i) + _msContext.X[i - UNW_AARCH64_X0] = r.getRegister(i); _msContext.Sp = r.getRegister(UNW_REG_SP); _msContext.Pc = r.getRegister(UNW_REG_IP); - for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i) - _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i); + for (int i = UNW_AARCH64_V0; i <= UNW_ARM64_D31; ++i) + _msContext.V[i - UNW_AARCH64_V0].D[0] = r.getFloatRegister(i); #endif } @@ -648,9 +655,11 @@ bool UnwindCursor<A, R>::validReg(int regNum) { #if defined(_LIBUNWIND_TARGET_X86_64) if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true; #elif defined(_LIBUNWIND_TARGET_ARM) - if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true; + if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) || + regNum == UNW_ARM_RA_AUTH_CODE) + return true; #elif defined(_LIBUNWIND_TARGET_AARCH64) - if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true; + if (regNum >= UNW_AARCH64_X0 && regNum <= UNW_ARM64_X30) return true; #endif return false; } @@ -699,7 +708,7 @@ unw_word_t UnwindCursor<A, R>::getReg(int regNum) { #elif defined(_LIBUNWIND_TARGET_AARCH64) case UNW_REG_SP: return _msContext.Sp; case UNW_REG_IP: return _msContext.Pc; - default: return _msContext.X[regNum - UNW_ARM64_X0]; + default: return _msContext.X[regNum - UNW_AARCH64_X0]; #endif } _LIBUNWIND_ABORT("unsupported register"); @@ -749,37 +758,37 @@ void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) { #elif defined(_LIBUNWIND_TARGET_AARCH64) case UNW_REG_SP: _msContext.Sp = value; break; case UNW_REG_IP: _msContext.Pc = value; break; - case UNW_ARM64_X0: - case UNW_ARM64_X1: - case UNW_ARM64_X2: - case UNW_ARM64_X3: - case UNW_ARM64_X4: - case UNW_ARM64_X5: - case UNW_ARM64_X6: - case UNW_ARM64_X7: - case UNW_ARM64_X8: - case UNW_ARM64_X9: - case UNW_ARM64_X10: - case UNW_ARM64_X11: - case UNW_ARM64_X12: - case UNW_ARM64_X13: - case UNW_ARM64_X14: - case UNW_ARM64_X15: - case UNW_ARM64_X16: - case UNW_ARM64_X17: - case UNW_ARM64_X18: - case UNW_ARM64_X19: - case UNW_ARM64_X20: - case UNW_ARM64_X21: - case UNW_ARM64_X22: - case UNW_ARM64_X23: - case UNW_ARM64_X24: - case UNW_ARM64_X25: - case UNW_ARM64_X26: - case UNW_ARM64_X27: - case UNW_ARM64_X28: - case UNW_ARM64_FP: - case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; + case UNW_AARCH64_X0: + case UNW_AARCH64_X1: + case UNW_AARCH64_X2: + case UNW_AARCH64_X3: + case UNW_AARCH64_X4: + case UNW_AARCH64_X5: + case UNW_AARCH64_X6: + case UNW_AARCH64_X7: + case UNW_AARCH64_X8: + case UNW_AARCH64_X9: + case UNW_AARCH64_X10: + case UNW_AARCH64_X11: + case UNW_AARCH64_X12: + case UNW_AARCH64_X13: + case UNW_AARCH64_X14: + case UNW_AARCH64_X15: + case UNW_AARCH64_X16: + case UNW_AARCH64_X17: + case UNW_AARCH64_X18: + case UNW_AARCH64_X19: + case UNW_AARCH64_X20: + case UNW_AARCH64_X21: + case UNW_AARCH64_X22: + case UNW_AARCH64_X23: + case UNW_AARCH64_X24: + case UNW_AARCH64_X25: + case UNW_AARCH64_X26: + case UNW_AARCH64_X27: + case UNW_AARCH64_X28: + case UNW_AARCH64_FP: + case UNW_AARCH64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; #endif default: _LIBUNWIND_ABORT("unsupported register"); @@ -792,7 +801,7 @@ bool UnwindCursor<A, R>::validFloatReg(int regNum) { if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true; if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true; #elif defined(_LIBUNWIND_TARGET_AARCH64) - if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true; + if (regNum >= UNW_AARCH64_V0 && regNum <= UNW_ARM64_D31) return true; #else (void)regNum; #endif @@ -820,7 +829,7 @@ unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) { } _LIBUNWIND_ABORT("unsupported float register"); #elif defined(_LIBUNWIND_TARGET_AARCH64) - return _msContext.V[regNum - UNW_ARM64_D0].D[0]; + return _msContext.V[regNum - UNW_AARCH64_V0].D[0]; #else (void)regNum; _LIBUNWIND_ABORT("float registers unimplemented"); @@ -848,7 +857,7 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { } _LIBUNWIND_ABORT("unsupported float register"); #elif defined(_LIBUNWIND_TARGET_AARCH64) - _msContext.V[regNum - UNW_ARM64_D0].D[0] = value; + _msContext.V[regNum - UNW_AARCH64_V0].D[0] = value; #else (void)regNum; (void)value; @@ -901,6 +910,9 @@ public: virtual void saveVFPAsX(); #endif +#if defined(_LIBUNWIND_USE_CET) + virtual void *get_registers() { return &_registers; } +#endif // libunwind does not and should not depend on C++ library which means that we // need our own defition of inline placement new. static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; } @@ -2077,7 +2089,7 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) { for (int i = 0; i <= 30; ++i) { uint64_t value = _addressSpace.get64(sigctx + kOffsetGprs + static_cast<pint_t>(i * 8)); - _registers.setRegister(UNW_ARM64_X0 + i, value); + _registers.setRegister(UNW_AARCH64_X0 + i, value); } _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp)); _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc)); @@ -2141,6 +2153,12 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen, buf, bufLen, offset); } +#if defined(_LIBUNWIND_USE_CET) +extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->get_registers(); +} +#endif } // namespace libunwind #endif // __UNWINDCURSOR_HPP__ diff --git a/lib/libunwind/src/UnwindLevel1-gcc-ext.c b/lib/libunwind/src/UnwindLevel1-gcc-ext.c index 6727f43011..951d5d219a 100644 --- a/lib/libunwind/src/UnwindLevel1-gcc-ext.c +++ b/lib/libunwind/src/UnwindLevel1-gcc-ext.c @@ -1,4 +1,4 @@ -//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -22,36 +22,27 @@ #include "Unwind-EHABI.h" #include "unwind.h" -#pragma clang diagnostic ignored "-Wdll-attribute-on-redeclaration" - #if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) -#define private_1 private_[0] +#define PRIVATE_1 private_[0] +#elif defined(_LIBUNWIND_ARM_EHABI) +#define PRIVATE_1 unwinder_cache.reserved1 +#else +#define PRIVATE_1 private_1 #endif /// Called by __cxa_rethrow(). _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { -#if defined(_LIBUNWIND_ARM_EHABI) - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld", - (void *)exception_object, - (long)exception_object->unwinder_cache.reserved1); -#else - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR, - (void *)exception_object, - (intptr_t)exception_object->private_1); -#endif + _LIBUNWIND_TRACE_API( + "_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR, + (void *)exception_object, (intptr_t)exception_object->PRIVATE_1); -#if defined(_LIBUNWIND_ARM_EHABI) - // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, - // which is in the same position as private_1 below. - return _Unwind_RaiseException(exception_object); -#else // If this is non-forced and a stopping place was found, then this is a // re-throw. // Call _Unwind_RaiseException() as if this was a new exception - if (exception_object->private_1 == 0) { + if (exception_object->PRIVATE_1 == 0) { return _Unwind_RaiseException(exception_object); // Will return if there is no catch clause, so that __cxa_rethrow can call // std::terminate(). @@ -62,10 +53,8 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { _Unwind_Resume(exception_object); _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" " which unexpectedly returned"); -#endif } - /// Called by personality handler during phase 2 to get base address for data /// relative encodings. _LIBUNWIND_EXPORT uintptr_t @@ -120,7 +109,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { // Create a mock exception object for force unwinding. _Unwind_Exception ex; memset(&ex, '\0', sizeof(ex)); - ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0 + strcpy((char *)&ex.exception_class, "CLNGUNW"); #endif // walk each frame diff --git a/lib/libunwind/src/UnwindLevel1.c b/lib/libunwind/src/UnwindLevel1.c index 41047b6689..5c1f99d4bf 100644 --- a/lib/libunwind/src/UnwindLevel1.c +++ b/lib/libunwind/src/UnwindLevel1.c @@ -1,4 +1,4 @@ -//===------------------------- UnwindLevel1.c -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -25,17 +25,48 @@ #include <stdio.h> #include <string.h> +#include "cet_unwind.h" #include "config.h" #include "libunwind.h" #include "libunwind_ext.h" #include "unwind.h" -#pragma clang diagnostic ignored "-Wdll-attribute-on-redeclaration" - #if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) #ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND +// When CET is enabled, each "call" instruction will push return address to +// CET shadow stack, each "ret" instruction will pop current CET shadow stack +// top and compare it with target address which program will return. +// In exception handing, some stack frames will be skipped before jumping to +// landing pad and we must adjust CET shadow stack accordingly. +// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we +// directly jump to __libunwind_Registerts_x86/x86_64_jumpto instead of using +// a regular function call to avoid pushing to CET shadow stack again. +#if !defined(_LIBUNWIND_USE_CET) +#define __unw_phase2_resume(cursor, fn) __unw_resume((cursor)) +#elif defined(_LIBUNWIND_TARGET_I386) +#define __unw_phase2_resume(cursor, fn) \ + do { \ + _LIBUNWIND_POP_CET_SSP((fn)); \ + void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ + void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ + __asm__ volatile("push %%edi\n\t" \ + "sub $4, %%esp\n\t" \ + "jmp *%%edx\n\t" :: "D"(cetRegContext), \ + "d"(cetJumpAddress)); \ + } while (0) +#elif defined(_LIBUNWIND_TARGET_X86_64) +#define __unw_phase2_resume(cursor, fn) \ + do { \ + _LIBUNWIND_POP_CET_SSP((fn)); \ + void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ + void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ + __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \ + "d"(cetJumpAddress)); \ + } while (0) +#endif + static _Unwind_Reason_Code unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { __unw_init_local(cursor, uc); @@ -70,6 +101,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except return _URC_FATAL_PHASE1_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -87,6 +119,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except (void *)exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // If there is a personality routine, ask it if it will want to stop at // this frame. @@ -137,6 +170,9 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", (void *)exception_object); + // uc is initialized by __unw_getcontext in the parent frame. The first stack + // frame walked is unwind_phase2. + unsigned framesWalked = 1; // Walk each frame until we reach where search phase said to stop. while (true) { @@ -169,6 +205,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -185,7 +222,9 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except functionName, sp, frameInfo.lsda, frameInfo.handler); } +#endif + ++framesWalked; // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { _Unwind_Personality_Fn p = @@ -225,8 +264,9 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except ", sp=0x%" PRIxPTR, (void *)exception_object, pc, sp); } - __unw_resume(cursor); - // __unw_resume() only returns if there was an error. + + __unw_phase2_resume(cursor, framesWalked); + // __unw_phase2_resume() only returns if there was an error. return _URC_FATAL_PHASE2_ERROR; default: // Personality routine returned an unknown result code. @@ -248,6 +288,9 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Stop_Fn stop, void *stop_parameter) { __unw_init_local(cursor, uc); + // uc is initialized by __unw_getcontext in the parent frame. The first stack + // frame walked is unwind_phase2_forced. + unsigned framesWalked = 1; // Walk each frame until we reach where search phase said to stop while (__unw_step(cursor) > 0) { @@ -260,6 +303,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -275,6 +319,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, (void *)exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // Call stop function at each frame. _Unwind_Action action = @@ -292,6 +337,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, return _URC_FATAL_PHASE2_ERROR; } + ++framesWalked; // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { _Unwind_Personality_Fn p = @@ -316,7 +362,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, "_URC_INSTALL_CONTEXT", (void *)exception_object); // We may get control back if landing pad calls _Unwind_Resume(). - __unw_resume(cursor); + __unw_phase2_resume(cursor, framesWalked); break; default: // Personality routine returned an unknown result code. diff --git a/lib/libunwind/src/UnwindRegistersRestore.S b/lib/libunwind/src/UnwindRegistersRestore.S index bbdabcc355..1df97f5fc4 100644 --- a/lib/libunwind/src/UnwindRegistersRestore.S +++ b/lib/libunwind/src/UnwindRegistersRestore.S @@ -1,4 +1,4 @@ -//===-------------------- UnwindRegistersRestore.S ------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -25,6 +25,8 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) # + return address + # +-----------------------+ <-- SP # + + + + _LIBUNWIND_CET_ENDBR movl 4(%esp), %eax # set up eax and ret on new stack location movl 28(%eax), %edx # edx holds new stack pointer @@ -46,7 +48,8 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) # skip ss # skip eflags pop %eax # eax was already pushed on new stack - ret # eip was already pushed on new stack + pop %ecx + jmp *%ecx # skip cs # skip ds # skip es @@ -70,6 +73,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) # On entry, thread_state pointer is in rdi #endif + _LIBUNWIND_CET_ENDBR movq 56(%rdi), %rax # rax holds new stack pointer subq $16, %rax movq %rax, 56(%rdi) @@ -119,7 +123,8 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) #endif movq 56(%rdi), %rsp # cut back rsp to new location pop %rdi # rdi was saved here earlier - ret # rip was saved here + pop %rcx + jmpq *%rcx #elif defined(__powerpc64__) @@ -389,7 +394,7 @@ Lnovec: PPC64_LR(3) bctr -#elif defined(__ppc__) +#elif defined(__powerpc__) DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) // @@ -655,7 +660,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_arm20restoreCoreAndJumpToEv) ldr sp, [lr, #52] ldr lr, [lr, #60] @ restore pc into lr #endif +#if defined(__ARM_FEATURE_BTI_DEFAULT) && !defined(__ARM_ARCH_ISA_ARM) + // 'bx' is not BTI setting when used with lr, therefore r12 is used instead + mov r12, lr + JMP(r12) +#else JMP(lr) +#endif @ @ static void libunwind::Registers_arm::restoreVFPWithFLDMD(unw_fpreg_t* values) @@ -800,11 +811,12 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) l.lwz r30,120(r3) l.lwz r31,124(r3) + # load new pc into ra + l.lwz r9, 128(r3) + # at last, restore r3 l.lwz r3, 12(r3) - # load new pc into ra - l.lwz r9, 128(r3) # jump to pc l.jr r9 l.nop diff --git a/lib/libunwind/src/UnwindRegistersSave.S b/lib/libunwind/src/UnwindRegistersSave.S index b6fca2be27..b39489235c 100644 --- a/lib/libunwind/src/UnwindRegistersSave.S +++ b/lib/libunwind/src/UnwindRegistersSave.S @@ -1,4 +1,4 @@ -//===------------------------ UnwindRegistersSave.S -----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -27,6 +27,8 @@ # + + # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) + + _LIBUNWIND_CET_ENDBR push %eax movl 8(%esp), %eax movl %ebx, 4(%eax) @@ -70,6 +72,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) #define TMP %rsi #endif + _LIBUNWIND_CET_ENDBR movq %rax, (PTR) movq %rbx, 8(PTR) movq %rcx, 16(PTR) @@ -556,7 +559,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) blr -#elif defined(__ppc__) +#elif defined(__powerpc__) // // extern int unw_getcontext(unw_context_t* thread_state) @@ -600,9 +603,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stw 30,128(3) stw 31,132(3) +#if defined(__ALTIVEC__) // save VRSave register mfspr 0, 256 stw 0, 156(3) +#endif // save CR registers mfcr 0 stw 0, 136(3) @@ -766,7 +771,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) @ @ On entry: @ thread_state pointer is in r0 -@ +@ @ Per EHABI #4.7 this only saves the core integer registers. @ EHABI #7.4.5 notes that in general all VRS registers should be restored @ however this is very hard to do for VFP registers because it is unknown diff --git a/lib/libunwind/src/Unwind_AppleExtras.cpp b/lib/libunwind/src/Unwind_AppleExtras.cpp index e3d41ca2b4..ffb49a89e5 100644 --- a/lib/libunwind/src/Unwind_AppleExtras.cpp +++ b/lib/libunwind/src/Unwind_AppleExtras.cpp @@ -1,4 +1,4 @@ -//===--------------------- Unwind_AppleExtras.cpp -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libunwind/src/assembly.h b/lib/libunwind/src/assembly.h index 76ef825532..89293a555b 100644 --- a/lib/libunwind/src/assembly.h +++ b/lib/libunwind/src/assembly.h @@ -15,6 +15,13 @@ #ifndef UNWIND_ASSEMBLY_H #define UNWIND_ASSEMBLY_H +#if defined(__linux__) && defined(__CET__) +#include <cet.h> +#define _LIBUNWIND_CET_ENDBR _CET_ENDBR +#else +#define _LIBUNWIND_CET_ENDBR +#endif + #if defined(__powerpc64__) #define SEPARATOR ; #define PPC64_OFFS_SRR0 0 @@ -74,7 +81,7 @@ #define PPC64_OPD2 #endif -#if defined(__ARM_FEATURE_BTI_DEFAULT) +#if defined(__aarch64__) && defined(__ARM_FEATURE_BTI_DEFAULT) .pushsection ".note.gnu.property", "a" SEPARATOR \ .balign 8 SEPARATOR \ .long 4 SEPARATOR \ @@ -92,6 +99,17 @@ #define AARCH64_BTI #endif +#if !defined(__aarch64__) +#ifdef __ARM_FEATURE_PAC_DEFAULT + .eabi_attribute Tag_PAC_extension, 2 + .eabi_attribute Tag_PACRET_use, 1 +#endif +#ifdef __ARM_FEATURE_BTI_DEFAULT + .eabi_attribute Tag_BTI_extension, 1 + .eabi_attribute Tag_BTI_use, 1 +#endif +#endif + #define GLUE2(a, b) a ## b #define GLUE(a, b) GLUE2(a, b) #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) @@ -216,7 +234,7 @@ #endif #endif /* __arm__ */ -#if defined(__ppc__) || defined(__powerpc64__) +#if defined(__powerpc__) #define PPC_LEFT_SHIFT(index) << (index) #endif diff --git a/lib/libunwind/src/cet_unwind.h b/lib/libunwind/src/cet_unwind.h new file mode 100644 index 0000000000..e371be20c4 --- /dev/null +++ b/lib/libunwind/src/cet_unwind.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// +//===----------------------------------------------------------------------===// + +#ifndef LIBUNWIND_CET_UNWIND_H +#define LIBUNWIND_CET_UNWIND_H + +#include "libunwind.h" + +// Currently, CET is implemented on Linux x86 platforms. +#if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__) +#define _LIBUNWIND_USE_CET 1 +#endif + +#if defined(_LIBUNWIND_USE_CET) +#include <cet.h> +#include <immintrin.h> + +#define _LIBUNWIND_POP_CET_SSP(x) \ + do { \ + unsigned long ssp = _get_ssp(); \ + if (ssp != 0) { \ + unsigned int tmp = (x); \ + while (tmp > 255) { \ + _inc_ssp(255); \ + tmp -= 255; \ + } \ + _inc_ssp(tmp); \ + } \ + } while (0) +#endif + +extern void *__libunwind_cet_get_registers(unw_cursor_t *); +extern void *__libunwind_cet_get_jump_target(); + +#endif diff --git a/lib/libunwind/src/config.h b/lib/libunwind/src/config.h index f25b390c84..5ae1604f65 100644 --- a/lib/libunwind/src/config.h +++ b/lib/libunwind/src/config.h @@ -1,4 +1,4 @@ -//===----------------------------- config.h -------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -105,7 +105,7 @@ #define _LIBUNWIND_BUILD_SJLJ_APIS #endif -#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) #define _LIBUNWIND_SUPPORT_FRAME_APIS #endif diff --git a/lib/libunwind/src/dwarf2.h b/lib/libunwind/src/dwarf2.h index 40f0daf468..174277d5a7 100644 --- a/lib/libunwind/src/dwarf2.h +++ b/lib/libunwind/src/dwarf2.h @@ -1,4 +1,4 @@ -//===------------------------------- dwarf2.h -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lib/libunwind/src/libunwind.cpp b/lib/libunwind/src/libunwind.cpp index ac01246e86..03f8b75b5b 100644 --- a/lib/libunwind/src/libunwind.cpp +++ b/lib/libunwind/src/libunwind.cpp @@ -1,4 +1,4 @@ -//===--------------------------- libunwind.cpp ----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,8 +11,8 @@ #include <libunwind.h> -#include "libunwind_ext.h" #include "config.h" +#include "libunwind_ext.h" #include <stdlib.h> @@ -30,8 +30,6 @@ #include "AddressSpace.hpp" #include "UnwindCursor.hpp" -#pragma clang diagnostic ignored "-Wdll-attribute-on-redeclaration" - using namespace libunwind; /// internal object to represent this processes address space @@ -53,7 +51,7 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, # define REGISTER_KIND Registers_x86_64 #elif defined(__powerpc64__) # define REGISTER_KIND Registers_ppc64 -#elif defined(__ppc__) +#elif defined(__powerpc__) # define REGISTER_KIND Registers_ppc #elif defined(__aarch64__) # define REGISTER_KIND Registers_arm64 @@ -70,7 +68,7 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, #elif defined(__mips__) # warning The MIPS architecture is not supported with this ABI and environment! #elif defined(__sparc__) && defined(__arch64__) -# define REGISTER_KIND Registers_sparc64 +#define REGISTER_KIND Registers_sparc64 #elif defined(__sparc__) # define REGISTER_KIND Registers_sparc #elif defined(__riscv) @@ -296,6 +294,35 @@ void __unw_remove_dynamic_fde(unw_word_t fde) { // fde is own mh_group DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde); } + +void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) { + // The eh_frame section start serves as the mh_group + unw_word_t mh_group = eh_frame_start; + CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; + CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; + auto p = (LocalAddressSpace::pint_t)eh_frame_start; + while (true) { + if (CFI_Parser<LocalAddressSpace>::decodeFDE( + LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo, + true) == NULL) { + DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group, + fdeInfo.pcStart, fdeInfo.pcEnd, + fdeInfo.fdeStart); + p += fdeInfo.fdeLength; + } else if (CFI_Parser<LocalAddressSpace>::parseCIE( + LocalAddressSpace::sThisAddressSpace, p, &cieInfo) == NULL) { + p += cieInfo.cieLength; + } else + return; + } +} + +void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { + // The eh_frame section start serves as the mh_group + DwarfFDECache<LocalAddressSpace>::removeAllIn( + (LocalAddressSpace::pint_t)eh_frame_start); +} + #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #endif // !defined(__USING_SJLJ_EXCEPTIONS__) diff --git a/lib/libunwind/src/libunwind_ext.h b/lib/libunwind/src/libunwind_ext.h index 316dee2982..7065ffcdae 100644 --- a/lib/libunwind/src/libunwind_ext.h +++ b/lib/libunwind/src/libunwind_ext.h @@ -1,4 +1,4 @@ -//===------------------------ libunwind_ext.h -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -51,6 +51,9 @@ extern void __unw_iterate_dwarf_unwind_cache(void (*func)( extern void __unw_add_dynamic_fde(unw_word_t fde); extern void __unw_remove_dynamic_fde(unw_word_t fde); +extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start); +extern void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start); + #if defined(_LIBUNWIND_ARM_EHABI) extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*); extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context, |
