diff --git a/lib/libcxx/include/__config b/lib/libcxx/include/__config index b9203e640a..58a396e764 100644 --- a/lib/libcxx/include/__config +++ b/lib/libcxx/include/__config @@ -10,8 +10,6 @@ #ifndef _LIBCPP___CONFIG #define _LIBCPP___CONFIG -#include <__config_site> - #if defined(_MSC_VER) && !defined(__clang__) # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) # define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER diff --git a/lib/libunwind/include/__libunwind_config.h b/lib/libunwind/include/__libunwind_config.h index 5e9de90f64..f69fe89e9a 100644 --- a/lib/libunwind/include/__libunwind_config.h +++ b/lib/libunwind/include/__libunwind_config.h @@ -30,6 +30,7 @@ #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X 83 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH 64 #if defined(_LIBUNWIND_IS_NATIVE_ONLY) # if defined(__linux__) @@ -166,6 +167,16 @@ # define _LIBUNWIND_CONTEXT_SIZE 34 # define _LIBUNWIND_CURSOR_SIZE 46 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X +#elif defined(__loongarch__) +#define _LIBUNWIND_TARGET_LOONGARCH 1 +#if __loongarch_grlen == 64 +#define _LIBUNWIND_CONTEXT_SIZE 65 +#define _LIBUNWIND_CURSOR_SIZE 77 +#else +#error "Unsupported LoongArch ABI" +#endif +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER \ + _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH # else # error "Unsupported architecture." # endif @@ -185,6 +196,7 @@ # define _LIBUNWIND_TARGET_RISCV 1 # define _LIBUNWIND_TARGET_VE 1 # define _LIBUNWIND_TARGET_S390X 1 +#define _LIBUNWIND_TARGET_LOONGARCH 1 # define _LIBUNWIND_CONTEXT_SIZE 167 # define _LIBUNWIND_CURSOR_SIZE 179 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 diff --git a/lib/libunwind/include/libunwind.h b/lib/libunwind/include/libunwind.h index f878b46f03..d2ad5ab871 100644 --- a/lib/libunwind/include/libunwind.h +++ b/lib/libunwind/include/libunwind.h @@ -1023,6 +1023,16 @@ enum { UNW_RISCV_F29 = 61, UNW_RISCV_F30 = 62, UNW_RISCV_F31 = 63, + // 65-95 -- Reserved for future standard extensions + // 96-127 -- v0-v31 (Vector registers) + // 128-3071 -- Reserved for future standard extensions + // 3072-4095 -- Reserved for custom extensions + // 4096-8191 -- CSRs + // + // VLENB CSR number: 0xC22 -- defined by section 3 of v-spec: + // https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#3-vector-extension-programmers-model + // VLENB DWARF number: 0x1000 + 0xC22 + UNW_RISCV_VLENB = 0x1C22, }; // VE register numbers @@ -1219,4 +1229,72 @@ enum { // 68-83 Vector Registers %v16-%v31 }; +// LoongArch registers. +enum { + UNW_LOONGARCH_R0 = 0, + UNW_LOONGARCH_R1 = 1, + UNW_LOONGARCH_R2 = 2, + UNW_LOONGARCH_R3 = 3, + UNW_LOONGARCH_R4 = 4, + UNW_LOONGARCH_R5 = 5, + UNW_LOONGARCH_R6 = 6, + UNW_LOONGARCH_R7 = 7, + UNW_LOONGARCH_R8 = 8, + UNW_LOONGARCH_R9 = 9, + UNW_LOONGARCH_R10 = 10, + UNW_LOONGARCH_R11 = 11, + UNW_LOONGARCH_R12 = 12, + UNW_LOONGARCH_R13 = 13, + UNW_LOONGARCH_R14 = 14, + UNW_LOONGARCH_R15 = 15, + UNW_LOONGARCH_R16 = 16, + UNW_LOONGARCH_R17 = 17, + UNW_LOONGARCH_R18 = 18, + UNW_LOONGARCH_R19 = 19, + UNW_LOONGARCH_R20 = 20, + UNW_LOONGARCH_R21 = 21, + UNW_LOONGARCH_R22 = 22, + UNW_LOONGARCH_R23 = 23, + UNW_LOONGARCH_R24 = 24, + UNW_LOONGARCH_R25 = 25, + UNW_LOONGARCH_R26 = 26, + UNW_LOONGARCH_R27 = 27, + UNW_LOONGARCH_R28 = 28, + UNW_LOONGARCH_R29 = 29, + UNW_LOONGARCH_R30 = 30, + UNW_LOONGARCH_R31 = 31, + UNW_LOONGARCH_F0 = 32, + UNW_LOONGARCH_F1 = 33, + UNW_LOONGARCH_F2 = 34, + UNW_LOONGARCH_F3 = 35, + UNW_LOONGARCH_F4 = 36, + UNW_LOONGARCH_F5 = 37, + UNW_LOONGARCH_F6 = 38, + UNW_LOONGARCH_F7 = 39, + UNW_LOONGARCH_F8 = 40, + UNW_LOONGARCH_F9 = 41, + UNW_LOONGARCH_F10 = 42, + UNW_LOONGARCH_F11 = 43, + UNW_LOONGARCH_F12 = 44, + UNW_LOONGARCH_F13 = 45, + UNW_LOONGARCH_F14 = 46, + UNW_LOONGARCH_F15 = 47, + UNW_LOONGARCH_F16 = 48, + UNW_LOONGARCH_F17 = 49, + UNW_LOONGARCH_F18 = 50, + UNW_LOONGARCH_F19 = 51, + UNW_LOONGARCH_F20 = 52, + UNW_LOONGARCH_F21 = 53, + UNW_LOONGARCH_F22 = 54, + UNW_LOONGARCH_F23 = 55, + UNW_LOONGARCH_F24 = 56, + UNW_LOONGARCH_F25 = 57, + UNW_LOONGARCH_F26 = 58, + UNW_LOONGARCH_F27 = 59, + UNW_LOONGARCH_F28 = 60, + UNW_LOONGARCH_F29 = 61, + UNW_LOONGARCH_F30 = 62, + UNW_LOONGARCH_F31 = 63, +}; + #endif diff --git a/lib/libunwind/include/mach-o/compact_unwind_encoding.h b/lib/libunwind/include/mach-o/compact_unwind_encoding.h index 68d562eec4..2dd857e45b 100644 --- a/lib/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/lib/libunwind/include/mach-o/compact_unwind_encoding.h @@ -33,7 +33,7 @@ // -// The compact unwind endoding is a 32-bit value which encoded in an +// The compact unwind encoding is a 32-bit value which encoded in an // architecture specific way, which registers to restore from where, and how // to unwind out of the function. // @@ -116,7 +116,7 @@ enum { // on the stack immediately after the return address. The stack_size/4 is // encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024). // The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT. -// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were +// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were // saved and their order. // UNWIND_X86_MODE_STACK_IND: // A "frameless" (EBP not used as frame pointer) function large constant @@ -250,7 +250,7 @@ enum { // on the stack immediately after the return address. The stack_size/8 is // encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048). // The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT. -// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were +// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were // saved and their order. // UNWIND_X86_64_MODE_STACK_IND: // A "frameless" (RBP not used as frame pointer) function large constant diff --git a/lib/libunwind/include/unwind.h b/lib/libunwind/include/unwind.h index 6557374fa9..26cdef2220 100644 --- a/lib/libunwind/include/unwind.h +++ b/lib/libunwind/include/unwind.h @@ -93,7 +93,7 @@ extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc); #endif // -// The following are semi-suppoted extensions to the C++ ABI +// The following are semi-supported extensions to the C++ ABI // // diff --git a/lib/libunwind/src/AddressSpace.hpp b/lib/libunwind/src/AddressSpace.hpp index 36c9f5a9e3..26d289068b 100644 --- a/lib/libunwind/src/AddressSpace.hpp +++ b/lib/libunwind/src/AddressSpace.hpp @@ -246,7 +246,7 @@ inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { const uint8_t *p = (uint8_t *)addr; const uint8_t *pend = (uint8_t *)end; - int64_t result = 0; + uint64_t result = 0; int bit = 0; uint8_t byte; do { @@ -260,7 +260,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { if ((byte & 0x40) != 0 && bit < 64) result |= (-1ULL) << bit; addr = (pint_t) p; - return result; + return (int64_t)result; } inline LocalAddressSpace::pint_t @@ -373,28 +373,6 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, typedef ElfW(Addr) Elf_Addr; #endif -static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) { - Elf_Addr image_base = pinfo->dlpi_addr; -#if defined(__ANDROID__) && __ANDROID_API__ < 18 - if (image_base == 0) { - // Normally, an image base of 0 indicates a non-PIE executable. On - // versions of Android prior to API 18, the dynamic linker reported a - // dlpi_addr of 0 for PIE executables. Compute the true image base - // using the PT_PHDR segment. - // See https://github.com/android/ndk/issues/505. - for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { - const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; - if (phdr->p_type == PT_PHDR) { - image_base = reinterpret_cast(pinfo->dlpi_phdr) - - phdr->p_vaddr; - break; - } - } - } -#endif - return image_base; -} - struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { LocalAddressSpace *addressSpace; UnwindInfoSections *sects; @@ -468,7 +446,7 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, (void)pinfo_size; #endif - Elf_Addr image_base = calculateImageBase(pinfo); + Elf_Addr image_base = pinfo->dlpi_addr; // Most shared objects seen in this callback function likely don't contain the // target address, so optimize for that. Scan for a matching PT_LOAD segment @@ -601,6 +579,56 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, if (info.arm_section && info.arm_section_length) return true; #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) + // Use DLFO_STRUCT_HAS_EH_DBASE to determine the existence of + // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind + // support for _dl_find_object on other unwind formats is not implemented, + // yet. +#if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + // We expect `_dl_find_object` to return PT_GNU_EH_FRAME. +#if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME +#error _dl_find_object retrieves an unexpected section type +#endif + // We look-up `dl_find_object` dynamically at runtime to ensure backwards + // compatibility with earlier version of glibc not yet providing it. On older + // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer + // so we only look it up once. Do manual lock to avoid _cxa_guard_acquire. + static decltype(_dl_find_object) *dlFindObject; + static bool dlFindObjectChecked = false; + if (!dlFindObjectChecked) { + dlFindObject = reinterpret_cast( + dlsym(RTLD_DEFAULT, "_dl_find_object")); + dlFindObjectChecked = true; + } + // Try to find the unwind info using `dl_find_object` + dl_find_object findResult; + if (dlFindObject && dlFindObject((void *)targetAddr, &findResult) == 0) { + if (findResult.dlfo_eh_frame == nullptr) { + // Found an entry for `targetAddr`, but there is no unwind info. + return false; + } + info.dso_base = reinterpret_cast(findResult.dlfo_map_start); + info.text_segment_length = static_cast( + (char *)findResult.dlfo_map_end - (char *)findResult.dlfo_map_start); + + // Record the start of PT_GNU_EH_FRAME. + info.dwarf_index_section = + reinterpret_cast(findResult.dlfo_eh_frame); + // `_dl_find_object` does not give us the size of PT_GNU_EH_FRAME. + // Setting length to `SIZE_MAX` effectively disables all range checks. + info.dwarf_index_section_length = SIZE_MAX; + EHHeaderParser::EHHeaderInfo hdrInfo; + if (!EHHeaderParser::decodeEHHdr( + *this, info.dwarf_index_section, info.dwarf_index_section_length, + hdrInfo)) { + return false; + } + // Record the start of the FDE and use SIZE_MAX to indicate that we do + // not know the end address. + info.dwarf_section = hdrInfo.eh_frame_ptr; + info.dwarf_section_length = SIZE_MAX; + return true; + } +#endif dl_iterate_cb_data cb_data = {this, &info, targetAddr}; int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); return static_cast(found); diff --git a/lib/libunwind/src/CompactUnwinder.hpp b/lib/libunwind/src/CompactUnwinder.hpp index 0b2b5e111b..a7a8a153d8 100644 --- a/lib/libunwind/src/CompactUnwinder.hpp +++ b/lib/libunwind/src/CompactUnwinder.hpp @@ -19,6 +19,7 @@ #include #include "Registers.hpp" +#include "libunwind_ext.h" #define EXTRACT_BITS(value, mask) \ ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) diff --git a/lib/libunwind/src/DwarfInstructions.hpp b/lib/libunwind/src/DwarfInstructions.hpp index cee4ea53da..27432be561 100644 --- a/lib/libunwind/src/DwarfInstructions.hpp +++ b/lib/libunwind/src/DwarfInstructions.hpp @@ -16,16 +16,17 @@ #include #include -#include "dwarf2.h" -#include "Registers.hpp" #include "DwarfParser.hpp" +#include "Registers.hpp" #include "config.h" +#include "dwarf2.h" +#include "libunwind_ext.h" namespace libunwind { -/// DwarfInstructions maps abtract DWARF unwind instructions to a particular +/// DwarfInstructions maps abstract DWARF unwind instructions to a particular /// architecture template class DwarfInstructions { @@ -34,7 +35,7 @@ public: typedef typename A::sint_t sint_t; static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, - R ®isters, bool &isSignalFrame); + R ®isters, bool &isSignalFrame, bool stage2); private: @@ -189,7 +190,7 @@ bool DwarfInstructions::getRA_SIGN_STATE(A &addressSpace, R registers, template int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, R ®isters, - bool &isSignalFrame) { + bool &isSignalFrame, bool stage2) { FDE_Info fdeInfo; CIE_Info cieInfo; if (CFI_Parser::decodeFDE(addressSpace, fdeStart, &fdeInfo, @@ -200,7 +201,38 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // get pointer to cfa (architecture specific) pint_t cfa = getCFA(addressSpace, prolog, registers); - // restore registers that DWARF says were saved + (void)stage2; + // __unw_step_stage2 is not used for cross unwinding, so we use + // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are + // building for AArch64 natively. +#if defined(__aarch64__) + if (stage2 && cieInfo.mteTaggedFrame) { + pint_t sp = registers.getSP(); + pint_t p = sp; + // AArch64 doesn't require the value of SP to be 16-byte aligned at + // all times, only at memory accesses and public interfaces [1]. Thus, + // a signal could arrive at a point where SP is not aligned properly. + // In that case, the kernel fixes up [2] the signal frame, but we + // still have a misaligned SP in the previous frame. If that signal + // handler caused stack unwinding, we would have an unaligned SP. + // We do not need to fix up the CFA, as that is the SP at a "public + // interface". + // [1]: + // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack + // [2]: + // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718 + p &= ~0xfULL; + // CFA is the bottom of the current stack frame. + for (; p < cfa; p += 16) { + __asm__ __volatile__(".arch_extension memtag\n" + "stg %[Ptr], [%[Ptr]]\n" + : + : [Ptr] "r"(p) + : "memory"); + } + } +#endif + // restore registers that DWARF says were saved R newRegisters = registers; // Typically, the CFA is the stack pointer at the call site in @@ -241,7 +273,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, return UNW_EBADREG; } else if (i == (int)cieInfo.returnAddressRegister) { // Leaf function keeps the return address in register and there is no - // explicit intructions how to restore it. + // explicit instructions how to restore it. returnAddress = registers.getRegister(cieInfo.returnAddressRegister); } } @@ -331,7 +363,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, #endif // Return address is address after call site instruction, so setting IP to - // that does simualates a return. + // that does simulates a return. newRegisters.setIP(returnAddress); // Simulate the step by replacing the register set with the new ones. @@ -635,7 +667,7 @@ DwarfInstructions::evaluateExpression(pint_t expression, A &addressSpace, svalue = (sint_t)*sp; *sp = (pint_t)(svalue >> value); if (log) - fprintf(stderr, "shift left arithmetric\n"); + fprintf(stderr, "shift left arithmetic\n"); break; case DW_OP_xor: diff --git a/lib/libunwind/src/DwarfParser.hpp b/lib/libunwind/src/DwarfParser.hpp index b5a53166fc..0682942ce1 100644 --- a/lib/libunwind/src/DwarfParser.hpp +++ b/lib/libunwind/src/DwarfParser.hpp @@ -51,6 +51,7 @@ public: uint8_t returnAddressRegister; #if defined(_LIBUNWIND_TARGET_AARCH64) bool addressesSignedWithBKey; + bool mteTaggedFrame; #endif }; @@ -325,6 +326,7 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, cieInfo->fdesHaveAugmentationData = false; #if defined(_LIBUNWIND_TARGET_AARCH64) cieInfo->addressesSignedWithBKey = false; + cieInfo->mteTaggedFrame = false; #endif cieInfo->cieStart = cie; pint_t p = cie; @@ -353,7 +355,7 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, while (addressSpace.get8(p) != 0) ++p; ++p; - // parse code aligment factor + // parse code alignment factor cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd); // parse data alignment factor cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); @@ -394,6 +396,9 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, case 'B': cieInfo->addressesSignedWithBKey = true; break; + case 'G': + cieInfo->mteTaggedFrame = true; + break; #endif default: // ignore unknown letters @@ -407,7 +412,7 @@ const char *CFI_Parser::parseCIE(A &addressSpace, pint_t cie, } -/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE +/// "run" the DWARF instructions and create the abstract PrologInfo for an FDE template bool CFI_Parser::parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, diff --git a/lib/libunwind/src/Registers.hpp b/lib/libunwind/src/Registers.hpp index 98adb78940..c7b875d74a 100644 --- a/lib/libunwind/src/Registers.hpp +++ b/lib/libunwind/src/Registers.hpp @@ -40,6 +40,7 @@ enum { REGISTERS_RISCV, REGISTERS_VE, REGISTERS_S390X, + REGISTERS_LOONGARCH, }; #if defined(_LIBUNWIND_TARGET_I386) @@ -4003,7 +4004,7 @@ typedef float fp_t; # error "Unsupported __riscv_flen" # endif # else -// This is just for supressing undeclared error of fp_t. +// This is just for suppressing undeclared error of fp_t. typedef double fp_t; # endif # else @@ -4084,6 +4085,8 @@ inline bool Registers_riscv::validRegister(int regNum) const { return true; if (regNum < 0) return false; + if (regNum == UNW_RISCV_VLENB) + return true; if (regNum > UNW_RISCV_F31) return false; return true; @@ -4098,6 +4101,11 @@ inline reg_t Registers_riscv::getRegister(int regNum) const { return 0; if ((regNum > 0) && (regNum < 32)) return _registers[regNum]; + if (regNum == UNW_RISCV_VLENB) { + reg_t vlenb; + __asm__("csrr %0, 0xC22" : "=r"(vlenb)); + return vlenb; + } _LIBUNWIND_ABORT("unsupported riscv register"); } @@ -4249,6 +4257,8 @@ inline const char *Registers_riscv::getRegisterName(int regNum) { return "ft10"; case UNW_RISCV_F31: return "ft11"; + case UNW_RISCV_VLENB: + return "vlenb"; default: return "unknown register"; } @@ -5031,6 +5041,271 @@ inline const char *Registers_s390x::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_S390X +#if defined(_LIBUNWIND_TARGET_LOONGARCH) +/// Registers_loongarch holds the register state of a thread in a 64-bit +/// LoongArch process. +class _LIBUNWIND_HIDDEN Registers_loongarch { +public: + Registers_loongarch(); + Registers_loongarch(const void *registers); + + bool validRegister(int num) const; + uint64_t getRegister(int num) const; + void setRegister(int num, uint64_t value); + bool validFloatRegister(int num) const; + double getFloatRegister(int num) const; + void setFloatRegister(int num, double value); + bool validVectorRegister(int num) const; + v128 getVectorRegister(int num) const; + void setVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + void jumpto(); + static constexpr int lastDwarfRegNum() { + return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH; + } + static int getArch() { return REGISTERS_LOONGARCH; } + + uint64_t getSP() const { return _registers.__r[3]; } + void setSP(uint64_t value) { _registers.__r[3] = value; } + uint64_t getIP() const { return _registers.__pc; } + void setIP(uint64_t value) { _registers.__pc = value; } + +private: + struct loongarch_thread_state_t { + uint64_t __r[32]; + uint64_t __pc; + }; + + loongarch_thread_state_t _registers; +#if __loongarch_frlen == 64 + double _floats[32]; +#endif +}; + +inline Registers_loongarch::Registers_loongarch(const void *registers) { + static_assert((check_fit::does_fit), + "loongarch registers do not fit into unw_context_t"); + memcpy(&_registers, registers, sizeof(_registers)); + static_assert(sizeof(_registers) == 0x108, + "expected float registers to be at offset 264"); +#if __loongarch_frlen == 64 + memcpy(_floats, static_cast(registers) + sizeof(_registers), + sizeof(_floats)); +#endif +} + +inline Registers_loongarch::Registers_loongarch() { + memset(&_registers, 0, sizeof(_registers)); +#if __loongarch_frlen == 64 + memset(&_floats, 0, sizeof(_floats)); +#endif +} + +inline bool Registers_loongarch::validRegister(int regNum) const { + if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) + return true; + if (regNum < 0 || regNum > UNW_LOONGARCH_F31) + return false; + return true; +} + +inline uint64_t Registers_loongarch::getRegister(int regNum) const { + if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) + return _registers.__r[regNum - UNW_LOONGARCH_R0]; + + if (regNum == UNW_REG_IP) + return _registers.__pc; + if (regNum == UNW_REG_SP) + return _registers.__r[3]; + _LIBUNWIND_ABORT("unsupported loongarch register"); +} + +inline void Registers_loongarch::setRegister(int regNum, uint64_t value) { + if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) + _registers.__r[regNum - UNW_LOONGARCH_R0] = value; + else if (regNum == UNW_REG_IP) + _registers.__pc = value; + else if (regNum == UNW_REG_SP) + _registers.__r[3] = value; + else + _LIBUNWIND_ABORT("unsupported loongarch register"); +} + +inline const char *Registers_loongarch::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "$pc"; + case UNW_REG_SP: + return "$sp"; + case UNW_LOONGARCH_R0: + return "$r0"; + case UNW_LOONGARCH_R1: + return "$r1"; + case UNW_LOONGARCH_R2: + return "$r2"; + case UNW_LOONGARCH_R3: + return "$r3"; + case UNW_LOONGARCH_R4: + return "$r4"; + case UNW_LOONGARCH_R5: + return "$r5"; + case UNW_LOONGARCH_R6: + return "$r6"; + case UNW_LOONGARCH_R7: + return "$r7"; + case UNW_LOONGARCH_R8: + return "$r8"; + case UNW_LOONGARCH_R9: + return "$r9"; + case UNW_LOONGARCH_R10: + return "$r10"; + case UNW_LOONGARCH_R11: + return "$r11"; + case UNW_LOONGARCH_R12: + return "$r12"; + case UNW_LOONGARCH_R13: + return "$r13"; + case UNW_LOONGARCH_R14: + return "$r14"; + case UNW_LOONGARCH_R15: + return "$r15"; + case UNW_LOONGARCH_R16: + return "$r16"; + case UNW_LOONGARCH_R17: + return "$r17"; + case UNW_LOONGARCH_R18: + return "$r18"; + case UNW_LOONGARCH_R19: + return "$r19"; + case UNW_LOONGARCH_R20: + return "$r20"; + case UNW_LOONGARCH_R21: + return "$r21"; + case UNW_LOONGARCH_R22: + return "$r22"; + case UNW_LOONGARCH_R23: + return "$r23"; + case UNW_LOONGARCH_R24: + return "$r24"; + case UNW_LOONGARCH_R25: + return "$r25"; + case UNW_LOONGARCH_R26: + return "$r26"; + case UNW_LOONGARCH_R27: + return "$r27"; + case UNW_LOONGARCH_R28: + return "$r28"; + case UNW_LOONGARCH_R29: + return "$r29"; + case UNW_LOONGARCH_R30: + return "$r30"; + case UNW_LOONGARCH_R31: + return "$r31"; + case UNW_LOONGARCH_F0: + return "$f0"; + case UNW_LOONGARCH_F1: + return "$f1"; + case UNW_LOONGARCH_F2: + return "$f2"; + case UNW_LOONGARCH_F3: + return "$f3"; + case UNW_LOONGARCH_F4: + return "$f4"; + case UNW_LOONGARCH_F5: + return "$f5"; + case UNW_LOONGARCH_F6: + return "$f6"; + case UNW_LOONGARCH_F7: + return "$f7"; + case UNW_LOONGARCH_F8: + return "$f8"; + case UNW_LOONGARCH_F9: + return "$f9"; + case UNW_LOONGARCH_F10: + return "$f10"; + case UNW_LOONGARCH_F11: + return "$f11"; + case UNW_LOONGARCH_F12: + return "$f12"; + case UNW_LOONGARCH_F13: + return "$f13"; + case UNW_LOONGARCH_F14: + return "$f14"; + case UNW_LOONGARCH_F15: + return "$f15"; + case UNW_LOONGARCH_F16: + return "$f16"; + case UNW_LOONGARCH_F17: + return "$f17"; + case UNW_LOONGARCH_F18: + return "$f18"; + case UNW_LOONGARCH_F19: + return "$f19"; + case UNW_LOONGARCH_F20: + return "$f20"; + case UNW_LOONGARCH_F21: + return "$f21"; + case UNW_LOONGARCH_F22: + return "$f22"; + case UNW_LOONGARCH_F23: + return "$f23"; + case UNW_LOONGARCH_F24: + return "$f24"; + case UNW_LOONGARCH_F25: + return "$f25"; + case UNW_LOONGARCH_F26: + return "$f26"; + case UNW_LOONGARCH_F27: + return "$f27"; + case UNW_LOONGARCH_F28: + return "$f28"; + case UNW_LOONGARCH_F29: + return "$f29"; + case UNW_LOONGARCH_F30: + return "$f30"; + case UNW_LOONGARCH_F31: + return "$f31"; + default: + return "unknown register"; + } +} + +inline bool Registers_loongarch::validFloatRegister(int regNum) const { + if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31) + return false; + return true; +} + +inline double Registers_loongarch::getFloatRegister(int regNum) const { +#if __loongarch_frlen == 64 + assert(validFloatRegister(regNum)); + return _floats[regNum - UNW_LOONGARCH_F0]; +#else + _LIBUNWIND_ABORT("libunwind not built with float support"); +#endif +} + +inline void Registers_loongarch::setFloatRegister(int regNum, double value) { +#if __loongarch_frlen == 64 + assert(validFloatRegister(regNum)); + _floats[regNum - UNW_LOONGARCH_F0] = value; +#else + _LIBUNWIND_ABORT("libunwind not built with float support"); +#endif +} + +inline bool Registers_loongarch::validVectorRegister(int) const { + return false; +} + +inline v128 Registers_loongarch::getVectorRegister(int) const { + _LIBUNWIND_ABORT("loongarch vector support not implemented"); +} + +inline void Registers_loongarch::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("loongarch vector support not implemented"); +} +#endif //_LIBUNWIND_TARGET_LOONGARCH } // namespace libunwind diff --git a/lib/libunwind/src/Unwind-EHABI.cpp b/lib/libunwind/src/Unwind-EHABI.cpp index f203887567..95701823bc 100644 --- a/lib/libunwind/src/Unwind-EHABI.cpp +++ b/lib/libunwind/src/Unwind-EHABI.cpp @@ -235,7 +235,7 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { } else { // 6.3: ARM Compact Model // - // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded + // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeed // by format: Descriptor::Format format = static_cast((*data & 0x0f000000) >> 24); @@ -845,7 +845,7 @@ _LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) { /// may force a jump to a landing pad in that function, the landing /// pad code may then call _Unwind_Resume() to continue with the /// unwinding. Note: the call to _Unwind_Resume() is from compiler -/// geneated user code. All other _Unwind_* routines are called +/// generated user code. All other _Unwind_* routines are called /// by the C++ runtime __cxa_* routines. /// /// Note: re-throwing an exception (as opposed to continuing the unwind) diff --git a/lib/libunwind/src/Unwind-seh.cpp b/lib/libunwind/src/Unwind-seh.cpp index c2c31045a3..d08c29c213 100644 --- a/lib/libunwind/src/Unwind-seh.cpp +++ b/lib/libunwind/src/Unwind-seh.cpp @@ -137,7 +137,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, // If we were called by __libunwind_seh_personality(), indicate that // a handler was found; otherwise, initiate phase 2 by unwinding. if (ours && ms_exc->NumberParameters > 1) - return 4 /* ExecptionExecuteHandler in mingw */; + return 4 /* ExceptionExecuteHandler in mingw */; // This should never happen in phase 2. if (IS_UNWINDING(ms_exc->ExceptionFlags)) _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!"); @@ -155,7 +155,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, // a handler was found; otherwise, it's time to initiate a collided // unwind to the target. if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) - return 4 /* ExecptionExecuteHandler in mingw */; + return 4 /* ExceptionExecuteHandler in mingw */; // This should never happen in phase 1. if (!IS_UNWINDING(ms_exc->ExceptionFlags)) _LIBUNWIND_ABORT("Personality installed context during phase 1!"); @@ -354,7 +354,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) { /// may force a jump to a landing pad in that function; the landing /// pad code may then call \c _Unwind_Resume() to continue with the /// unwinding. Note: the call to \c _Unwind_Resume() is from compiler -/// geneated user code. All other \c _Unwind_* routines are called +/// generated user code. All other \c _Unwind_* routines are called /// by the C++ runtime \c __cxa_* routines. /// /// Note: re-throwing an exception (as opposed to continuing the unwind) diff --git a/lib/libunwind/src/Unwind-sjlj.c b/lib/libunwind/src/Unwind-sjlj.c index d487995bb7..90a55fd29d 100644 --- a/lib/libunwind/src/Unwind-sjlj.c +++ b/lib/libunwind/src/Unwind-sjlj.c @@ -33,7 +33,7 @@ struct _Unwind_FunctionContext { struct _Unwind_FunctionContext *prev; #if defined(__ve__) - // VE requires to store 64 bit pointers in the buffer for SjLj execption. + // VE requires to store 64 bit pointers in the buffer for SjLj exception. // We expand the size of values defined here. This size must be matched // to the size returned by TargetMachine::getSjLjDataSize(). @@ -357,7 +357,7 @@ _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) { /// may force a jump to a landing pad in that function, the landing /// pad code may then call _Unwind_Resume() to continue with the /// unwinding. Note: the call to _Unwind_Resume() is from compiler -/// geneated user code. All other _Unwind_* routines are called +/// generated user code. All other _Unwind_* routines are called /// by the C++ runtime __cxa_* routines. /// /// Re-throwing an exception is implemented by having the code call @@ -394,7 +394,7 @@ _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) { // std::terminate() } - // Call through to _Unwind_Resume() which distiguishes between forced and + // Call through to _Unwind_Resume() which distinguishes between forced and // regular exceptions. _Unwind_SjLj_Resume(exception_object); _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called " diff --git a/lib/libunwind/src/UnwindCursor.hpp b/lib/libunwind/src/UnwindCursor.hpp index b8bd9bc590..0c6cda3604 100644 --- a/lib/libunwind/src/UnwindCursor.hpp +++ b/lib/libunwind/src/UnwindCursor.hpp @@ -38,6 +38,17 @@ #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 #endif +#include "AddressSpace.hpp" +#include "CompactUnwinder.hpp" +#include "config.h" +#include "DwarfInstructions.hpp" +#include "EHHeaderParser.hpp" +#include "libunwind.h" +#include "libunwind_ext.h" +#include "Registers.hpp" +#include "RWMutex.hpp" +#include "Unwind-EHABI.h" + #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and // earlier) SDKs. @@ -75,18 +86,6 @@ extern "C" _Unwind_Reason_Code __libunwind_seh_personality( #endif -#include "config.h" - -#include "AddressSpace.hpp" -#include "CompactUnwinder.hpp" -#include "config.h" -#include "DwarfInstructions.hpp" -#include "EHHeaderParser.hpp" -#include "libunwind.h" -#include "Registers.hpp" -#include "RWMutex.hpp" -#include "Unwind-EHABI.h" - namespace libunwind { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) @@ -443,7 +442,7 @@ public: virtual void setFloatReg(int, unw_fpreg_t) { _LIBUNWIND_ABORT("setFloatReg not implemented"); } - virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } + virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); } virtual void getInfo(unw_proc_info_t *) { _LIBUNWIND_ABORT("getInfo not implemented"); } @@ -495,7 +494,7 @@ public: virtual bool validFloatReg(int); virtual unw_fpreg_t getFloatReg(int); virtual void setFloatReg(int, unw_fpreg_t); - virtual int step(); + virtual int step(bool = false); virtual void getInfo(unw_proc_info_t *); virtual void jumpto(); virtual bool isSignalFrame(); @@ -510,7 +509,7 @@ public: void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; } // libunwind does not and should not depend on C++ library which means that we - // need our own defition of inline placement new. + // need our own definition of inline placement new. static void *operator new(size_t, UnwindCursor *p) { return p; } private: @@ -926,7 +925,7 @@ public: virtual bool validFloatReg(int); virtual unw_fpreg_t getFloatReg(int); virtual void setFloatReg(int, unw_fpreg_t); - virtual int step(); + virtual int step(bool stage2 = false); virtual void getInfo(unw_proc_info_t *); virtual void jumpto(); virtual bool isSignalFrame(); @@ -946,7 +945,7 @@ public: #endif // libunwind does not and should not depend on C++ library which means that we - // need our own defition of inline placement new. + // need our own definition of inline placement new. static void *operator new(size_t, UnwindCursor *p) { return p; } private: @@ -1000,22 +999,21 @@ private: pint_t pc, uintptr_t dso_base); bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint=0); - int stepWithDwarfFDE() { - return DwarfInstructions::stepWithDwarf(_addressSpace, - (pint_t)this->getReg(UNW_REG_IP), - (pint_t)_info.unwind_info, - _registers, _isSignalFrame); + int stepWithDwarfFDE(bool stage2) { + return DwarfInstructions::stepWithDwarf( + _addressSpace, (pint_t)this->getReg(UNW_REG_IP), + (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2); } #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) bool getInfoFromCompactEncodingSection(pint_t pc, const UnwindInfoSections §s); - int stepWithCompactEncoding() { - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + int stepWithCompactEncoding(bool stage2 = false) { +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) if ( compactSaysUseDwarf() ) - return stepWithDwarfFDE(); - #endif + return stepWithDwarfFDE(stage2); +#endif R dummy; return stepWithCompactEncoding(dummy); } @@ -1066,6 +1064,10 @@ private: } #endif +#if defined(_LIBUNWIND_TARGET_LOONGARCH) + int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; } +#endif + #if defined(_LIBUNWIND_TARGET_SPARC) int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } #endif @@ -1142,6 +1144,12 @@ private: } #endif +#if defined(_LIBUNWIND_TARGET_LOONGARCH) + bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const { + return true; + } +#endif + #if defined(_LIBUNWIND_TARGET_SPARC) bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } #endif @@ -1226,6 +1234,12 @@ private: } #endif +#if defined(_LIBUNWIND_TARGET_LOONGARCH) + compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const { + return 0; + } +#endif + #if defined(_LIBUNWIND_TARGET_SPARC) compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } #endif @@ -2106,6 +2120,11 @@ bool UnwindCursor::getInfoFromTBTable(pint_t pc, R ®isters) { // using dlopen(). const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)"; void *libHandle; + // The AIX dlopen() sets errno to 0 when it is successful, which + // clobbers the value of errno from the user code. This is an AIX + // bug because according to POSIX it should not set errno to 0. To + // workaround before AIX fixes the bug, errno is saved and restored. + int saveErrno = errno; libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW); if (libHandle == NULL) { _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", @@ -2119,6 +2138,7 @@ bool UnwindCursor::getInfoFromTBTable(pint_t pc, R ®isters) { assert(0 && "dlsym() failed"); } dlclose(libHandle); + errno = saveErrno; } } xlcPersonalityV0InitLock.unlock(); @@ -2455,7 +2475,7 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, reinterpret_cast(pc)); // The return address is the address after call site instruction, so - // setting IP to that simualates a return. + // setting IP to that simulates a return. newRegisters.setIP(reinterpret_cast(returnAddress)); // Simulate the step by replacing the register set with the new ones. @@ -2791,8 +2811,8 @@ int UnwindCursor::stepThroughSigReturn(Registers_s390x &) { #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && // defined(_LIBUNWIND_TARGET_S390X) -template -int UnwindCursor::step() { +template int UnwindCursor::step(bool stage2) { + (void)stage2; // Bottom of stack is defined is when unwind info cannot be found. if (_unwindInfoMissing) return UNW_STEP_END; @@ -2806,13 +2826,13 @@ int UnwindCursor::step() { #endif { #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) - result = this->stepWithCompactEncoding(); + result = this->stepWithCompactEncoding(stage2); #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) result = this->stepWithSEHData(); #elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) result = this->stepWithTBTableData(); #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - result = this->stepWithDwarfFDE(); + result = this->stepWithDwarfFDE(stage2); #elif defined(_LIBUNWIND_ARM_EHABI) result = this->stepWithEHABI(); #else diff --git a/lib/libunwind/src/UnwindLevel1-gcc-ext.c b/lib/libunwind/src/UnwindLevel1-gcc-ext.c index 0250664bbc..efb872bbe5 100644 --- a/lib/libunwind/src/UnwindLevel1-gcc-ext.c +++ b/lib/libunwind/src/UnwindLevel1-gcc-ext.c @@ -22,6 +22,10 @@ #include "Unwind-EHABI.h" #include "unwind.h" +#if defined(_AIX) +#include +#endif + #if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) @@ -48,7 +52,7 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { // std::terminate(). } - // Call through to _Unwind_Resume() which distiguishes between forced and + // Call through to _Unwind_Resume() which distinguishes between forced and // regular exceptions. _Unwind_Resume(exception_object); _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" @@ -82,6 +86,32 @@ _Unwind_GetTextRelBase(struct _Unwind_Context *context) { /// specified code address "pc". _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc); +#if defined(_AIX) + if (pc == NULL) + return NULL; + + // Get the start address of the enclosing function from the function's + // traceback table. + uint32_t *p = (uint32_t *)pc; + + // Keep looking forward until a word of 0 is found. The traceback + // table starts at the following word. + while (*p) + ++p; + struct tbtable *TBTable = (struct tbtable *)(p + 1); + + // Get the address of the traceback table extension. + p = (uint32_t *)&TBTable->tb_ext; + + // Skip field parminfo if it exists. + if (TBTable->tb.fixedparms || TBTable->tb.floatparms) + ++p; + + if (TBTable->tb.has_tboff) + // *p contains the offset from the function start to traceback table. + return (void *)((uintptr_t)TBTable - *p - sizeof(uint32_t)); + return NULL; +#else // This is slow, but works. // We create an unwind cursor then alter the IP to be pc unw_cursor_t cursor; @@ -94,6 +124,7 @@ _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { return (void *)(intptr_t) info.start_ip; else return NULL; +#endif } /// Walk every frame and call trace function at each one. If trace function diff --git a/lib/libunwind/src/UnwindLevel1.c b/lib/libunwind/src/UnwindLevel1.c index 84f865e591..7e9adf6424 100644 --- a/lib/libunwind/src/UnwindLevel1.c +++ b/lib/libunwind/src/UnwindLevel1.c @@ -41,7 +41,7 @@ // 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 +// directly jump to __libunwind_Registers_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) \ @@ -50,6 +50,7 @@ __unw_resume((cursor)); \ } while (0) #elif defined(_LIBUNWIND_TARGET_I386) +#define __cet_ss_step_size 4 #define __unw_phase2_resume(cursor, fn) \ do { \ _LIBUNWIND_POP_CET_SSP((fn)); \ @@ -61,6 +62,7 @@ "d"(cetJumpAddress)); \ } while (0) #elif defined(_LIBUNWIND_TARGET_X86_64) +#define __cet_ss_step_size 8 #define __unw_phase2_resume(cursor, fn) \ do { \ _LIBUNWIND_POP_CET_SSP((fn)); \ @@ -82,13 +84,13 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except int stepResult = __unw_step(cursor); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): __unw_step() reached " + "unwind_phase1(ex_obj=%p): __unw_step() reached " "bottom => _URC_END_OF_STACK", (void *)exception_object); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): __unw_step failed => " + "unwind_phase1(ex_obj=%p): __unw_step failed => " "_URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; @@ -99,7 +101,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except unw_word_t sp; if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): __unw_get_proc_info " + "unwind_phase1(ex_obj=%p): __unw_get_proc_info " "failed => _URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; @@ -118,7 +120,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except unw_word_t pc; __unw_get_reg(cursor, UNW_REG_IP, &pc); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR + "unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "", (void *)exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); @@ -131,7 +133,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except _Unwind_Personality_Fn p = (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): calling personality function %p", + "unwind_phase1(ex_obj=%p): calling personality function %p", (void *)exception_object, (void *)(uintptr_t)p); _Unwind_Reason_Code personalityResult = (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, @@ -143,13 +145,13 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except __unw_get_reg(cursor, UNW_REG_SP, &sp); exception_object->private_2 = (uintptr_t)sp; _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", + "unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND", (void *)exception_object); return _URC_NO_REASON; case _URC_CONTINUE_UNWIND: _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", + "unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND", (void *)exception_object); // continue unwinding break; @@ -157,7 +159,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except default: // something went wrong _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", + "unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE1_ERROR; } @@ -165,33 +167,36 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except } return _URC_NO_REASON; } - +extern int __unw_step_stage2(unw_cursor_t *); static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { __unw_init_local(cursor, uc); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%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; +#ifdef _LIBUNWIND_USE_CET + unsigned long shadowStackTop = _get_ssp(); +#endif // Walk each frame until we reach where search phase said to stop. while (true) { // Ask libunwind to get next frame (skip over first which is // _Unwind_RaiseException). - int stepResult = __unw_step(cursor); + int stepResult = __unw_step_stage2(cursor); if (stepResult == 0) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): __unw_step() reached " + "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached " "bottom => _URC_END_OF_STACK", (void *)exception_object); return _URC_END_OF_STACK; } else if (stepResult < 0) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): __unw_step failed => " + "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => " "_URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; @@ -203,7 +208,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except __unw_get_reg(cursor, UNW_REG_SP, &sp); if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): __unw_get_proc_info " + "unwind_phase2(ex_obj=%p): __unw_get_proc_info " "failed => _URC_FATAL_PHASE1_ERROR", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; @@ -219,7 +224,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except &offset) != UNW_ESUCCESS) || (frameInfo.start_ip + offset > frameInfo.end_ip)) functionName = ".anonymous."; - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, (void *)exception_object, frameInfo.start_ip, @@ -228,6 +233,20 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except } #endif +// In CET enabled environment, we check return address stored in normal stack +// against return address stored in CET shadow stack, if the 2 addresses don't +// match, it means return address in normal stack has been corrupted, we return +// _URC_FATAL_PHASE2_ERROR. +#ifdef _LIBUNWIND_USE_CET + if (shadowStackTop != 0) { + unw_word_t retInNormalStack; + __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack); + unsigned long retInShadowStack = *( + unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked); + if (retInNormalStack != retInShadowStack) + return _URC_FATAL_PHASE2_ERROR; + } +#endif ++framesWalked; // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { @@ -245,7 +264,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except case _URC_CONTINUE_UNWIND: // Continue unwinding _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", + "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND", (void *)exception_object); if (sp == exception_object->private_2) { // Phase 1 said we would stop at this frame, but we did not... @@ -255,7 +274,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except break; case _URC_INSTALL_CONTEXT: _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", + "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT", (void *)exception_object); // Personality routine says to transfer control to landing pad. // We may get control back if landing pad calls _Unwind_Resume(). @@ -263,7 +282,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except unw_word_t pc; __unw_get_reg(cursor, UNW_REG_IP, &pc); __unw_get_reg(cursor, UNW_REG_SP, &sp); - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering " "user code with ip=0x%" PRIxPTR ", sp=0x%" PRIxPTR, (void *)exception_object, pc, sp); @@ -296,14 +315,15 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, // 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) { + while (__unw_step_stage2(cursor) > 0) { // 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); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_obj=%p): __unw_step_stage2 " + "failed => _URC_END_OF_STACK", + (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } @@ -318,7 +338,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, (frameInfo.start_ip + offset > frameInfo.end_ip)) functionName = ".anonymous."; _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR + "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, (void *)exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); @@ -332,11 +352,11 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, (*stop)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(cursor), stop_parameter); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", + "unwind_phase2_forced(ex_obj=%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", + "unwind_phase2_forced(ex_obj=%p): stopped by stop function", (void *)exception_object); return _URC_FATAL_PHASE2_ERROR; } @@ -347,21 +367,21 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Personality_Fn p = (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); _LIBUNWIND_TRACE_UNWINDING( - "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", + "unwind_phase2_forced(ex_obj=%p): calling personality function %p", (void *)exception_object, (void *)(uintptr_t)p); _Unwind_Reason_Code personalityResult = (*p)(1, action, exception_object->exception_class, exception_object, (struct _Unwind_Context *)(cursor)); switch (personalityResult) { case _URC_CONTINUE_UNWIND: - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%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): " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): " "personality returned " "_URC_INSTALL_CONTEXT", (void *)exception_object); @@ -370,7 +390,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, break; default: // Personality routine returned an unknown result code. - _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): " "personality returned %d, " "_URC_FATAL_PHASE2_ERROR", (void *)exception_object, personalityResult); @@ -381,7 +401,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, // 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 " + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop " "function with _UA_END_OF_STACK", (void *)exception_object); _Unwind_Action lastAction = @@ -425,7 +445,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) { /// may force a jump to a landing pad in that function, the landing /// pad code may then call _Unwind_Resume() to continue with the /// unwinding. Note: the call to _Unwind_Resume() is from compiler -/// geneated user code. All other _Unwind_* routines are called +/// generated user code. All other _Unwind_* routines are called /// by the C++ runtime __cxa_* routines. /// /// Note: re-throwing an exception (as opposed to continuing the unwind) diff --git a/lib/libunwind/src/UnwindRegistersRestore.S b/lib/libunwind/src/UnwindRegistersRestore.S index eeb6453496..2a472be943 100644 --- a/lib/libunwind/src/UnwindRegistersRestore.S +++ b/lib/libunwind/src/UnwindRegistersRestore.S @@ -8,6 +8,12 @@ #include "assembly.h" +#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 +#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + +#define FROM_0_TO_31 0,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 +#define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 + #if defined(_AIX) .toc #else @@ -441,7 +447,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) // thread_state pointer is in r3 // - // restore integral registerrs + // restore integral registers // skip r0 for now // skip r1 for now lwz 2, 16(3) @@ -1026,38 +1032,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) .set noreorder .set nomacro #ifdef __mips_hard_float - ldc1 $f0, (8 * 35)($4) - ldc1 $f1, (8 * 36)($4) - ldc1 $f2, (8 * 37)($4) - ldc1 $f3, (8 * 38)($4) - ldc1 $f4, (8 * 39)($4) - ldc1 $f5, (8 * 40)($4) - ldc1 $f6, (8 * 41)($4) - ldc1 $f7, (8 * 42)($4) - ldc1 $f8, (8 * 43)($4) - ldc1 $f9, (8 * 44)($4) - ldc1 $f10, (8 * 45)($4) - ldc1 $f11, (8 * 46)($4) - ldc1 $f12, (8 * 47)($4) - ldc1 $f13, (8 * 48)($4) - ldc1 $f14, (8 * 49)($4) - ldc1 $f15, (8 * 50)($4) - ldc1 $f16, (8 * 51)($4) - ldc1 $f17, (8 * 52)($4) - ldc1 $f18, (8 * 53)($4) - ldc1 $f19, (8 * 54)($4) - ldc1 $f20, (8 * 55)($4) - ldc1 $f21, (8 * 56)($4) - ldc1 $f22, (8 * 57)($4) - ldc1 $f23, (8 * 58)($4) - ldc1 $f24, (8 * 59)($4) - ldc1 $f25, (8 * 60)($4) - ldc1 $f26, (8 * 61)($4) - ldc1 $f27, (8 * 62)($4) - ldc1 $f28, (8 * 63)($4) - ldc1 $f29, (8 * 64)($4) - ldc1 $f30, (8 * 65)($4) - ldc1 $f31, (8 * 66)($4) + .irp i,FROM_0_TO_31 + ldc1 $f\i, (280+8*\i)($4) + .endr #endif // restore hi and lo ld $8, (8 * 33)($4) @@ -1069,32 +1046,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) ld $2, (8 * 2)($4) ld $3, (8 * 3)($4) // skip a0 for now - ld $5, (8 * 5)($4) - ld $6, (8 * 6)($4) - ld $7, (8 * 7)($4) - ld $8, (8 * 8)($4) - ld $9, (8 * 9)($4) - ld $10, (8 * 10)($4) - ld $11, (8 * 11)($4) - ld $12, (8 * 12)($4) - ld $13, (8 * 13)($4) - ld $14, (8 * 14)($4) - ld $15, (8 * 15)($4) - ld $16, (8 * 16)($4) - ld $17, (8 * 17)($4) - ld $18, (8 * 18)($4) - ld $19, (8 * 19)($4) - ld $20, (8 * 20)($4) - ld $21, (8 * 21)($4) - ld $22, (8 * 22)($4) - ld $23, (8 * 23)($4) - ld $24, (8 * 24)($4) - ld $25, (8 * 25)($4) - ld $26, (8 * 26)($4) - ld $27, (8 * 27)($4) - ld $28, (8 * 28)($4) - ld $29, (8 * 29)($4) - ld $30, (8 * 30)($4) + .irp i,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 + ld $\i, (8 * \i)($4) + .endr // load new pc into ra ld $31, (8 * 32)($4) // jump to ra, load a0 in the delay slot @@ -1182,72 +1136,20 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) .p2align 2 DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) # if defined(__riscv_flen) - FLOAD f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0) - FLOAD f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0) - FLOAD f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0) - FLOAD f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0) - FLOAD f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0) - FLOAD f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0) - FLOAD f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0) - FLOAD f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0) - FLOAD f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0) - FLOAD f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0) - FLOAD f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0) - FLOAD f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0) - FLOAD f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0) - FLOAD f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0) - FLOAD f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0) - FLOAD f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0) - FLOAD f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0) - FLOAD f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0) - FLOAD f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0) - FLOAD f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0) - FLOAD f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0) - FLOAD f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0) - FLOAD f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0) - FLOAD f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0) - FLOAD f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0) - FLOAD f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0) - FLOAD f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0) - FLOAD f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0) - FLOAD f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0) - FLOAD f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0) - FLOAD f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0) - FLOAD f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0) + .irp i,FROM_0_TO_31 + FLOAD f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0) + .endr # endif // x0 is zero ILOAD x1, (RISCV_ISIZE * 0)(a0) // restore pc into ra - ILOAD x2, (RISCV_ISIZE * 2)(a0) - ILOAD x3, (RISCV_ISIZE * 3)(a0) - ILOAD x4, (RISCV_ISIZE * 4)(a0) - ILOAD x5, (RISCV_ISIZE * 5)(a0) - ILOAD x6, (RISCV_ISIZE * 6)(a0) - ILOAD x7, (RISCV_ISIZE * 7)(a0) - ILOAD x8, (RISCV_ISIZE * 8)(a0) - ILOAD x9, (RISCV_ISIZE * 9)(a0) + .irp i,2,3,4,5,6,7,8,9 + ILOAD x\i, (RISCV_ISIZE * \i)(a0) + .endr // skip a0 for now - ILOAD x11, (RISCV_ISIZE * 11)(a0) - ILOAD x12, (RISCV_ISIZE * 12)(a0) - ILOAD x13, (RISCV_ISIZE * 13)(a0) - ILOAD x14, (RISCV_ISIZE * 14)(a0) - ILOAD x15, (RISCV_ISIZE * 15)(a0) - ILOAD x16, (RISCV_ISIZE * 16)(a0) - ILOAD x17, (RISCV_ISIZE * 17)(a0) - ILOAD x18, (RISCV_ISIZE * 18)(a0) - ILOAD x19, (RISCV_ISIZE * 19)(a0) - ILOAD x20, (RISCV_ISIZE * 20)(a0) - ILOAD x21, (RISCV_ISIZE * 21)(a0) - ILOAD x22, (RISCV_ISIZE * 22)(a0) - ILOAD x23, (RISCV_ISIZE * 23)(a0) - ILOAD x24, (RISCV_ISIZE * 24)(a0) - ILOAD x25, (RISCV_ISIZE * 25)(a0) - ILOAD x26, (RISCV_ISIZE * 26)(a0) - ILOAD x27, (RISCV_ISIZE * 27)(a0) - ILOAD x28, (RISCV_ISIZE * 28)(a0) - ILOAD x29, (RISCV_ISIZE * 29)(a0) - ILOAD x30, (RISCV_ISIZE * 30)(a0) - ILOAD x31, (RISCV_ISIZE * 31)(a0) + .irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + ILOAD x\i, (RISCV_ISIZE * \i)(a0) + .endr ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0 ret // jump to ra @@ -1266,22 +1168,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv) lg %r1, 8(%r2) // Restore FPRs - ld %f0, 144(%r2) - ld %f1, 152(%r2) - ld %f2, 160(%r2) - ld %f3, 168(%r2) - ld %f4, 176(%r2) - ld %f5, 184(%r2) - ld %f6, 192(%r2) - ld %f7, 200(%r2) - ld %f8, 208(%r2) - ld %f9, 216(%r2) - ld %f10, 224(%r2) - ld %f11, 232(%r2) - ld %f12, 240(%r2) - ld %f13, 248(%r2) - ld %f14, 256(%r2) - ld %f15, 264(%r2) + .irp i,FROM_0_TO_15 + ld %f\i, (144+8*\i)(%r2) + .endr // Restore GPRs - skipping %r0 and %r1 lmg %r2, %r15, 32(%r2) @@ -1289,6 +1178,36 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv) // Return to PSWA (was loaded into %r1 above) br %r1 +#elif defined(__loongarch__) && __loongarch_grlen == 64 + +// +// void libunwind::Registers_loongarch::jumpto() +// +// On entry: +// thread_state pointer is in $a0($r4) +// + .p2align 2 +DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) +# if __loongarch_frlen == 64 + .irp i,FROM_0_TO_31 + fld.d $f\i, $a0, (8 * 33 + 8 * \i) + .endr +# endif + + // $r0 is zero + .irp i,1,2,3 + ld.d $r\i, $a0, (8 * \i) + .endr + // skip $a0 for now + .irp i,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 + ld.d $r\i, $a0, (8 * \i) + .endr + + ld.d $r4, $a0, (8 * 4) // restore $a0 last + ld.d $r1, $a0, (8 * 32) // load new pc into $ra + + jr $ra + #endif #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ diff --git a/lib/libunwind/src/UnwindRegistersSave.S b/lib/libunwind/src/UnwindRegistersSave.S index f57dd637dd..6c26b79877 100644 --- a/lib/libunwind/src/UnwindRegistersSave.S +++ b/lib/libunwind/src/UnwindRegistersSave.S @@ -8,6 +8,12 @@ #include "assembly.h" +#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 +#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 + +#define FROM_0_TO_31 0,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 +#define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 + #if defined(_AIX) .toc #else @@ -244,37 +250,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) .set noat .set noreorder .set nomacro - sd $1, (8 * 1)($4) - sd $2, (8 * 2)($4) - sd $3, (8 * 3)($4) - sd $4, (8 * 4)($4) - sd $5, (8 * 5)($4) - sd $6, (8 * 6)($4) - sd $7, (8 * 7)($4) - sd $8, (8 * 8)($4) - sd $9, (8 * 9)($4) - sd $10, (8 * 10)($4) - sd $11, (8 * 11)($4) - sd $12, (8 * 12)($4) - sd $13, (8 * 13)($4) - sd $14, (8 * 14)($4) - sd $15, (8 * 15)($4) - sd $16, (8 * 16)($4) - sd $17, (8 * 17)($4) - sd $18, (8 * 18)($4) - sd $19, (8 * 19)($4) - sd $20, (8 * 20)($4) - sd $21, (8 * 21)($4) - sd $22, (8 * 22)($4) - sd $23, (8 * 23)($4) - sd $24, (8 * 24)($4) - sd $25, (8 * 25)($4) - sd $26, (8 * 26)($4) - sd $27, (8 * 27)($4) - sd $28, (8 * 28)($4) - sd $29, (8 * 29)($4) - sd $30, (8 * 30)($4) - sd $31, (8 * 31)($4) + .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 + sd $\i, (8 * \i)($4) + .endr # Store return address to pc sd $31, (8 * 32)($4) # hi and lo @@ -283,38 +261,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) mflo $8 sd $8, (8 * 34)($4) #ifdef __mips_hard_float - sdc1 $f0, (8 * 35)($4) - sdc1 $f1, (8 * 36)($4) - sdc1 $f2, (8 * 37)($4) - sdc1 $f3, (8 * 38)($4) - sdc1 $f4, (8 * 39)($4) - sdc1 $f5, (8 * 40)($4) - sdc1 $f6, (8 * 41)($4) - sdc1 $f7, (8 * 42)($4) - sdc1 $f8, (8 * 43)($4) - sdc1 $f9, (8 * 44)($4) - sdc1 $f10, (8 * 45)($4) - sdc1 $f11, (8 * 46)($4) - sdc1 $f12, (8 * 47)($4) - sdc1 $f13, (8 * 48)($4) - sdc1 $f14, (8 * 49)($4) - sdc1 $f15, (8 * 50)($4) - sdc1 $f16, (8 * 51)($4) - sdc1 $f17, (8 * 52)($4) - sdc1 $f18, (8 * 53)($4) - sdc1 $f19, (8 * 54)($4) - sdc1 $f20, (8 * 55)($4) - sdc1 $f21, (8 * 56)($4) - sdc1 $f22, (8 * 57)($4) - sdc1 $f23, (8 * 58)($4) - sdc1 $f24, (8 * 59)($4) - sdc1 $f25, (8 * 60)($4) - sdc1 $f26, (8 * 61)($4) - sdc1 $f27, (8 * 62)($4) - sdc1 $f28, (8 * 63)($4) - sdc1 $f29, (8 * 64)($4) - sdc1 $f30, (8 * 65)($4) - sdc1 $f31, (8 * 66)($4) + .irp i,FROM_0_TO_31 + sdc1 $f\i, (280+8*\i)($4) + .endr #endif jr $31 # return UNW_ESUCCESS @@ -1110,71 +1059,14 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc - ISTORE x1, (RISCV_ISIZE * 1)(a0) - ISTORE x2, (RISCV_ISIZE * 2)(a0) - ISTORE x3, (RISCV_ISIZE * 3)(a0) - ISTORE x4, (RISCV_ISIZE * 4)(a0) - ISTORE x5, (RISCV_ISIZE * 5)(a0) - ISTORE x6, (RISCV_ISIZE * 6)(a0) - ISTORE x7, (RISCV_ISIZE * 7)(a0) - ISTORE x8, (RISCV_ISIZE * 8)(a0) - ISTORE x9, (RISCV_ISIZE * 9)(a0) - ISTORE x10, (RISCV_ISIZE * 10)(a0) - ISTORE x11, (RISCV_ISIZE * 11)(a0) - ISTORE x12, (RISCV_ISIZE * 12)(a0) - ISTORE x13, (RISCV_ISIZE * 13)(a0) - ISTORE x14, (RISCV_ISIZE * 14)(a0) - ISTORE x15, (RISCV_ISIZE * 15)(a0) - ISTORE x16, (RISCV_ISIZE * 16)(a0) - ISTORE x17, (RISCV_ISIZE * 17)(a0) - ISTORE x18, (RISCV_ISIZE * 18)(a0) - ISTORE x19, (RISCV_ISIZE * 19)(a0) - ISTORE x20, (RISCV_ISIZE * 20)(a0) - ISTORE x21, (RISCV_ISIZE * 21)(a0) - ISTORE x22, (RISCV_ISIZE * 22)(a0) - ISTORE x23, (RISCV_ISIZE * 23)(a0) - ISTORE x24, (RISCV_ISIZE * 24)(a0) - ISTORE x25, (RISCV_ISIZE * 25)(a0) - ISTORE x26, (RISCV_ISIZE * 26)(a0) - ISTORE x27, (RISCV_ISIZE * 27)(a0) - ISTORE x28, (RISCV_ISIZE * 28)(a0) - ISTORE x29, (RISCV_ISIZE * 29)(a0) - ISTORE x30, (RISCV_ISIZE * 30)(a0) - ISTORE x31, (RISCV_ISIZE * 31)(a0) + .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 + ISTORE x\i, (RISCV_ISIZE * \i)(a0) + .endr # if defined(__riscv_flen) - FSTORE f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0) - FSTORE f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0) - FSTORE f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0) - FSTORE f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0) - FSTORE f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0) - FSTORE f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0) - FSTORE f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0) - FSTORE f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0) - FSTORE f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0) - FSTORE f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0) - FSTORE f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0) - FSTORE f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0) - FSTORE f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0) - FSTORE f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0) - FSTORE f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0) - FSTORE f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0) - FSTORE f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0) - FSTORE f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0) - FSTORE f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0) - FSTORE f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0) - FSTORE f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0) - FSTORE f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0) - FSTORE f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0) - FSTORE f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0) - FSTORE f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0) - FSTORE f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0) - FSTORE f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0) - FSTORE f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0) - FSTORE f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0) - FSTORE f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0) - FSTORE f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0) - FSTORE f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0) + .irp i,FROM_0_TO_31 + FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0) + .endr # endif li a0, 0 // return UNW_ESUCCESS @@ -1201,27 +1093,37 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stg %r14, 8(%r2) // Save FPRs - std %f0, 144(%r2) - std %f1, 152(%r2) - std %f2, 160(%r2) - std %f3, 168(%r2) - std %f4, 176(%r2) - std %f5, 184(%r2) - std %f6, 192(%r2) - std %f7, 200(%r2) - std %f8, 208(%r2) - std %f9, 216(%r2) - std %f10, 224(%r2) - std %f11, 232(%r2) - std %f12, 240(%r2) - std %f13, 248(%r2) - std %f14, 256(%r2) - std %f15, 264(%r2) + .irp i,FROM_0_TO_15 + std %f\i, (144+8*\i)(%r2) + .endr // Return UNW_ESUCCESS lghi %r2, 0 br %r14 +#elif defined(__loongarch__) && __loongarch_grlen == 64 + +# +# extern int __unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in $a0($r4) +# +DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) + .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 + st.d $r\i, $a0, (8*\i) + .endr + st.d $r1, $a0, (8 * 32) // store $ra to pc + +# if __loongarch_frlen == 64 + .irp i,FROM_0_TO_31 + fst.d $f\i, $a0, (8 * 33 + 8 * \i) + .endr +# endif + + move $a0, $zero // UNW_ESUCCESS + jr $ra + #endif WEAK_ALIAS(__unw_getcontext, unw_getcontext) diff --git a/lib/libunwind/src/Unwind_AIXExtras.cpp b/lib/libunwind/src/Unwind_AIXExtras.cpp index 7e47f70186..66194ab4a1 100644 --- a/lib/libunwind/src/Unwind_AIXExtras.cpp +++ b/lib/libunwind/src/Unwind_AIXExtras.cpp @@ -38,7 +38,7 @@ char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen, if (TBTable->tb.fixedparms || TBTable->tb.floatparms) p++; - // If the tb_offset field exisits, get the offset from the start of + // If the tb_offset field exists, get the offset from the start of // the function to pc. Skip the field. if (TBTable->tb.has_tboff) { unw_word_t StartIp = diff --git a/lib/libunwind/src/config.h b/lib/libunwind/src/config.h index cc41b817ac..4bbac95162 100644 --- a/lib/libunwind/src/config.h +++ b/lib/libunwind/src/config.h @@ -115,7 +115,7 @@ #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \ (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \ defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \ - defined(__sparc__) || defined(__s390x__) + defined(__sparc__) || defined(__s390x__) || defined(__loongarch__) #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) #define _LIBUNWIND_BUILD_ZERO_COST_APIS #endif diff --git a/lib/libunwind/src/libunwind.cpp b/lib/libunwind/src/libunwind.cpp index b8b41ff25e..0faea2b785 100644 --- a/lib/libunwind/src/libunwind.cpp +++ b/lib/libunwind/src/libunwind.cpp @@ -77,6 +77,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, # define REGISTER_KIND Registers_ve #elif defined(__s390x__) # define REGISTER_KIND Registers_s390x +#elif defined(__loongarch__) && __loongarch_grlen == 64 +#define REGISTER_KIND Registers_loongarch #else # error Architecture not supported #endif @@ -117,7 +119,7 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { co->setReg(regNum, (pint_t)value); - // specical case altering IP to re-find info (being called by personality + // special case altering IP to re-find info (being called by personality // function) if (regNum == UNW_REG_IP) { unw_proc_info_t info; @@ -181,6 +183,15 @@ _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) { } _LIBUNWIND_WEAK_ALIAS(__unw_step, unw_step) +// Move cursor to next frame and for stage2 of unwinding. +// This resets MTE tags of tagged frames to zero. +extern "C" _LIBUNWIND_HIDDEN int __unw_step_stage2(unw_cursor_t *cursor) { + _LIBUNWIND_TRACE_API("__unw_step_stage2(cursor=%p)", + static_cast(cursor)); + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->step(true); +} + /// Get unwind info at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor, unw_proc_info_t *info) {