diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-01-02 01:10:03 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2021-01-02 01:10:03 +0000 |
commit | ae3c93b102d5ae5b557e5cb07ad54b605467cb80 (patch) | |
tree | f5508f6a24dd47d7db4bb7ace845136d3eaa52c9 /gnu/llvm | |
parent | 78257747c48b0e42828960067f7c33356f8bc9f8 (diff) |
Re-apply our libunwind 8.0.0 patches to libunwind 11.0.0. Patches to the
PPC ASM had to be re-applied manually due to whitespace changes upstream,
other merge conflicts were harmless.
"Looks good" kettenis@
Diffstat (limited to 'gnu/llvm')
-rw-r--r-- | gnu/llvm/libunwind/include/__libunwind_config.h | 7 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/AddressSpace.hpp | 61 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/DwarfInstructions.hpp | 6 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/DwarfParser.hpp | 18 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/EHHeaderParser.hpp | 6 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/Registers.hpp | 170 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/UnwindCursor.hpp | 17 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/UnwindRegistersRestore.S | 55 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/UnwindRegistersSave.S | 85 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/assembly.h | 2 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/config.h | 1 | ||||
-rw-r--r-- | gnu/llvm/libunwind/src/libunwind.cpp | 2 |
12 files changed, 407 insertions, 23 deletions
diff --git a/gnu/llvm/libunwind/include/__libunwind_config.h b/gnu/llvm/libunwind/include/__libunwind_config.h index 71d77ca6511..302c97d3c85 100644 --- a/gnu/llvm/libunwind/include/__libunwind_config.h +++ b/gnu/llvm/libunwind/include/__libunwind_config.h @@ -23,6 +23,7 @@ #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64 32 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 @@ -121,6 +122,11 @@ # error "Unsupported MIPS ABI and/or environment" # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS +# elif defined(__sparc__) && defined(__arch64__) +# define _LIBUNWIND_TARGET_SPARC64 1 +# define _LIBUNWIND_CONTEXT_SIZE 33 +# define _LIBUNWIND_CURSOR_SIZE 45 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64 # elif defined(__sparc__) #define _LIBUNWIND_TARGET_SPARC 1 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC @@ -149,6 +155,7 @@ # define _LIBUNWIND_TARGET_MIPS_O32 1 # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 # define _LIBUNWIND_TARGET_SPARC 1 +# define _LIBUNWIND_TARGET_SPARC64 1 # define _LIBUNWIND_TARGET_HEXAGON 1 # define _LIBUNWIND_TARGET_RISCV 1 # define _LIBUNWIND_CONTEXT_SIZE 167 diff --git a/gnu/llvm/libunwind/src/AddressSpace.hpp b/gnu/llvm/libunwind/src/AddressSpace.hpp index 93395ffb3b1..76a1eca9400 100644 --- a/gnu/llvm/libunwind/src/AddressSpace.hpp +++ b/gnu/llvm/libunwind/src/AddressSpace.hpp @@ -16,6 +16,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/tree.h> #ifndef _LIBUNWIND_USE_DLADDR #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) @@ -185,6 +186,62 @@ struct UnwindInfoSections { #endif }; +class UnwindInfoSectionsCache { +public: + + struct CacheItem { + CacheItem(UnwindInfoSections &uis, uintptr_t pc) + : m_uis(uis), m_pc(pc) { + } + CacheItem(uintptr_t pc) + : m_pc(pc) { + } + + UnwindInfoSections m_uis; + uintptr_t m_pc; + + RB_ENTRY(CacheItem) entry; + }; + + typedef uintptr_t CacheItemKey; + + int CacheCmp(struct CacheItem *c1, struct CacheItem *c2) { + return (c1->m_pc < c2->m_pc ? -1 : c1->m_pc > c2->m_pc); + } + + UnwindInfoSectionsCache() { + m_head = RB_INITIALIZER(&head); + } + + bool getUnwindInfoSectionsForPC(CacheItemKey key, UnwindInfoSections &uis) { + UnwindInfoSections *result = nullptr; + if (m_prev_req_item && m_prev_req_item->m_pc == key) + result = &m_prev_req_item->m_uis; + else { + struct CacheItem find(key), *res; + res = RB_FIND(CacheTree, &m_head, &find); + if (res) { + m_prev_req_item = res; + result = &res->m_uis; + } + } + if (result) { + uis = *result; + return true; + } + return false; + } + + void setUnwindInfoSectionsForPC(CacheItemKey key, UnwindInfoSections &uis) { + CacheItem *p_item(new CacheItem(uis, key)); + RB_INSERT(CacheTree, &m_head, p_item); + } + +private: + CacheItem *m_prev_req_item = nullptr; + RB_HEAD(CacheTree, CacheItem) m_head; + RB_GENERATE(CacheTree, CacheItem, entry, CacheCmp); +}; /// LocalAddressSpace is used as a template parameter to UnwindCursor when /// unwinding a thread in the same process. The wrappers compile away, @@ -307,6 +364,10 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, const uint8_t *p = (uint8_t *)addr; pint_t result; + if (encoding == DW_EH_PE_omit) { + return (pint_t)NULL; + } + // first get value switch (encoding & 0x0F) { case DW_EH_PE_ptr: diff --git a/gnu/llvm/libunwind/src/DwarfInstructions.hpp b/gnu/llvm/libunwind/src/DwarfInstructions.hpp index ee98f538d43..73beb500971 100644 --- a/gnu/llvm/libunwind/src/DwarfInstructions.hpp +++ b/gnu/llvm/libunwind/src/DwarfInstructions.hpp @@ -83,6 +83,10 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( case CFI_Parser<A>::kRegisterInCFA: return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); + case CFI_Parser<A>::kRegisterInCFADecrypt: + return addressSpace.getP( + cfa + (pint_t)savedReg.value) ^ registers.getWCookie(); + case CFI_Parser<A>::kRegisterAtExpression: return (pint_t)addressSpace.getRegister(evaluateExpression( (pint_t)savedReg.value, addressSpace, registers, cfa)); @@ -119,6 +123,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister( case CFI_Parser<A>::kRegisterUnused: case CFI_Parser<A>::kRegisterOffsetFromCFA: case CFI_Parser<A>::kRegisterInRegister: + case CFI_Parser<A>::kRegisterInCFADecrypt: // FIX ME break; } @@ -142,6 +147,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( case CFI_Parser<A>::kRegisterUnused: case CFI_Parser<A>::kRegisterOffsetFromCFA: case CFI_Parser<A>::kRegisterInRegister: + case CFI_Parser<A>::kRegisterInCFADecrypt: // FIX ME break; } diff --git a/gnu/llvm/libunwind/src/DwarfParser.hpp b/gnu/llvm/libunwind/src/DwarfParser.hpp index d05ac468367..b6c9079e762 100644 --- a/gnu/llvm/libunwind/src/DwarfParser.hpp +++ b/gnu/llvm/libunwind/src/DwarfParser.hpp @@ -70,6 +70,7 @@ public: enum RegisterSavedWhere { kRegisterUnused, kRegisterInCFA, + kRegisterInCFADecrypt, kRegisterOffsetFromCFA, kRegisterInRegister, kRegisterAtExpression, @@ -723,7 +724,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); break; -#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) +#if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) \ + || defined(_LIBUNWIND_TARGET_SPARC64) // The same constant is used to represent different instructions on // AArch64 (negate_ra_state) and SPARC (window_save). static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, @@ -739,6 +741,20 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, } break; #endif +#if defined(_LIBUNWIND_TARGET_SPARC64) + case REGISTERS_SPARC64: + // Hardcodes windowed registers for SPARC + for (reg = 16; reg < 32; reg++) { + if (reg == 31) + results->savedRegisters[reg].location = kRegisterInCFADecrypt; + else + results->savedRegisters[reg].location = kRegisterInCFA; + results->savedRegisters[reg].value = (reg - 16) * sizeof(pint_t); + } + _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save"); + break; +#endif + #if defined(_LIBUNWIND_TARGET_SPARC) // case DW_CFA_GNU_window_save: case REGISTERS_SPARC: diff --git a/gnu/llvm/libunwind/src/EHHeaderParser.hpp b/gnu/llvm/libunwind/src/EHHeaderParser.hpp index f97cca54825..d9902edb4d6 100644 --- a/gnu/llvm/libunwind/src/EHHeaderParser.hpp +++ b/gnu/llvm/libunwind/src/EHHeaderParser.hpp @@ -144,6 +144,10 @@ bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, template <typename A> size_t EHHeaderParser<A>::getTableEntrySize(uint8_t tableEnc) { + if (tableEnc == DW_EH_PE_omit) { + return 0; + } + switch (tableEnc & 0x0f) { case DW_EH_PE_sdata2: case DW_EH_PE_udata2: @@ -157,8 +161,6 @@ size_t EHHeaderParser<A>::getTableEntrySize(uint8_t tableEnc) { case DW_EH_PE_sleb128: case DW_EH_PE_uleb128: _LIBUNWIND_ABORT("Can't binary search on variable length encoded data."); - case DW_EH_PE_omit: - return 0; default: _LIBUNWIND_ABORT("Unknown DWARF encoding for search table."); } diff --git a/gnu/llvm/libunwind/src/Registers.hpp b/gnu/llvm/libunwind/src/Registers.hpp index c76b05bf314..3fd8b8abf1d 100644 --- a/gnu/llvm/libunwind/src/Registers.hpp +++ b/gnu/llvm/libunwind/src/Registers.hpp @@ -34,6 +34,7 @@ enum { REGISTERS_MIPS_O32, REGISTERS_MIPS_NEWABI, REGISTERS_SPARC, + REGISTERS_SPARC64, REGISTERS_HEXAGON, REGISTERS_RISCV, }; @@ -76,6 +77,7 @@ public: void setESI(uint32_t value) { _registers.__esi = value; } uint32_t getEDI() const { return _registers.__edi; } void setEDI(uint32_t value) { _registers.__edi = value; } + uint32_t getWCookie() const { return 0; } private: struct GPRs { @@ -283,6 +285,7 @@ public: void setR14(uint64_t value) { _registers.__r14 = value; } uint64_t getR15() const { return _registers.__r15; } void setR15(uint64_t value) { _registers.__r15 = value; } + uint64_t getWCookie() const { return 0; } private: struct GPRs { @@ -585,6 +588,7 @@ public: void setSP(uint32_t value) { _registers.__r1 = value; } uint64_t getIP() const { return _registers.__srr0; } void setIP(uint32_t value) { _registers.__srr0 = value; } + uint64_t getWCookie() const { return 0; } private: struct ppc_thread_state_t { @@ -627,7 +631,7 @@ private: unsigned int __lr; /* Link register */ unsigned int __ctr; /* Count register */ unsigned int __mq; /* MQ register (601 only) */ - unsigned int __vrsave; /* Vector Save Register */ + mutable unsigned int __vrsave; /* Vector Save Register */ }; struct ppc_float_state_t { @@ -637,9 +641,11 @@ private: unsigned int __fpscr; /* floating point status register */ }; + void saveVectorRegisters() const; + ppc_thread_state_t _registers; ppc_float_state_t _floatRegisters; - v128 _vectorRegisters[32]; // offset 424 + mutable v128 _vectorRegisters[32]; // offset 424 }; inline Registers_ppc::Registers_ppc(const void *registers) { @@ -654,10 +660,8 @@ inline Registers_ppc::Registers_ppc(const void *registers) { sizeof(_floatRegisters)); static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424, "expected vector register offset to be 424 bytes"); - memcpy(_vectorRegisters, - static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) + - sizeof(ppc_float_state_t), - sizeof(_vectorRegisters)); + // no values until saveVectorRegisters() + memset(&_vectorRegisters, 0, sizeof(_vectorRegisters)); } inline Registers_ppc::Registers_ppc() { @@ -777,6 +781,7 @@ inline uint32_t Registers_ppc::getRegister(int regNum) const { case UNW_PPC_CR7: return (_registers.__cr & 0x0000000F); case UNW_PPC_VRSAVE: + saveVectorRegisters(); return _registers.__vrsave; } _LIBUNWIND_ABORT("unsupported ppc register"); @@ -929,6 +934,7 @@ inline void Registers_ppc::setRegister(int regNum, uint32_t value) { _registers.__cr |= (value & 0x0000000F); return; case UNW_PPC_VRSAVE: + saveVectorRegisters(); _registers.__vrsave = value; return; // not saved @@ -973,12 +979,14 @@ inline bool Registers_ppc::validVectorRegister(int regNum) const { inline v128 Registers_ppc::getVectorRegister(int regNum) const { assert(validVectorRegister(regNum)); + saveVectorRegisters(); v128 result = _vectorRegisters[regNum - UNW_PPC_V0]; return result; } inline void Registers_ppc::setVectorRegister(int regNum, v128 value) { assert(validVectorRegister(regNum)); + saveVectorRegisters(); _vectorRegisters[regNum - UNW_PPC_V0] = value; } @@ -1151,6 +1159,7 @@ public: void setSP(uint64_t value) { _registers.__r1 = value; } uint64_t getIP() const { return _registers.__srr0; } void setIP(uint64_t value) { _registers.__srr0 = value; } + uint64_t getWCookie() const { return 0; } private: struct ppc64_thread_state_t { @@ -1796,6 +1805,7 @@ public: void setIP(uint64_t value) { _registers.__pc = value; } uint64_t getFP() const { return _registers.__fp; } void setFP(uint64_t value) { _registers.__fp = value; } + uint64_t getWCookie() const { return 0; } private: struct GPRs { @@ -2074,6 +2084,7 @@ public: void setSP(uint32_t value) { _registers.__sp = value; } uint32_t getIP() const { return _registers.__pc; } void setIP(uint32_t value) { _registers.__pc = value; } + uint64_t getWCookie() const { return 0; } void saveVFPAsX() { assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); @@ -2552,6 +2563,7 @@ public: void setSP(uint32_t value) { _registers.__r[1] = value; } uint64_t getIP() const { return _registers.__pc; } void setIP(uint32_t value) { _registers.__pc = value; } + uint64_t getWCookie() const { return 0; } private: struct or1k_thread_state_t { @@ -2723,6 +2735,150 @@ inline const char *Registers_or1k::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_OR1K +#if defined(_LIBUNWIND_TARGET_SPARC64) +/// Registers_sparc64 holds the register state of a thread in a 64-bit +/// sparc process. +class _LIBUNWIND_HIDDEN Registers_sparc64 { +public: + Registers_sparc64(); + Registers_sparc64(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); + const char *getRegisterName(int num); + void jumpto(); + static int lastDwarfRegNum() { return 31; } + static int getArch() { return REGISTERS_SPARC64; } + + uint64_t getSP() const { return _registers.__o[6] + 2047; } + void setSP(uint64_t value) { _registers.__o[6] = value - 2047; } + uint64_t getIP() const { return _registers.__o[7]; } + void setIP(uint64_t value) { _registers.__o[7] = value; } + uint64_t getWCookie() const { return _wcookie; } + +private: + struct GPRs { + uint64_t __g[8]; + uint64_t __o[8]; + uint64_t __l[8]; + uint64_t __i[8]; + }; + + GPRs _registers; + uint64_t _wcookie; +}; + +inline Registers_sparc64::Registers_sparc64(const void *registers) { + static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit), + "sparc64 registers do not fit into unw_context_t"); + memcpy(&_registers, static_cast<const uint8_t *>(registers), + sizeof(_registers)); + memcpy(&_wcookie, static_cast<const uint8_t *>(registers) + sizeof(GPRs), + sizeof(_wcookie)); +} + +inline Registers_sparc64::Registers_sparc64() { + memset(&_registers, 0, sizeof(_registers)); + _wcookie = 0; +} + +inline bool Registers_sparc64::validRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return true; + if (regNum == UNW_REG_SP) + return true; + if (regNum < 0) + return false; + if (regNum <= 31) + return true; + return false; +} + +inline uint64_t Registers_sparc64::getRegister(int regNum) const { + if (regNum >= 0 && regNum <= 7) + return _registers.__g[regNum - 0]; + if (regNum >= 8 && regNum <= 15) + return _registers.__o[regNum - 8]; + if (regNum >= 16 && regNum <= 23) + return _registers.__l[regNum - 16]; + if (regNum >= 24 && regNum <= 31) + return _registers.__i[regNum - 24]; + + switch (regNum) { + case UNW_REG_IP: + return _registers.__o[7] + 8; + case UNW_REG_SP: + return _registers.__o[6] + 2047; + } + _LIBUNWIND_ABORT("unsupported sparc64 register"); +} + +inline void Registers_sparc64::setRegister(int regNum, uint64_t value) { + if (regNum >= 0 && regNum <= 7) { + _registers.__g[regNum - 0] = value; + return; + } + if (regNum >= 8 && regNum <= 15) { + _registers.__o[regNum - 8] = value; + return; + } + if (regNum >= 16 && regNum <= 23) { + _registers.__l[regNum - 16] = value; + return; + } + if (regNum >= 24 && regNum <= 31) { + _registers.__i[regNum - 24] = value; + return; + } + + switch (regNum) { + case UNW_REG_IP: + _registers.__o[7] = value - 8; + return; + case UNW_REG_SP: + _registers.__o[6] = value - 2047; + return; + } + _LIBUNWIND_ABORT("unsupported sparc64 register"); +} + +inline bool Registers_sparc64::validFloatRegister(int) const { + return false; +} + +inline double Registers_sparc64::getFloatRegister(int) const { + _LIBUNWIND_ABORT("no sparc64 float registers"); +} + +inline void Registers_sparc64::setFloatRegister(int, double) { + _LIBUNWIND_ABORT("no sparc64 float registers"); +} + +inline bool Registers_sparc64::validVectorRegister(int) const { + return false; +} + +inline v128 Registers_sparc64::getVectorRegister(int) const { + _LIBUNWIND_ABORT("no sparc64 vector registers"); +} + +inline void Registers_sparc64::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("no sparc64 vector registers"); +} + +inline const char *Registers_sparc64::getRegisterName(int regNum) { + return "unknown register"; +} + +#endif // _LIBUNWIND_TARGET_SPARC64 + #if defined(_LIBUNWIND_TARGET_MIPS_O32) /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS /// process. @@ -2749,6 +2905,7 @@ public: void setSP(uint32_t value) { _registers.__r[29] = value; } uint32_t getIP() const { return _registers.__pc; } void setIP(uint32_t value) { _registers.__pc = value; } + uint32_t getWCookie() const { return 0; } private: struct mips_o32_thread_state_t { @@ -3076,6 +3233,7 @@ public: void setSP(uint64_t value) { _registers.__r[29] = value; } uint64_t getIP() const { return _registers.__pc; } void setIP(uint64_t value) { _registers.__pc = value; } + uint32_t getWCookie() const { return 0; } private: struct mips_newabi_thread_state_t { diff --git a/gnu/llvm/libunwind/src/UnwindCursor.hpp b/gnu/llvm/libunwind/src/UnwindCursor.hpp index f346c720d22..31097b48fb3 100644 --- a/gnu/llvm/libunwind/src/UnwindCursor.hpp +++ b/gnu/llvm/libunwind/src/UnwindCursor.hpp @@ -75,6 +75,8 @@ extern "C" _Unwind_Reason_Code __libunwind_seh_personality( namespace libunwind { +static UnwindInfoSectionsCache uwis_cache; + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) /// Cache of recently found FDEs. template <typename A> @@ -1145,6 +1147,12 @@ private: compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } #endif +#if defined (_LIBUNWIND_TARGET_SPARC64) + compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const { + return 0; + } +#endif + #if defined (_LIBUNWIND_TARGET_RISCV) compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { return 0; @@ -1876,7 +1884,14 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { // Ask address space object to find unwind sections for this pc. UnwindInfoSections sects; - if (_addressSpace.findUnwindSections(pc, sects)) { + bool have_sects = false; + if (uwis_cache.getUnwindInfoSectionsForPC(pc, sects)) + have_sects = true; + else if (_addressSpace.findUnwindSections(pc, sects)) { + uwis_cache.setUnwindInfoSectionsForPC(pc, sects); + have_sects = true; + } + if (have_sects) { #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) // If there is a compact unwind encoding table, look there first. if (sects.compact_unwind_section != 0) { diff --git a/gnu/llvm/libunwind/src/UnwindRegistersRestore.S b/gnu/llvm/libunwind/src/UnwindRegistersRestore.S index 5d544321528..9f60594b654 100644 --- a/gnu/llvm/libunwind/src/UnwindRegistersRestore.S +++ b/gnu/llvm/libunwind/src/UnwindRegistersRestore.S @@ -475,11 +475,11 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) cmpwi %r5, 0 beq Lnovec - subi %r4, %r1, 16 - rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits - // r4 is now a 16-byte aligned pointer into the red zone - // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer - + stwu %r1, -32(%r1) // allocate a stack frame + addi %r4, %r1, 16 + clrrwi %r4, %r4, 4 + // r4 is now a 16-byte aligned pointer + // the _vectorRegisters may not be 16-byte aligned so copy via r4 #define LOAD_VECTOR_UNALIGNEDl(_index) \ andis. %r0, %r5, (1<<(15-_index)) SEPARATOR \ @@ -543,6 +543,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) LOAD_VECTOR_UNALIGNEDh(30) LOAD_VECTOR_UNALIGNEDh(31) + addi %r1,%r1,32 // drop the stack frame + Lnovec: lwz %r0, 136(%r3) // __cr mtcr %r0 @@ -1049,6 +1051,49 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) ld $4, (8 * 4)($4) .set pop +#elif defined(__sparc__) && defined(__arch64__) + +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv) +# +# void libunwind::Registers_sparc64::jumpto() +# +# On entry: +# thread_state pointer is in %o0 +# + flushw + ldx [%o0 + 0x08], %g1 + ldx [%o0 + 0x10], %g2 + ldx [%o0 + 0x18], %g3 + ldx [%o0 + 0x20], %g4 + ldx [%o0 + 0x28], %g5 + ldx [%o0 + 0x30], %g6 + ldx [%o0 + 0x38], %g7 + ldx [%o0 + 0x48], %o1 + ldx [%o0 + 0x50], %o2 + ldx [%o0 + 0x58], %o3 + ldx [%o0 + 0x60], %o4 + ldx [%o0 + 0x68], %o5 + ldx [%o0 + 0x70], %o6 + ldx [%o0 + 0x78], %o7 + ldx [%o0 + 0x80], %l0 + ldx [%o0 + 0x88], %l1 + ldx [%o0 + 0x90], %l2 + ldx [%o0 + 0x98], %l3 + ldx [%o0 + 0xa0], %l4 + ldx [%o0 + 0xa8], %l5 + ldx [%o0 + 0xb0], %l6 + ldx [%o0 + 0xb8], %l7 + ldx [%o0 + 0xc0], %i0 + ldx [%o0 + 0xc8], %i1 + ldx [%o0 + 0xd0], %i2 + ldx [%o0 + 0xd8], %i3 + ldx [%o0 + 0xe0], %i4 + ldx [%o0 + 0xe8], %i5 + ldx [%o0 + 0xf0], %i6 + ldx [%o0 + 0xf8], %i7 + jmpl %o7 + 8, %g0 + ldx [%o0 + 0x40], %o0 + #elif defined(__sparc__) // diff --git a/gnu/llvm/libunwind/src/UnwindRegistersSave.S b/gnu/llvm/libunwind/src/UnwindRegistersSave.S index 51bb9b0688f..78c8c534131 100644 --- a/gnu/llvm/libunwind/src/UnwindRegistersSave.S +++ b/gnu/llvm/libunwind/src/UnwindRegistersSave.S @@ -598,8 +598,8 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stw %r30,128(%r3) stw %r31,132(%r3) - // save VRSave register - mfspr %r0, 256 + // zero VRSave register; saveVectorRegisters() will save it + li %r0, 0 stw %r0, 156(%r3) // save CR registers mfcr %r0 @@ -642,12 +642,29 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) stfd %f30,400(%r3) stfd %f31,408(%r3) + li %r3, 0 // return UNW_ESUCCESS + blr - // save vector registers +// +// void libunwind::Registers_ppc::saveVectorRegisters() const +// +// On entry: +// thread_state pointer is in r3 +// +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZNK9libunwind13Registers_ppc19saveVectorRegistersEv) + // return if we have already saved VRsave + lwz %r0, 156(%r3) + cmpwi %r0, 0 + bnelr - subi %r4, %r1, 16 - rlwinm %r4, %r4, 0, 0, 27 // mask low 4-bits - // r4 is now a 16-byte aligned pointer into the red zone + stwu %r1, -32(%r1) // allocate a stack frame + addi %r4, %r1, 16 + clrrwi %r4, %r4, 4 + // r4 is now a 16-byte aligned pointer + + // save VRsave register + mfvrsave %r0 + stw %r0, 156(%r3) #define SAVE_VECTOR_UNALIGNED(_vec, _offset) \ stvx _vec, 0, %r4 SEPARATOR \ @@ -693,10 +710,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) - li %r3, 0 // return UNW_ESUCCESS + addi %r1, %r1, 32 // drop the stack frame blr - #elif defined(__aarch64__) // @@ -946,6 +962,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) l.sw 132(r3), r0 #elif defined(__hexagon__) + # # extern int unw_getcontext(unw_context_t* thread_state) # @@ -991,6 +1008,58 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) jumpr r31 +#elif defined(__sparc__) && defined(__arch64__) + +# +# extern int unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in %o0 +# +DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) + stx %g1, [%o0 + 0x08] + stx %g2, [%o0 + 0x10] + stx %g3, [%o0 + 0x18] + stx %g4, [%o0 + 0x20] + stx %g5, [%o0 + 0x28] + stx %g6, [%o0 + 0x30] + stx %g7, [%o0 + 0x38] + stx %o0, [%o0 + 0x40] + stx %o1, [%o0 + 0x48] + stx %o2, [%o0 + 0x50] + stx %o3, [%o0 + 0x58] + stx %o4, [%o0 + 0x60] + stx %o5, [%o0 + 0x68] + stx %o6, [%o0 + 0x70] + stx %o7, [%o0 + 0x78] + stx %l0, [%o0 + 0x80] + stx %l1, [%o0 + 0x88] + stx %l2, [%o0 + 0x90] + stx %l3, [%o0 + 0x98] + stx %l4, [%o0 + 0xa0] + stx %l5, [%o0 + 0xa8] + stx %l6, [%o0 + 0xb0] + stx %l7, [%o0 + 0xb8] + stx %i0, [%o0 + 0xc0] + stx %i1, [%o0 + 0xc8] + stx %i2, [%o0 + 0xd0] + stx %i3, [%o0 + 0xd8] + stx %i4, [%o0 + 0xe0] + stx %i5, [%o0 + 0xe8] + stx %i6, [%o0 + 0xf0] + stx %i7, [%o0 + 0xf8] + + # save StackGhost cookie + add %i7, %g0, %g4 + save %sp, -176, %sp + # register window flush necessary even without StackGhost + flushw + restore + ldx [%sp + 2047 + 0x78], %g5 + xor %g4, %g5, %g4 + retl + stx %g4, [%o0 + 0x100] + #elif defined(__sparc__) # diff --git a/gnu/llvm/libunwind/src/assembly.h b/gnu/llvm/libunwind/src/assembly.h index 4cf179e13ed..f3fe6863113 100644 --- a/gnu/llvm/libunwind/src/assembly.h +++ b/gnu/llvm/libunwind/src/assembly.h @@ -28,6 +28,8 @@ #ifdef _ARCH_PWR8 #define PPC64_HAS_VMX #endif +#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) +#define SEPARATOR ; #elif defined(__APPLE__) && defined(__aarch64__) #define SEPARATOR %% #else diff --git a/gnu/llvm/libunwind/src/config.h b/gnu/llvm/libunwind/src/config.h index 842fd829af1..656962872b0 100644 --- a/gnu/llvm/libunwind/src/config.h +++ b/gnu/llvm/libunwind/src/config.h @@ -105,6 +105,7 @@ defined(__aarch64__) || \ defined(__mips__) || \ defined(__riscv) || \ + defined(__sparc64__) || \ defined(__hexagon__) #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) #define _LIBUNWIND_BUILD_ZERO_COST_APIS diff --git a/gnu/llvm/libunwind/src/libunwind.cpp b/gnu/llvm/libunwind/src/libunwind.cpp index fd079da3089..b59221c3038 100644 --- a/gnu/llvm/libunwind/src/libunwind.cpp +++ b/gnu/llvm/libunwind/src/libunwind.cpp @@ -58,6 +58,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, # define REGISTER_KIND Registers_mips_newabi #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 #elif defined(__sparc__) # define REGISTER_KIND Registers_sparc #elif defined(__riscv) && __riscv_xlen == 64 |