diff options
author | 2019-02-04 17:04:33 +0000 | |
---|---|---|
committer | 2019-02-04 17:04:33 +0000 | |
commit | 71d9f34297ef5b8104aac6236e8dc7c95ff5da15 (patch) | |
tree | 92fdcc887ac1b153c5e7da9cb557e6207705d89e /lib/libunwind/src | |
parent | Import libc++ 7.0.1. (diff) | |
download | wireguard-openbsd-71d9f34297ef5b8104aac6236e8dc7c95ff5da15.tar.xz wireguard-openbsd-71d9f34297ef5b8104aac6236e8dc7c95ff5da15.zip |
Merge libc++, libc++abi and libunwind version 7.0.1.
Tested by visa on octeon
Tested by kettenis on arm64, armv7 and sparc64
"go for it" deraadt and sthen
Diffstat (limited to 'lib/libunwind/src')
-rw-r--r-- | lib/libunwind/src/AddressSpace.hpp | 29 | ||||
-rw-r--r-- | lib/libunwind/src/DwarfInstructions.hpp | 4 | ||||
-rw-r--r-- | lib/libunwind/src/Registers.hpp | 329 | ||||
-rw-r--r-- | lib/libunwind/src/UnwindCursor.hpp | 14 | ||||
-rw-r--r-- | lib/libunwind/src/UnwindRegistersRestore.S | 332 | ||||
-rw-r--r-- | lib/libunwind/src/UnwindRegistersSave.S | 294 | ||||
-rw-r--r-- | lib/libunwind/src/libunwind.cpp | 20 |
7 files changed, 717 insertions, 305 deletions
diff --git a/lib/libunwind/src/AddressSpace.hpp b/lib/libunwind/src/AddressSpace.hpp index 17145755747..7d1c5249cc9 100644 --- a/lib/libunwind/src/AddressSpace.hpp +++ b/lib/libunwind/src/AddressSpace.hpp @@ -18,7 +18,15 @@ #include <stdlib.h> #include <string.h> -#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) +#ifndef _LIBUNWIND_USE_DLADDR + #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) + #define _LIBUNWIND_USE_DLADDR 1 + #else + #define _LIBUNWIND_USE_DLADDR 0 + #endif +#endif + +#if _LIBUNWIND_USE_DLADDR #include <dlfcn.h> #endif @@ -207,6 +215,7 @@ public: return val; } uintptr_t getP(pint_t addr); + uint64_t getRegister(pint_t addr); static uint64_t getULEB128(pint_t &addr, pint_t end); static int64_t getSLEB128(pint_t &addr, pint_t end); @@ -228,6 +237,14 @@ inline uintptr_t LocalAddressSpace::getP(pint_t addr) { #endif } +inline uint64_t LocalAddressSpace::getRegister(pint_t addr) { +#if __SIZEOF_POINTER__ == 8 || defined(__mips64) + return get64(addr); +#else + return get32(addr); +#endif +} + /// Read a ULEB128 into a 64-bit word. inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { const uint8_t *p = (uint8_t *)addr; @@ -571,7 +588,7 @@ inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, size_t bufLen, unw_word_t *offset) { -#if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) +#if _LIBUNWIND_USE_DLADDR Dl_info dyldInfo; if (dladdr((void *)addr, &dyldInfo)) { if (dyldInfo.dli_sname != NULL) { @@ -604,6 +621,7 @@ public: uint32_t get32(pint_t addr); uint64_t get64(pint_t addr); pint_t getP(pint_t addr); + uint64_t getRegister(pint_t addr); uint64_t getULEB128(pint_t &addr, pint_t end); int64_t getSLEB128(pint_t &addr, pint_t end); pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, @@ -640,7 +658,12 @@ typename P::uint_t RemoteAddressSpace<P>::getP(pint_t addr) { } template <typename P> -uint64_t RemoteAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { +typename P::uint_t OtherAddressSpace<P>::getRegister(pint_t addr) { + return P::getRegister(*(uint64_t *)localCopy(addr)); +} + +template <typename P> +uint64_t OtherAddressSpace<P>::getULEB128(pint_t &addr, pint_t end) { uintptr_t size = (end - addr); LocalAddressSpace::pint_t laddr = (LocalAddressSpace::pint_t) localCopy(addr); LocalAddressSpace::pint_t sladdr = laddr; diff --git a/lib/libunwind/src/DwarfInstructions.hpp b/lib/libunwind/src/DwarfInstructions.hpp index eff054e7a06..93de0c0ea57 100644 --- a/lib/libunwind/src/DwarfInstructions.hpp +++ b/lib/libunwind/src/DwarfInstructions.hpp @@ -82,14 +82,14 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( const RegisterLocation &savedReg) { switch (savedReg.location) { case CFI_Parser<A>::kRegisterInCFA: - return addressSpace.getP(cfa + (pint_t)savedReg.value); + return 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 addressSpace.getP( + return addressSpace.getRegister( evaluateExpression((pint_t)savedReg.value, addressSpace, registers, cfa)); diff --git a/lib/libunwind/src/Registers.hpp b/lib/libunwind/src/Registers.hpp index 6676daa1b09..5696357855d 100644 --- a/lib/libunwind/src/Registers.hpp +++ b/lib/libunwind/src/Registers.hpp @@ -1110,7 +1110,7 @@ inline const char *Registers_ppc::getRegisterName(int regNum) { #endif // _LIBUNWIND_TARGET_PPC #if defined(_LIBUNWIND_TARGET_PPC64) -/// Registers_ppc holds the register state of a thread in a 64-bit PowerPC +/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC /// process. class _LIBUNWIND_HIDDEN Registers_ppc64 { public: @@ -1137,8 +1137,8 @@ public: private: struct ppc64_thread_state_t { - uint64_t __srr0; /* Instruction address register (PC) */ - uint64_t __srr1; /* Machine state register (supervisor) */ + uint64_t __srr0; // Instruction address register (PC) + uint64_t __srr1; // Machine state register (supervisor) uint64_t __r0; uint64_t __r1; uint64_t __r2; @@ -1171,21 +1171,25 @@ private: uint64_t __r29; uint64_t __r30; uint64_t __r31; - uint64_t __cr; /* Condition register */ - uint64_t __xer; /* User's integer exception register */ - uint64_t __lr; /* Link register */ - uint64_t __ctr; /* Count register */ - uint64_t __vrsave; /* Vector Save Register */ + uint64_t __cr; // Condition register + uint64_t __xer; // User's integer exception register + uint64_t __lr; // Link register + uint64_t __ctr; // Count register + uint64_t __vrsave; // Vector Save Register }; - struct ppc64_float_state_t { - double __fpregs[32]; - uint64_t __fpscr; /* floating point status register */ + union ppc64_vsr_t { + struct asfloat_s { + double f; + uint64_t v2; + } asfloat; + v128 v; }; ppc64_thread_state_t _registers; - ppc64_float_state_t _floatRegisters; - v128 _vectorRegisters[32]; + ppc64_vsr_t _vectorScalarRegisters[64]; + + static int getVectorRegNum(int num); }; inline Registers_ppc64::Registers_ppc64(const void *registers) { @@ -1193,32 +1197,29 @@ inline Registers_ppc64::Registers_ppc64(const void *registers) { "ppc64 registers do not fit into unw_context_t"); memcpy(&_registers, static_cast<const uint8_t *>(registers), sizeof(_registers)); - static_assert(sizeof(ppc64_thread_state_t) == 312, - "expected float register offset to be 312"); - memcpy(&_floatRegisters, - static_cast<const uint8_t *>(registers) + sizeof(ppc64_thread_state_t), - sizeof(_floatRegisters)); - static_assert(sizeof(ppc64_thread_state_t) + sizeof(ppc64_float_state_t) == 576, - "expected vector register offset to be 576 bytes"); - memcpy(_vectorRegisters, - static_cast<const uint8_t *>(registers) + sizeof(ppc64_thread_state_t) + - sizeof(ppc64_float_state_t), - sizeof(_vectorRegisters)); + static_assert(sizeof(_registers) == 312, + "expected vector scalar register offset to be 312"); + memcpy(&_vectorScalarRegisters, + static_cast<const uint8_t *>(registers) + sizeof(_registers), + sizeof(_vectorScalarRegisters)); + static_assert(sizeof(_registers) + + sizeof(_vectorScalarRegisters) == 1336, + "expected vector register offset to be 1336 bytes"); } inline Registers_ppc64::Registers_ppc64() { memset(&_registers, 0, sizeof(_registers)); - memset(&_floatRegisters, 0, sizeof(_floatRegisters)); - memset(&_vectorRegisters, 0, sizeof(_vectorRegisters)); + memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters)); } inline bool Registers_ppc64::validRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: case UNW_REG_SP: - case UNW_PPC64_VRSAVE: + case UNW_PPC64_XER: case UNW_PPC64_LR: case UNW_PPC64_CTR: + case UNW_PPC64_VRSAVE: return true; } @@ -1234,11 +1235,10 @@ inline uint64_t Registers_ppc64::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: return _registers.__srr0; - case UNW_REG_SP: - return _registers.__r1; case UNW_PPC64_R0: return _registers.__r0; case UNW_PPC64_R1: + case UNW_REG_SP: return _registers.__r1; case UNW_PPC64_R2: return _registers.__r2; @@ -1300,10 +1300,6 @@ inline uint64_t Registers_ppc64::getRegister(int regNum) const { return _registers.__r30; case UNW_PPC64_R31: return _registers.__r31; - case UNW_PPC64_LR: - return _registers.__lr; - case UNW_PPC64_CTR: - return _registers.__ctr; case UNW_PPC64_CR0: return (_registers.__cr & 0xF0000000); case UNW_PPC64_CR1: @@ -1320,10 +1316,14 @@ inline uint64_t Registers_ppc64::getRegister(int regNum) const { return (_registers.__cr & 0x000000F0); case UNW_PPC64_CR7: return (_registers.__cr & 0x0000000F); + case UNW_PPC64_XER: + return _registers.__xer; + case UNW_PPC64_LR: + return _registers.__lr; + case UNW_PPC64_CTR: + return _registers.__ctr; case UNW_PPC64_VRSAVE: return _registers.__vrsave; - case UNW_PPC64_FPSCR: - return _floatRegisters.__fpscr; } _LIBUNWIND_ABORT("unsupported ppc64 register"); } @@ -1333,13 +1333,11 @@ inline void Registers_ppc64::setRegister(int regNum, uint64_t value) { case UNW_REG_IP: _registers.__srr0 = value; return; - case UNW_REG_SP: - _registers.__r1 = value; - return; case UNW_PPC64_R0: _registers.__r0 = value; return; case UNW_PPC64_R1: + case UNW_REG_SP: _registers.__r1 = value; return; case UNW_PPC64_R2: @@ -1432,12 +1430,6 @@ inline void Registers_ppc64::setRegister(int regNum, uint64_t value) { case UNW_PPC64_R31: _registers.__r31 = value; return; - case UNW_PPC64_LR: - _registers.__lr = value; - return; - case UNW_PPC64_CTR: - _registers.__ctr = value; - return; case UNW_PPC64_CR0: _registers.__cr &= 0x0FFFFFFF; _registers.__cr |= (value & 0xF0000000); @@ -1470,54 +1462,65 @@ inline void Registers_ppc64::setRegister(int regNum, uint64_t value) { _registers.__cr &= 0xFFFFFFF0; _registers.__cr |= (value & 0x0000000F); return; - case UNW_PPC64_VRSAVE: - _registers.__vrsave = value; - return; case UNW_PPC64_XER: _registers.__xer = value; return; - case UNW_PPC64_VSCR: - // not saved + case UNW_PPC64_LR: + _registers.__lr = value; + return; + case UNW_PPC64_CTR: + _registers.__ctr = value; + return; + case UNW_PPC64_VRSAVE: + _registers.__vrsave = value; return; } _LIBUNWIND_ABORT("unsupported ppc64 register"); } inline bool Registers_ppc64::validFloatRegister(int regNum) const { - if (regNum < UNW_PPC64_F0) - return false; - if (regNum > UNW_PPC64_F31) - return false; - return true; + return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31; } inline double Registers_ppc64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); - return _floatRegisters.__fpregs[regNum - UNW_PPC64_F0]; + return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f; } inline void Registers_ppc64::setFloatRegister(int regNum, double value) { assert(validFloatRegister(regNum)); - _floatRegisters.__fpregs[regNum - UNW_PPC64_F0] = value; + _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value; } inline bool Registers_ppc64::validVectorRegister(int regNum) const { - if (regNum < UNW_PPC64_V0) - return false; - if (regNum > UNW_PPC64_V31) - return false; - return true; +#ifdef PPC64_HAS_VMX + if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31) + return true; + if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63) + return true; +#else + if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31) + return true; +#endif + return false; +} + +inline int Registers_ppc64::getVectorRegNum(int num) +{ + if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31) + return num - UNW_PPC64_VS0; + else + return num - UNW_PPC64_VS32 + 32; } inline v128 Registers_ppc64::getVectorRegister(int regNum) const { assert(validVectorRegister(regNum)); - v128 result = _vectorRegisters[regNum - UNW_PPC64_V0]; - return result; + return _vectorScalarRegisters[getVectorRegNum(regNum)].v; } inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) { assert(validVectorRegister(regNum)); - _vectorRegisters[regNum - UNW_PPC64_V0] = value; + _vectorScalarRegisters[getVectorRegNum(regNum)].v = value; } inline const char *Registers_ppc64::getRegisterName(int regNum) { @@ -1590,6 +1593,30 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { return "r30"; case UNW_PPC64_R31: return "r31"; + case UNW_PPC64_CR0: + return "cr0"; + case UNW_PPC64_CR1: + return "cr1"; + case UNW_PPC64_CR2: + return "cr2"; + case UNW_PPC64_CR3: + return "cr3"; + case UNW_PPC64_CR4: + return "cr4"; + case UNW_PPC64_CR5: + return "cr5"; + case UNW_PPC64_CR6: + return "cr6"; + case UNW_PPC64_CR7: + return "cr7"; + case UNW_PPC64_XER: + return "xer"; + case UNW_PPC64_LR: + return "lr"; + case UNW_PPC64_CTR: + return "ctr"; + case UNW_PPC64_VRSAVE: + return "vrsave"; case UNW_PPC64_F0: return "fp0"; case UNW_PPC64_F1: @@ -1654,35 +1681,72 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { return "fp30"; case UNW_PPC64_F31: return "fp31"; - case UNW_PPC64_LR: - return "lr"; - case UNW_PPC64_CTR: - return "ctr"; - case UNW_PPC64_CR0: - return "cr0"; - case UNW_PPC64_CR1: - return "cr1"; - case UNW_PPC64_CR2: - return "cr2"; - case UNW_PPC64_CR3: - return "cr3"; - case UNW_PPC64_CR4: - return "cr4"; - case UNW_PPC64_CR5: - return "cr5"; - case UNW_PPC64_CR6: - return "cr6"; - case UNW_PPC64_CR7: - return "cr7"; - case UNW_PPC64_XER: - return "xer"; - case UNW_PPC64_VRSAVE: - return "vrsave"; - case UNW_PPC64_FPSCR: - return "fpscr"; - default: - return "unknown register"; + case UNW_PPC64_V0: + return "v0"; + case UNW_PPC64_V1: + return "v1"; + case UNW_PPC64_V2: + return "v2"; + case UNW_PPC64_V3: + return "v3"; + case UNW_PPC64_V4: + return "v4"; + case UNW_PPC64_V5: + return "v5"; + case UNW_PPC64_V6: + return "v6"; + case UNW_PPC64_V7: + return "v7"; + case UNW_PPC64_V8: + return "v8"; + case UNW_PPC64_V9: + return "v9"; + case UNW_PPC64_V10: + return "v10"; + case UNW_PPC64_V11: + return "v11"; + case UNW_PPC64_V12: + return "v12"; + case UNW_PPC64_V13: + return "v13"; + case UNW_PPC64_V14: + return "v14"; + case UNW_PPC64_V15: + return "v15"; + case UNW_PPC64_V16: + return "v16"; + case UNW_PPC64_V17: + return "v17"; + case UNW_PPC64_V18: + return "v18"; + case UNW_PPC64_V19: + return "v19"; + case UNW_PPC64_V20: + return "v20"; + case UNW_PPC64_V21: + return "v21"; + case UNW_PPC64_V22: + return "v22"; + case UNW_PPC64_V23: + return "v23"; + case UNW_PPC64_V24: + return "v24"; + case UNW_PPC64_V25: + return "v25"; + case UNW_PPC64_V26: + return "v26"; + case UNW_PPC64_V27: + return "v27"; + case UNW_PPC64_V28: + return "v28"; + case UNW_PPC64_V29: + return "v29"; + case UNW_PPC64_V30: + return "v30"; + case UNW_PPC64_V31: + return "v31"; } + return "unknown register"; } #endif // _LIBUNWIND_TARGET_PPC64 @@ -2462,13 +2526,15 @@ public: uint64_t getSP() const { return _registers.__r[1]; } void setSP(uint32_t value) { _registers.__r[1] = value; } - uint64_t getIP() const { return _registers.__r[9]; } - void setIP(uint32_t value) { _registers.__r[9] = 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 { - unsigned int __r[32]; + unsigned int __r[32]; // r0-r31 + unsigned int __pc; // Program counter + unsigned int __epcr; // Program counter at exception }; or1k_thread_state_t _registers; @@ -2494,6 +2560,8 @@ inline bool Registers_or1k::validRegister(int regNum) const { return false; if (regNum <= UNW_OR1K_R31) return true; + if (regNum == UNW_OR1K_EPCR) + return true; return false; } @@ -2503,9 +2571,11 @@ inline uint32_t Registers_or1k::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: - return _registers.__r[9]; + return _registers.__pc; case UNW_REG_SP: return _registers.__r[1]; + case UNW_OR1K_EPCR: + return _registers.__epcr; } _LIBUNWIND_ABORT("unsupported or1k register"); } @@ -2518,11 +2588,14 @@ inline void Registers_or1k::setRegister(int regNum, uint32_t value) { switch (regNum) { case UNW_REG_IP: - _registers.__r[9] = value; + _registers.__pc = value; return; case UNW_REG_SP: _registers.__r[1] = value; return; + case UNW_OR1K_EPCR: + _registers.__epcr = value; + return; } _LIBUNWIND_ABORT("unsupported or1k register"); } @@ -2618,6 +2691,8 @@ inline const char *Registers_or1k::getRegisterName(int regNum) { return "r30"; case UNW_OR1K_R31: return "r31"; + case UNW_OR1K_EPCR: + return "EPCR"; default: return "unknown register"; } @@ -3088,13 +3163,13 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_MIPS_O32 -#if defined(_LIBUNWIND_TARGET_MIPS_N64) -/// Registers_mips_n64 holds the register state of a thread in a 64-bit MIPS -/// process. -class _LIBUNWIND_HIDDEN Registers_mips_n64 { +#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) +/// Registers_mips_newabi holds the register state of a thread in a +/// MIPS process using NEWABI (the N32 or N64 ABIs). +class _LIBUNWIND_HIDDEN Registers_mips_newabi { public: - Registers_mips_n64(); - Registers_mips_n64(const void *registers); + Registers_mips_newabi(); + Registers_mips_newabi(const void *registers); bool validRegister(int num) const; uint64_t getRegister(int num) const; @@ -3116,31 +3191,31 @@ public: uint32_t getWCookie() const { return 0; } private: - struct mips_n64_thread_state_t { + struct mips_newabi_thread_state_t { uint64_t __r[32]; uint64_t __pc; uint64_t __hi; uint64_t __lo; }; - mips_n64_thread_state_t _registers; + mips_newabi_thread_state_t _registers; #ifdef __mips_hard_float double _floats[32]; #endif }; -inline Registers_mips_n64::Registers_mips_n64(const void *registers) { - static_assert((check_fit<Registers_mips_n64, unw_context_t>::does_fit), - "mips_n64 registers do not fit into unw_context_t"); +inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) { + static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit), + "mips_newabi registers do not fit into unw_context_t"); memcpy(&_registers, static_cast<const uint8_t *>(registers), sizeof(_registers)); } -inline Registers_mips_n64::Registers_mips_n64() { +inline Registers_mips_newabi::Registers_mips_newabi() { memset(&_registers, 0, sizeof(_registers)); } -inline bool Registers_mips_n64::validRegister(int regNum) const { +inline bool Registers_mips_newabi::validRegister(int regNum) const { if (regNum == UNW_REG_IP) return true; if (regNum == UNW_REG_SP) @@ -3157,7 +3232,7 @@ inline bool Registers_mips_n64::validRegister(int regNum) const { return false; } -inline uint64_t Registers_mips_n64::getRegister(int regNum) const { +inline uint64_t Registers_mips_newabi::getRegister(int regNum) const { if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) return _registers.__r[regNum - UNW_MIPS_R0]; @@ -3171,10 +3246,10 @@ inline uint64_t Registers_mips_n64::getRegister(int regNum) const { case UNW_MIPS_LO: return _registers.__lo; } - _LIBUNWIND_ABORT("unsupported mips_n64 register"); + _LIBUNWIND_ABORT("unsupported mips_newabi register"); } -inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) { +inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) { if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { _registers.__r[regNum - UNW_MIPS_R0] = value; return; @@ -3194,10 +3269,10 @@ inline void Registers_mips_n64::setRegister(int regNum, uint64_t value) { _registers.__lo = value; return; } - _LIBUNWIND_ABORT("unsupported mips_n64 register"); + _LIBUNWIND_ABORT("unsupported mips_newabi register"); } -inline bool Registers_mips_n64::validFloatRegister(int regNum) const { +inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { #ifdef __mips_hard_float if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) return true; @@ -3205,38 +3280,38 @@ inline bool Registers_mips_n64::validFloatRegister(int regNum) const { return false; } -inline double Registers_mips_n64::getFloatRegister(int regNum) const { +inline double Registers_mips_newabi::getFloatRegister(int regNum) const { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); return _floats[regNum - UNW_MIPS_F0]; #else - _LIBUNWIND_ABORT("mips_n64 float support not implemented"); + _LIBUNWIND_ABORT("mips_newabi float support not implemented"); #endif } -inline void Registers_mips_n64::setFloatRegister(int regNum, - double value) { +inline void Registers_mips_newabi::setFloatRegister(int regNum, + double value) { #ifdef __mips_hard_float assert(validFloatRegister(regNum)); _floats[regNum - UNW_MIPS_F0] = value; #else - _LIBUNWIND_ABORT("mips_n64 float support not implemented"); + _LIBUNWIND_ABORT("mips_newabi float support not implemented"); #endif } -inline bool Registers_mips_n64::validVectorRegister(int /* regNum */) const { +inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const { return false; } -inline v128 Registers_mips_n64::getVectorRegister(int /* regNum */) const { - _LIBUNWIND_ABORT("mips_n64 vector support not implemented"); +inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const { + _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); } -inline void Registers_mips_n64::setVectorRegister(int /* regNum */, v128 /* value */) { - _LIBUNWIND_ABORT("mips_n64 vector support not implemented"); +inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) { + _LIBUNWIND_ABORT("mips_newabi vector support not implemented"); } -inline const char *Registers_mips_n64::getRegisterName(int regNum) { +inline const char *Registers_mips_newabi::getRegisterName(int regNum) { switch (regNum) { case UNW_MIPS_R0: return "$0"; @@ -3374,7 +3449,7 @@ inline const char *Registers_mips_n64::getRegisterName(int regNum) { return "unknown register"; } } -#endif // _LIBUNWIND_TARGET_MIPS_N64 +#endif // _LIBUNWIND_TARGET_MIPS_NEWABI } // namespace libunwind #endif // __REGISTERS_HPP__ diff --git a/lib/libunwind/src/UnwindCursor.hpp b/lib/libunwind/src/UnwindCursor.hpp index df12a16d5d7..3268bbbedcc 100644 --- a/lib/libunwind/src/UnwindCursor.hpp +++ b/lib/libunwind/src/UnwindCursor.hpp @@ -521,8 +521,8 @@ private: } #endif -#if defined(_LIBUNWIND_TARGET_MIPS_N64) - int stepWithCompactEncoding(Registers_mips_n64 &) { +#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) + int stepWithCompactEncoding(Registers_mips_newabi &) { return UNW_EINVAL; } #endif @@ -583,8 +583,8 @@ private: } #endif -#if defined(_LIBUNWIND_TARGET_MIPS_N64) - bool compactSaysUseDwarf(Registers_mips_n64 &, uint32_t *) const { +#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) + bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const { return true; } #endif @@ -644,8 +644,8 @@ private: } #endif -#if defined (_LIBUNWIND_TARGET_MIPS_N64) - compact_unwind_encoding_t dwarfEncoding(Registers_mips_n64 &) const { +#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI) + compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const { return 0; } #endif @@ -1417,8 +1417,6 @@ int UnwindCursor<A, R>::step() { this->setInfoBasedOnIPRegister(true); if (_unwindInfoMissing) return UNW_STEP_END; - if (_info.gp) - setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp); } return result; diff --git a/lib/libunwind/src/UnwindRegistersRestore.S b/lib/libunwind/src/UnwindRegistersRestore.S index f73b51acf46..92a3f8bb433 100644 --- a/lib/libunwind/src/UnwindRegistersRestore.S +++ b/lib/libunwind/src/UnwindRegistersRestore.S @@ -138,89 +138,259 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) // thread_state pointer is in r3 // +// load register (GPR) +#define PPC64_LR(n) \ + ld %r##n, (8 * (n + 2))(%r3) + // restore integral registers // skip r0 for now // skip r1 for now - ld %r2, 32(%r3) + PPC64_LR(2) // skip r3 for now // skip r4 for now // skip r5 for now - ld %r6, 64(%r3) - ld %r7, 72(%r3) - ld %r8, 80(%r3) - ld %r9, 88(%r3) - ld %r10, 96(%r3) - ld %r11, 104(%r3) - ld %r12, 112(%r3) - ld %r13, 120(%r3) - ld %r14, 128(%r3) - ld %r15, 136(%r3) - ld %r16, 144(%r3) - ld %r17, 152(%r3) - ld %r18, 160(%r3) - ld %r19, 168(%r3) - ld %r20, 176(%r3) - ld %r21, 184(%r3) - ld %r22, 192(%r3) - ld %r23, 200(%r3) - ld %r24, 208(%r3) - ld %r25, 216(%r3) - ld %r26, 224(%r3) - ld %r27, 232(%r3) - ld %r28, 240(%r3) - ld %r29, 248(%r3) - ld %r30, 256(%r3) - ld %r31, 264(%r3) - - //restore float registers - lfd %f0, 312(%r3) - lfd %f1, 320(%r3) - lfd %f2, 328(%r3) - lfd %f3, 336(%r3) - lfd %f4, 344(%r3) - lfd %f5, 352(%r3) - lfd %f6, 360(%r3) - lfd %f7, 368(%r3) - lfd %f8, 376(%r3) - lfd %f9, 384(%r3) - lfd %f10, 392(%r3) - lfd %f11, 400(%r3) - lfd %f12, 408(%r3) - lfd %f13, 416(%r3) - lfd %f14, 424(%r3) - lfd %f15, 432(%r3) - lfd %f16, 440(%r3) - lfd %f17, 448(%r3) - lfd %f18, 456(%r3) - lfd %f19, 464(%r3) - lfd %f20, 472(%r3) - lfd %f21, 480(%r3) - lfd %f22, 488(%r3) - lfd %f23, 496(%r3) - lfd %f24, 504(%r3) - lfd %f25, 512(%r3) - lfd %f26, 520(%r3) - lfd %f27, 528(%r3) - lfd %f28, 536(%r3) - lfd %f29, 544(%r3) - lfd %f30, 552(%r3) - lfd %f31, 560(%r3) - - //TODO: restore vector registers - - // Lnovec: - ld %r0, 272(%r3) // __cr + PPC64_LR(6) + PPC64_LR(7) + PPC64_LR(8) + PPC64_LR(9) + PPC64_LR(10) + PPC64_LR(11) + PPC64_LR(12) + PPC64_LR(13) + PPC64_LR(14) + PPC64_LR(15) + PPC64_LR(16) + PPC64_LR(17) + PPC64_LR(18) + PPC64_LR(19) + PPC64_LR(20) + PPC64_LR(21) + PPC64_LR(22) + PPC64_LR(23) + PPC64_LR(24) + PPC64_LR(25) + PPC64_LR(26) + PPC64_LR(27) + PPC64_LR(28) + PPC64_LR(29) + PPC64_LR(30) + PPC64_LR(31) + +#ifdef PPC64_HAS_VMX + + // restore VS registers + // (note that this also restores floating point registers and V registers, + // because part of VS is mapped to these registers) + + addi %r4, %r3, PPC64_OFFS_FP + +// load VS register +#define PPC64_LVS(n) \ + lxvd2x %vs##n, 0, %r4 ;\ + addi %r4, %r4, 16 + + // restore the first 32 VS regs (and also all floating point regs) + PPC64_LVS(0) + PPC64_LVS(1) + PPC64_LVS(2) + PPC64_LVS(3) + PPC64_LVS(4) + PPC64_LVS(5) + PPC64_LVS(6) + PPC64_LVS(7) + PPC64_LVS(8) + PPC64_LVS(9) + PPC64_LVS(10) + PPC64_LVS(11) + PPC64_LVS(12) + PPC64_LVS(13) + PPC64_LVS(14) + PPC64_LVS(15) + PPC64_LVS(16) + PPC64_LVS(17) + PPC64_LVS(18) + PPC64_LVS(19) + PPC64_LVS(20) + PPC64_LVS(21) + PPC64_LVS(22) + PPC64_LVS(23) + PPC64_LVS(24) + PPC64_LVS(25) + PPC64_LVS(26) + PPC64_LVS(27) + PPC64_LVS(28) + PPC64_LVS(29) + PPC64_LVS(30) + PPC64_LVS(31) + + // use VRSAVE to conditionally restore the remaining VS regs, + // that are where the V regs are mapped + + ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave + cmpwi %r5, 0 + beq Lnovec + +// conditionally load VS +#define PPC64_CLVS_BOTTOM(n) \ + beq Ldone##n ;\ + addi %r4, %r3, PPC64_OFFS_FP + n * 16 ;\ + lxvd2x %vs##n, 0, %r4 ;\ +Ldone##n: + +#define PPC64_CLVSl(n) \ + andis. %r0, %r5, (1<<(47-n)) ;\ +PPC64_CLVS_BOTTOM(n) + +#define PPC64_CLVSh(n) \ + andi. %r0, %r5, (1<<(63-n)) ;\ +PPC64_CLVS_BOTTOM(n) + + PPC64_CLVSl(32) + PPC64_CLVSl(33) + PPC64_CLVSl(34) + PPC64_CLVSl(35) + PPC64_CLVSl(36) + PPC64_CLVSl(37) + PPC64_CLVSl(38) + PPC64_CLVSl(39) + PPC64_CLVSl(40) + PPC64_CLVSl(41) + PPC64_CLVSl(42) + PPC64_CLVSl(43) + PPC64_CLVSl(44) + PPC64_CLVSl(45) + PPC64_CLVSl(46) + PPC64_CLVSl(47) + PPC64_CLVSh(48) + PPC64_CLVSh(49) + PPC64_CLVSh(50) + PPC64_CLVSh(51) + PPC64_CLVSh(52) + PPC64_CLVSh(53) + PPC64_CLVSh(54) + PPC64_CLVSh(55) + PPC64_CLVSh(56) + PPC64_CLVSh(57) + PPC64_CLVSh(58) + PPC64_CLVSh(59) + PPC64_CLVSh(60) + PPC64_CLVSh(61) + PPC64_CLVSh(62) + PPC64_CLVSh(63) + +#else + +// load FP register +#define PPC64_LF(n) \ + lfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) + + // restore float registers + PPC64_LF(0) + PPC64_LF(1) + PPC64_LF(2) + PPC64_LF(3) + PPC64_LF(4) + PPC64_LF(5) + PPC64_LF(6) + PPC64_LF(7) + PPC64_LF(8) + PPC64_LF(9) + PPC64_LF(10) + PPC64_LF(11) + PPC64_LF(12) + PPC64_LF(13) + PPC64_LF(14) + PPC64_LF(15) + PPC64_LF(16) + PPC64_LF(17) + PPC64_LF(18) + PPC64_LF(19) + PPC64_LF(20) + PPC64_LF(21) + PPC64_LF(22) + PPC64_LF(23) + PPC64_LF(24) + PPC64_LF(25) + PPC64_LF(26) + PPC64_LF(27) + PPC64_LF(28) + PPC64_LF(29) + PPC64_LF(30) + PPC64_LF(31) + + // restore vector registers if any are in use + ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave + cmpwi %r5, 0 + beq Lnovec + + subi %r4, %r1, 16 + // r4 is now a 16-byte aligned pointer into the red zone + // the _vectorScalarRegisters may not be 16-byte aligned + // so copy via red zone temp buffer + +#define PPC64_CLV_UNALIGNED_BOTTOM(n) \ + beq Ldone##n ;\ + ld %r0, (PPC64_OFFS_V + n * 16)(%r3) ;\ + std %r0, 0(%r4) ;\ + ld %r0, (PPC64_OFFS_V + n * 16 + 8)(%r3) ;\ + std %r0, 8(%r4) ;\ + lvx %v##n, 0, %r4 ;\ +Ldone ## n: + +#define PPC64_CLV_UNALIGNEDl(n) \ + andis. %r0, %r5, (1<<(15-n)) ;\ +PPC64_CLV_UNALIGNED_BOTTOM(n) + +#define PPC64_CLV_UNALIGNEDh(n) \ + andi. %r0, %r5, (1<<(31-n)) ;\ +PPC64_CLV_UNALIGNED_BOTTOM(n) + + PPC64_CLV_UNALIGNEDl(0) + PPC64_CLV_UNALIGNEDl(1) + PPC64_CLV_UNALIGNEDl(2) + PPC64_CLV_UNALIGNEDl(3) + PPC64_CLV_UNALIGNEDl(4) + PPC64_CLV_UNALIGNEDl(5) + PPC64_CLV_UNALIGNEDl(6) + PPC64_CLV_UNALIGNEDl(7) + PPC64_CLV_UNALIGNEDl(8) + PPC64_CLV_UNALIGNEDl(9) + PPC64_CLV_UNALIGNEDl(10) + PPC64_CLV_UNALIGNEDl(11) + PPC64_CLV_UNALIGNEDl(12) + PPC64_CLV_UNALIGNEDl(13) + PPC64_CLV_UNALIGNEDl(14) + PPC64_CLV_UNALIGNEDl(15) + PPC64_CLV_UNALIGNEDh(16) + PPC64_CLV_UNALIGNEDh(17) + PPC64_CLV_UNALIGNEDh(18) + PPC64_CLV_UNALIGNEDh(19) + PPC64_CLV_UNALIGNEDh(20) + PPC64_CLV_UNALIGNEDh(21) + PPC64_CLV_UNALIGNEDh(22) + PPC64_CLV_UNALIGNEDh(23) + PPC64_CLV_UNALIGNEDh(24) + PPC64_CLV_UNALIGNEDh(25) + PPC64_CLV_UNALIGNEDh(26) + PPC64_CLV_UNALIGNEDh(27) + PPC64_CLV_UNALIGNEDh(28) + PPC64_CLV_UNALIGNEDh(29) + PPC64_CLV_UNALIGNEDh(30) + PPC64_CLV_UNALIGNEDh(31) + +#endif + +Lnovec: + ld %r0, PPC64_OFFS_CR(%r3) mtcr %r0 - ld %r0, 296(%r3) // __ctr - mtctr %r0 - ld %r0, 0(%r3) // __ssr0 + ld %r0, PPC64_OFFS_SRR0(%r3) mtctr %r0 - ld %r0, 16(%r3) - ld %r5, 56(%r3) - ld %r4, 48(%r3) - ld %r1, 24(%r3) - ld %r3, 40(%r3) + PPC64_LR(0) + PPC64_LR(5) + PPC64_LR(4) + PPC64_LR(1) + PPC64_LR(3) bctr #elif defined(__ppc__) @@ -588,7 +758,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) # thread_state pointer is in r3 # - # restore integral registerrs + # restore integral registers l.lwz r0, 0(r3) l.lwz r1, 4(r3) l.lwz r2, 8(r3) @@ -598,7 +768,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) l.lwz r6, 24(r3) l.lwz r7, 28(r3) l.lwz r8, 32(r3) - l.lwz r9, 36(r3) + # skip r9 l.lwz r10, 40(r3) l.lwz r11, 44(r3) l.lwz r12, 48(r3) @@ -625,6 +795,8 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) # at last, restore r3 l.lwz r3, 12(r3) + # load new pc into ra + l.lwz r9, 128(r3) # jump to pc l.jr r9 l.nop @@ -672,7 +844,7 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind17Registers_sparc646jumptoEv) jmpl %o7 + 8, %g0 ldx [%o0 + 0x40], %o0 -#elif defined(__mips__) && defined(_ABIO32) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 // // void libunwind::Registers_mips_o32::jumpto() @@ -781,15 +953,15 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv) lw $4, (4 * 4)($4) .set pop -#elif defined(__mips__) && defined(_ABI64) +#elif defined(__mips64) // -// void libunwind::Registers_mips_n64::jumpto() +// void libunwind::Registers_mips_newabi::jumpto() // // On entry: // thread state pointer is in a0 ($4) // -DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind18Registers_mips_n646jumptoEv) +DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) .set push .set noat .set noreorder diff --git a/lib/libunwind/src/UnwindRegistersSave.S b/lib/libunwind/src/UnwindRegistersSave.S index bf951d642c1..0df3d5b17a2 100644 --- a/lib/libunwind/src/UnwindRegistersSave.S +++ b/lib/libunwind/src/UnwindRegistersSave.S @@ -116,7 +116,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) xorl %eax, %eax # return UNW_ESUCCESS ret -#elif defined(__mips__) && defined(_ABIO32) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # # extern int unw_getcontext(unw_context_t* thread_state) @@ -225,7 +225,7 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) or $2, $0, $0 .set pop -#elif defined(__mips__) && defined(_ABI64) +#elif defined(__mips64) # # extern int unw_getcontext(unw_context_t* thread_state) @@ -333,95 +333,223 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) // thread_state pointer is in r3 // DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) - std %r0, 16(%r3) + +// store register (GPR) +#define PPC64_STR(n) \ + std %r##n, (8 * (n + 2))(%r3) + + // save GPRs + PPC64_STR(0) mflr %r0 - std %r0, 0(%r3) // store lr as ssr0 - std %r1, 24(%r3) - std %r2, 32(%r3) - std %r3, 40(%r3) - std %r4, 48(%r3) - std %r5, 56(%r3) - std %r6, 64(%r3) - std %r7, 72(%r3) - std %r8, 80(%r3) - std %r9, 88(%r3) - std %r10, 96(%r3) - std %r11, 104(%r3) - std %r12, 112(%r3) - std %r13, 120(%r3) - std %r14, 128(%r3) - std %r15, 136(%r3) - std %r16, 144(%r3) - std %r17, 152(%r3) - std %r18, 160(%r3) - std %r19, 168(%r3) - std %r20, 176(%r3) - std %r21, 184(%r3) - std %r22, 192(%r3) - std %r23, 200(%r3) - std %r24, 208(%r3) - std %r25, 216(%r3) - std %r26, 224(%r3) - std %r27, 232(%r3) - std %r28, 240(%r3) - std %r29, 248(%r3) - std %r30, 256(%r3) - std %r31, 264(%r3) + std %r0, PPC64_OFFS_SRR0(%r3) // store lr as ssr0 + PPC64_STR(1) + PPC64_STR(2) + PPC64_STR(3) + PPC64_STR(4) + PPC64_STR(5) + PPC64_STR(6) + PPC64_STR(7) + PPC64_STR(8) + PPC64_STR(9) + PPC64_STR(10) + PPC64_STR(11) + PPC64_STR(12) + PPC64_STR(13) + PPC64_STR(14) + PPC64_STR(15) + PPC64_STR(16) + PPC64_STR(17) + PPC64_STR(18) + PPC64_STR(19) + PPC64_STR(20) + PPC64_STR(21) + PPC64_STR(22) + PPC64_STR(23) + PPC64_STR(24) + PPC64_STR(25) + PPC64_STR(26) + PPC64_STR(27) + PPC64_STR(28) + PPC64_STR(29) + PPC64_STR(30) + PPC64_STR(31) mfcr %r0 - std %r0, 272(%r3) - + std %r0, PPC64_OFFS_CR(%r3) mfxer %r0 - std %r0, 280(%r3) - + std %r0, PPC64_OFFS_XER(%r3) mflr %r0 - std %r0, 288(%r3) - + std %r0, PPC64_OFFS_LR(%r3) mfctr %r0 - std %r0, 296(%r3) - + std %r0, PPC64_OFFS_CTR(%r3) mfvrsave %r0 - std %r0, 304(%r3) + std %r0, PPC64_OFFS_VRSAVE(%r3) + +#ifdef PPC64_HAS_VMX + // save VS registers + // (note that this also saves floating point registers and V registers, + // because part of VS is mapped to these registers) + + addi %r4, %r3, PPC64_OFFS_FP + +// store VS register +#define PPC64_STVS(n) \ + stxvd2x %vs##n, 0, %r4 ;\ + addi %r4, %r4, 16 + + PPC64_STVS(0) + PPC64_STVS(1) + PPC64_STVS(2) + PPC64_STVS(3) + PPC64_STVS(4) + PPC64_STVS(5) + PPC64_STVS(6) + PPC64_STVS(7) + PPC64_STVS(8) + PPC64_STVS(9) + PPC64_STVS(10) + PPC64_STVS(11) + PPC64_STVS(12) + PPC64_STVS(13) + PPC64_STVS(14) + PPC64_STVS(15) + PPC64_STVS(16) + PPC64_STVS(17) + PPC64_STVS(18) + PPC64_STVS(19) + PPC64_STVS(20) + PPC64_STVS(21) + PPC64_STVS(22) + PPC64_STVS(23) + PPC64_STVS(24) + PPC64_STVS(25) + PPC64_STVS(26) + PPC64_STVS(27) + PPC64_STVS(28) + PPC64_STVS(29) + PPC64_STVS(30) + PPC64_STVS(31) + PPC64_STVS(32) + PPC64_STVS(33) + PPC64_STVS(34) + PPC64_STVS(35) + PPC64_STVS(36) + PPC64_STVS(37) + PPC64_STVS(38) + PPC64_STVS(39) + PPC64_STVS(40) + PPC64_STVS(41) + PPC64_STVS(42) + PPC64_STVS(43) + PPC64_STVS(44) + PPC64_STVS(45) + PPC64_STVS(46) + PPC64_STVS(47) + PPC64_STVS(48) + PPC64_STVS(49) + PPC64_STVS(50) + PPC64_STVS(51) + PPC64_STVS(52) + PPC64_STVS(53) + PPC64_STVS(54) + PPC64_STVS(55) + PPC64_STVS(56) + PPC64_STVS(57) + PPC64_STVS(58) + PPC64_STVS(59) + PPC64_STVS(60) + PPC64_STVS(61) + PPC64_STVS(62) + PPC64_STVS(63) + +#else + +// store FP register +#define PPC64_STF(n) \ + stfd %f##n, (PPC64_OFFS_FP + n * 16)(%r3) // save float registers - stfd %f0, 312(%r3) - stfd %f1, 320(%r3) - stfd %f2, 328(%r3) - stfd %f3, 336(%r3) - stfd %f4, 344(%r3) - stfd %f5, 352(%r3) - stfd %f6, 360(%r3) - stfd %f7, 368(%r3) - stfd %f8, 376(%r3) - stfd %f9, 384(%r3) - stfd %f10, 392(%r3) - stfd %f11, 400(%r3) - stfd %f12, 408(%r3) - stfd %f13, 416(%r3) - stfd %f14, 424(%r3) - stfd %f15, 432(%r3) - stfd %f16, 440(%r3) - stfd %f17, 448(%r3) - stfd %f18, 456(%r3) - stfd %f19, 464(%r3) - stfd %f20, 472(%r3) - stfd %f21, 480(%r3) - stfd %f22, 488(%r3) - stfd %f23, 496(%r3) - stfd %f24, 504(%r3) - stfd %f25, 512(%r3) - stfd %f26, 520(%r3) - stfd %f27, 528(%r3) - stfd %f28, 536(%r3) - stfd %f29, 544(%r3) - stfd %f30, 552(%r3) - stfd %f31, 560(%r3) - - mffs %f0 - stfd %f0, 568(%r3) - - //TODO: save vector registers + PPC64_STF(0) + PPC64_STF(1) + PPC64_STF(2) + PPC64_STF(3) + PPC64_STF(4) + PPC64_STF(5) + PPC64_STF(6) + PPC64_STF(7) + PPC64_STF(8) + PPC64_STF(9) + PPC64_STF(10) + PPC64_STF(11) + PPC64_STF(12) + PPC64_STF(13) + PPC64_STF(14) + PPC64_STF(15) + PPC64_STF(16) + PPC64_STF(17) + PPC64_STF(18) + PPC64_STF(19) + PPC64_STF(20) + PPC64_STF(21) + PPC64_STF(22) + PPC64_STF(23) + PPC64_STF(24) + PPC64_STF(25) + PPC64_STF(26) + PPC64_STF(27) + PPC64_STF(28) + PPC64_STF(29) + PPC64_STF(30) + PPC64_STF(31) + + // save vector registers + + // Use 16-bytes below the stack pointer as an + // aligned buffer to save each vector register. + // Note that the stack pointer is always 16-byte aligned. + subi %r4, %r1, 16 + +#define PPC64_STV_UNALIGNED(n) \ + stvx %v##n, 0, %r4 ;\ + ld %r5, 0(%r4) ;\ + std %r5, (PPC64_OFFS_V + n * 16)(%r3) ;\ + ld %r5, 8(%r4) ;\ + std %r5, (PPC64_OFFS_V + n * 16 + 8)(%r3) + + PPC64_STV_UNALIGNED(0) + PPC64_STV_UNALIGNED(1) + PPC64_STV_UNALIGNED(2) + PPC64_STV_UNALIGNED(3) + PPC64_STV_UNALIGNED(4) + PPC64_STV_UNALIGNED(5) + PPC64_STV_UNALIGNED(6) + PPC64_STV_UNALIGNED(7) + PPC64_STV_UNALIGNED(8) + PPC64_STV_UNALIGNED(9) + PPC64_STV_UNALIGNED(10) + PPC64_STV_UNALIGNED(11) + PPC64_STV_UNALIGNED(12) + PPC64_STV_UNALIGNED(13) + PPC64_STV_UNALIGNED(14) + PPC64_STV_UNALIGNED(15) + PPC64_STV_UNALIGNED(16) + PPC64_STV_UNALIGNED(17) + PPC64_STV_UNALIGNED(18) + PPC64_STV_UNALIGNED(19) + PPC64_STV_UNALIGNED(20) + PPC64_STV_UNALIGNED(21) + PPC64_STV_UNALIGNED(22) + PPC64_STV_UNALIGNED(23) + PPC64_STV_UNALIGNED(24) + PPC64_STV_UNALIGNED(25) + PPC64_STV_UNALIGNED(26) + PPC64_STV_UNALIGNED(27) + PPC64_STV_UNALIGNED(28) + PPC64_STV_UNALIGNED(29) + PPC64_STV_UNALIGNED(30) + PPC64_STV_UNALIGNED(31) +#endif li %r3, 0 // return UNW_ESUCCESS blr @@ -810,6 +938,10 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext) l.sw 116(r3), r29 l.sw 120(r3), r30 l.sw 124(r3), r31 + # store ra to pc + l.sw 128(r3), r9 + # zero epcr + l.sw 132(r3), r0 #elif defined(__sparc__) && defined(__arch64__) diff --git a/lib/libunwind/src/libunwind.cpp b/lib/libunwind/src/libunwind.cpp index 632535ac470..20067994e7a 100644 --- a/lib/libunwind/src/libunwind.cpp +++ b/lib/libunwind/src/libunwind.cpp @@ -61,10 +61,10 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor, # define REGISTER_KIND Registers_arm #elif defined(__or1k__) # define REGISTER_KIND Registers_or1k -#elif defined(__mips__) && defined(_ABIO32) +#elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 # define REGISTER_KIND Registers_mips_o32 -#elif defined(__mips__) && defined(_ABI64) -# define REGISTER_KIND Registers_mips_n64 +#elif defined(__mips64) +# 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__) @@ -190,8 +190,20 @@ _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, co->setReg(regNum, (pint_t)value); // specical case altering IP to re-find info (being called by personality // function) - if (regNum == UNW_REG_IP) + if (regNum == UNW_REG_IP) { + unw_proc_info_t info; + // First, get the FDE for the old location and then update it. + co->getInfo(&info); co->setInfoBasedOnIPRegister(false); + // If the original call expects stack adjustment, perform this now. + // Normal frame unwinding would have included the offset already in the + // CFA computation. + // Note: for PA-RISC and other platforms where the stack grows up, + // this should actually be - info.gp. LLVM doesn't currently support + // any such platforms and Clang doesn't export a macro for them. + if (info.gp) + co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp); + } return UNW_ESUCCESS; } return UNW_EBADREG; |