diff --git a/lib/libunwind/include/__libunwind_config.h b/lib/libunwind/include/__libunwind_config.h index 6e7e5e6f7f..4d03bd83d8 100644 --- a/lib/libunwind/include/__libunwind_config.h +++ b/lib/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_RISCV 64 #if defined(_LIBUNWIND_IS_NATIVE_ONLY) # if defined(__i386__) @@ -118,6 +119,15 @@ #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC #define _LIBUNWIND_CONTEXT_SIZE 16 #define _LIBUNWIND_CURSOR_SIZE 23 +# elif defined(__riscv) +# if __riscv_xlen == 64 +# define _LIBUNWIND_TARGET_RISCV 1 +# define _LIBUNWIND_CONTEXT_SIZE 64 +# define _LIBUNWIND_CURSOR_SIZE 76 +# else +# error "Unsupported RISC-V ABI" +# endif +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV # else # error "Unsupported architecture." # endif @@ -132,6 +142,7 @@ # define _LIBUNWIND_TARGET_MIPS_O32 1 # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 # define _LIBUNWIND_TARGET_SPARC 1 +# define _LIBUNWIND_TARGET_RISCV 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 d06724d3c3..1a501b867d 100644 --- a/lib/libunwind/include/libunwind.h +++ b/lib/libunwind/include/libunwind.h @@ -832,4 +832,75 @@ enum { UNW_SPARC_I7 = 31, }; +// RISC-V registers. These match the DWARF register numbers defined by section +// 4 of the RISC-V ELF psABI specification, which can be found at: +// +// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md +enum { + UNW_RISCV_X0 = 0, + UNW_RISCV_X1 = 1, + UNW_RISCV_X2 = 2, + UNW_RISCV_X3 = 3, + UNW_RISCV_X4 = 4, + UNW_RISCV_X5 = 5, + UNW_RISCV_X6 = 6, + UNW_RISCV_X7 = 7, + UNW_RISCV_X8 = 8, + UNW_RISCV_X9 = 9, + UNW_RISCV_X10 = 10, + UNW_RISCV_X11 = 11, + UNW_RISCV_X12 = 12, + UNW_RISCV_X13 = 13, + UNW_RISCV_X14 = 14, + UNW_RISCV_X15 = 15, + UNW_RISCV_X16 = 16, + UNW_RISCV_X17 = 17, + UNW_RISCV_X18 = 18, + UNW_RISCV_X19 = 19, + UNW_RISCV_X20 = 20, + UNW_RISCV_X21 = 21, + UNW_RISCV_X22 = 22, + UNW_RISCV_X23 = 23, + UNW_RISCV_X24 = 24, + UNW_RISCV_X25 = 25, + UNW_RISCV_X26 = 26, + UNW_RISCV_X27 = 27, + UNW_RISCV_X28 = 28, + UNW_RISCV_X29 = 29, + UNW_RISCV_X30 = 30, + UNW_RISCV_X31 = 31, + UNW_RISCV_F0 = 32, + UNW_RISCV_F1 = 33, + UNW_RISCV_F2 = 34, + UNW_RISCV_F3 = 35, + UNW_RISCV_F4 = 36, + UNW_RISCV_F5 = 37, + UNW_RISCV_F6 = 38, + UNW_RISCV_F7 = 39, + UNW_RISCV_F8 = 40, + UNW_RISCV_F9 = 41, + UNW_RISCV_F10 = 42, + UNW_RISCV_F11 = 43, + UNW_RISCV_F12 = 44, + UNW_RISCV_F13 = 45, + UNW_RISCV_F14 = 46, + UNW_RISCV_F15 = 47, + UNW_RISCV_F16 = 48, + UNW_RISCV_F17 = 49, + UNW_RISCV_F18 = 50, + UNW_RISCV_F19 = 51, + UNW_RISCV_F20 = 52, + UNW_RISCV_F21 = 53, + UNW_RISCV_F22 = 54, + UNW_RISCV_F23 = 55, + UNW_RISCV_F24 = 56, + UNW_RISCV_F25 = 57, + UNW_RISCV_F26 = 58, + UNW_RISCV_F27 = 59, + UNW_RISCV_F28 = 60, + UNW_RISCV_F29 = 61, + UNW_RISCV_F30 = 62, + UNW_RISCV_F31 = 63, +}; + #endif diff --git a/lib/libunwind/src/AddressSpace.hpp b/lib/libunwind/src/AddressSpace.hpp index fb07c807db..7433476f91 100644 --- a/lib/libunwind/src/AddressSpace.hpp +++ b/lib/libunwind/src/AddressSpace.hpp @@ -27,11 +27,18 @@ #if _LIBUNWIND_USE_DLADDR #include -#if defined(__unix__) && defined(__ELF__) && defined(_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA) +#if defined(__ELF__) && defined(_LIBUNWIND_LINK_DL_LIB) #pragma comment(lib, "dl") #endif #endif +#if defined(_LIBUNWIND_ARM_EHABI) +struct EHABIIndexEntry { + uint32_t functionOffset; + uint32_t data; +}; +#endif + #ifdef __APPLE__ #include namespace libunwind { @@ -426,8 +433,12 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, HANDLE process = GetCurrentProcess(); DWORD needed; - if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) + if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) { + DWORD err = GetLastError(); + _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, " + "returned error %d", (int)err); return false; + } for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) { PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i]; @@ -462,12 +473,13 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, (void)targetAddr; (void)info; return true; -#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) && \ - (__ANDROID_API__ < 21) +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) + // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After + // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster. int length = 0; info.arm_section = (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); - info.arm_section_length = (uintptr_t)length; + info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); if (info.arm_section && info.arm_section_length) return true; #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) @@ -497,32 +509,40 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, #if !defined(Elf_Phdr) typedef ElfW(Phdr) Elf_Phdr; #endif -#if !defined(Elf_Addr) && defined(__ANDROID__) +#if !defined(Elf_Addr) typedef ElfW(Addr) Elf_Addr; #endif + 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 + #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." #endif size_t object_length; -#if defined(__ANDROID__) - Elf_Addr image_base = - pinfo->dlpi_phnum - ? reinterpret_cast(pinfo->dlpi_phdr) - - reinterpret_cast(pinfo->dlpi_phdr) - ->p_offset - : 0; -#endif for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { - uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; -#if defined(__ANDROID__) - if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) - begin = begin + image_base; -#endif + uintptr_t begin = image_base + phdr->p_vaddr; uintptr_t end = begin + phdr->p_memsz; if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { cbdata->sects->dso_base = begin; @@ -531,11 +551,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, } } else if (phdr->p_type == PT_GNU_EH_FRAME) { EHHeaderParser::EHHeaderInfo hdrInfo; - uintptr_t eh_frame_hdr_start = pinfo->dlpi_addr + phdr->p_vaddr; -#if defined(__ANDROID__) - if (pinfo->dlpi_addr == 0 && phdr->p_vaddr < image_base) - eh_frame_hdr_start = eh_frame_hdr_start + image_base; -#endif + uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; cbdata->sects->dwarf_index_section = eh_frame_hdr_start; cbdata->sects->dwarf_index_section_length = phdr->p_memsz; found_hdr = EHHeaderParser::decodeEHHdr( @@ -556,12 +572,12 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; if (phdr->p_type == PT_LOAD) { - uintptr_t begin = pinfo->dlpi_addr + phdr->p_vaddr; + uintptr_t begin = image_base + phdr->p_vaddr; uintptr_t end = begin + phdr->p_memsz; if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) found_obj = true; } else if (phdr->p_type == PT_ARM_EXIDX) { - uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr; + uintptr_t exidx_start = image_base + phdr->p_vaddr; cbdata->sects->arm_section = exidx_start; cbdata->sects->arm_section_length = phdr->p_memsz; found_hdr = true; diff --git a/lib/libunwind/src/DwarfInstructions.hpp b/lib/libunwind/src/DwarfInstructions.hpp index 29a070fa3e..ee98f538d4 100644 --- a/lib/libunwind/src/DwarfInstructions.hpp +++ b/lib/libunwind/src/DwarfInstructions.hpp @@ -34,7 +34,7 @@ public: typedef typename A::sint_t sint_t; static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, - R ®isters); + R ®isters, bool &isSignalFrame); private: @@ -150,7 +150,8 @@ v128 DwarfInstructions::getSavedVectorRegister( template int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, - pint_t fdeStart, R ®isters) { + pint_t fdeStart, R ®isters, + bool &isSignalFrame) { FDE_Info fdeInfo; CIE_Info cieInfo; if (CFI_Parser::decodeFDE(addressSpace, fdeStart, &fdeInfo, @@ -196,6 +197,8 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // restoring SP means setting it to CFA. newRegisters.setSP(cfa); + isSignalFrame = cieInfo.isSignalFrame; + #if defined(_LIBUNWIND_TARGET_AARCH64) // If the target is aarch64 then the return address may have been signed // using the v8.3 pointer authentication extensions. The original @@ -430,7 +433,7 @@ DwarfInstructions::evaluateExpression(pint_t expression, A &addressSpace, // pick from reg = addressSpace.get8(p); p += 1; - value = sp[-reg]; + value = sp[-(int)reg]; *(++sp) = value; if (log) fprintf(stderr, "duplicate %d in stack\n", reg); diff --git a/lib/libunwind/src/RWMutex.hpp b/lib/libunwind/src/RWMutex.hpp index a37ac77144..fcd3f4967d 100644 --- a/lib/libunwind/src/RWMutex.hpp +++ b/lib/libunwind/src/RWMutex.hpp @@ -17,7 +17,7 @@ #include #elif !defined(_LIBUNWIND_HAS_NO_THREADS) #include -#if defined(__unix__) && defined(__ELF__) && defined(_LIBUNWIND_HAS_COMMENT_LIB_PRAGMA) +#if defined(__ELF__) && defined(_LIBUNWIND_LINK_PTHREAD_LIB) #pragma comment(lib, "pthread") #endif #endif diff --git a/lib/libunwind/src/Registers.hpp b/lib/libunwind/src/Registers.hpp index a36c6cf90d..416ed61df7 100644 --- a/lib/libunwind/src/Registers.hpp +++ b/lib/libunwind/src/Registers.hpp @@ -34,6 +34,7 @@ enum { REGISTERS_MIPS_O32, REGISTERS_MIPS_NEWABI, REGISTERS_SPARC, + REGISTERS_RISCV, }; #if defined(_LIBUNWIND_TARGET_I386) @@ -3517,6 +3518,270 @@ inline const char *Registers_sparc::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_SPARC +#if defined(_LIBUNWIND_TARGET_RISCV) +/// Registers_riscv holds the register state of a thread in a 64-bit RISC-V +/// process. +class _LIBUNWIND_HIDDEN Registers_riscv { +public: + Registers_riscv(); + Registers_riscv(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 int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; } + static int getArch() { return REGISTERS_RISCV; } + + uint64_t getSP() const { return _registers[2]; } + void setSP(uint64_t value) { _registers[2] = value; } + uint64_t getIP() const { return _registers[1]; } + void setIP(uint64_t value) { _registers[1] = value; } + +private: + + uint64_t _registers[32]; + double _floats[32]; +}; + +inline Registers_riscv::Registers_riscv(const void *registers) { + static_assert((check_fit::does_fit), + "riscv registers do not fit into unw_context_t"); + memcpy(&_registers, registers, sizeof(_registers)); + static_assert(sizeof(_registers) == 0x100, + "expected float registers to be at offset 256"); + memcpy(_floats, + static_cast(registers) + sizeof(_registers), + sizeof(_floats)); +} + +inline Registers_riscv::Registers_riscv() { + memset(&_registers, 0, sizeof(_registers)); + memset(&_floats, 0, sizeof(_floats)); +} + +inline bool Registers_riscv::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 > UNW_RISCV_F31) + return false; + return true; +} + +inline uint64_t Registers_riscv::getRegister(int regNum) const { + if (regNum == UNW_REG_IP) + return _registers[1]; + if (regNum == UNW_REG_SP) + return _registers[2]; + if (regNum == UNW_RISCV_X0) + return 0; + if ((regNum > 0) && (regNum < 32)) + return _registers[regNum]; + _LIBUNWIND_ABORT("unsupported riscv register"); +} + +inline void Registers_riscv::setRegister(int regNum, uint64_t value) { + if (regNum == UNW_REG_IP) + _registers[1] = value; + else if (regNum == UNW_REG_SP) + _registers[2] = value; + else if (regNum == UNW_RISCV_X0) + /* x0 is hardwired to zero */ + return; + else if ((regNum > 0) && (regNum < 32)) + _registers[regNum] = value; + else + _LIBUNWIND_ABORT("unsupported riscv register"); +} + +inline const char *Registers_riscv::getRegisterName(int regNum) { + switch (regNum) { + case UNW_REG_IP: + return "pc"; + case UNW_REG_SP: + return "sp"; + case UNW_RISCV_X0: + return "zero"; + case UNW_RISCV_X1: + return "ra"; + case UNW_RISCV_X2: + return "sp"; + case UNW_RISCV_X3: + return "gp"; + case UNW_RISCV_X4: + return "tp"; + case UNW_RISCV_X5: + return "t0"; + case UNW_RISCV_X6: + return "t1"; + case UNW_RISCV_X7: + return "t2"; + case UNW_RISCV_X8: + return "s0"; + case UNW_RISCV_X9: + return "s1"; + case UNW_RISCV_X10: + return "a0"; + case UNW_RISCV_X11: + return "a1"; + case UNW_RISCV_X12: + return "a2"; + case UNW_RISCV_X13: + return "a3"; + case UNW_RISCV_X14: + return "a4"; + case UNW_RISCV_X15: + return "a5"; + case UNW_RISCV_X16: + return "a6"; + case UNW_RISCV_X17: + return "a7"; + case UNW_RISCV_X18: + return "s2"; + case UNW_RISCV_X19: + return "s3"; + case UNW_RISCV_X20: + return "s4"; + case UNW_RISCV_X21: + return "s5"; + case UNW_RISCV_X22: + return "s6"; + case UNW_RISCV_X23: + return "s7"; + case UNW_RISCV_X24: + return "s8"; + case UNW_RISCV_X25: + return "s9"; + case UNW_RISCV_X26: + return "s10"; + case UNW_RISCV_X27: + return "s11"; + case UNW_RISCV_X28: + return "t3"; + case UNW_RISCV_X29: + return "t4"; + case UNW_RISCV_X30: + return "t5"; + case UNW_RISCV_X31: + return "t6"; + case UNW_RISCV_F0: + return "ft0"; + case UNW_RISCV_F1: + return "ft1"; + case UNW_RISCV_F2: + return "ft2"; + case UNW_RISCV_F3: + return "ft3"; + case UNW_RISCV_F4: + return "ft4"; + case UNW_RISCV_F5: + return "ft5"; + case UNW_RISCV_F6: + return "ft6"; + case UNW_RISCV_F7: + return "ft7"; + case UNW_RISCV_F8: + return "fs0"; + case UNW_RISCV_F9: + return "fs1"; + case UNW_RISCV_F10: + return "fa0"; + case UNW_RISCV_F11: + return "fa1"; + case UNW_RISCV_F12: + return "fa2"; + case UNW_RISCV_F13: + return "fa3"; + case UNW_RISCV_F14: + return "fa4"; + case UNW_RISCV_F15: + return "fa5"; + case UNW_RISCV_F16: + return "fa6"; + case UNW_RISCV_F17: + return "fa7"; + case UNW_RISCV_F18: + return "fs2"; + case UNW_RISCV_F19: + return "fs3"; + case UNW_RISCV_F20: + return "fs4"; + case UNW_RISCV_F21: + return "fs5"; + case UNW_RISCV_F22: + return "fs6"; + case UNW_RISCV_F23: + return "fs7"; + case UNW_RISCV_F24: + return "fs8"; + case UNW_RISCV_F25: + return "fs9"; + case UNW_RISCV_F26: + return "fs10"; + case UNW_RISCV_F27: + return "fs11"; + case UNW_RISCV_F28: + return "ft8"; + case UNW_RISCV_F29: + return "ft9"; + case UNW_RISCV_F30: + return "ft10"; + case UNW_RISCV_F31: + return "ft11"; + default: + return "unknown register"; + } +} + +inline bool Registers_riscv::validFloatRegister(int regNum) const { + if (regNum < UNW_RISCV_F0) + return false; + if (regNum > UNW_RISCV_F31) + return false; + return true; +} + +inline double Registers_riscv::getFloatRegister(int regNum) const { +#if defined(__riscv_flen) && __riscv_flen == 64 + assert(validFloatRegister(regNum)); + return _floats[regNum - UNW_RISCV_F0]; +#else + _LIBUNWIND_ABORT("libunwind not built with float support"); +#endif +} + +inline void Registers_riscv::setFloatRegister(int regNum, double value) { +#if defined(__riscv_flen) && __riscv_flen == 64 + assert(validFloatRegister(regNum)); + _floats[regNum - UNW_RISCV_F0] = value; +#else + _LIBUNWIND_ABORT("libunwind not built with float support"); +#endif +} + +inline bool Registers_riscv::validVectorRegister(int) const { + return false; +} + +inline v128 Registers_riscv::getVectorRegister(int) const { + _LIBUNWIND_ABORT("no riscv vector register support yet"); +} + +inline void Registers_riscv::setVectorRegister(int, v128) { + _LIBUNWIND_ABORT("no riscv vector register support yet"); +} +#endif // _LIBUNWIND_TARGET_RISCV } // namespace libunwind #endif // __REGISTERS_HPP__ diff --git a/lib/libunwind/src/Unwind-EHABI.cpp b/lib/libunwind/src/Unwind-EHABI.cpp index 4ff5e318b5..a23ba2cc7e 100644 --- a/lib/libunwind/src/Unwind-EHABI.cpp +++ b/lib/libunwind/src/Unwind-EHABI.cpp @@ -941,8 +941,13 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, // format 1", which is equivalent to FSTMD + a padding word. for (uint32_t i = first; i < end; ++i) { // SP is only 32-bit aligned so don't copy 64-bit at a time. - uint64_t value = *sp++; - value |= ((uint64_t)(*sp++)) << 32; + uint64_t w0 = *sp++; + uint64_t w1 = *sp++; +#ifdef __LITTLE_ENDIAN__ + uint64_t value = (w1 << 32) | w0; +#else + uint64_t value = (w0 << 32) | w1; +#endif if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != _UVRSR_OK) return _UVRSR_FAILED; diff --git a/lib/libunwind/src/UnwindCursor.hpp b/lib/libunwind/src/UnwindCursor.hpp index a96c9f3995..31be8366d2 100644 --- a/lib/libunwind/src/UnwindCursor.hpp +++ b/lib/libunwind/src/UnwindCursor.hpp @@ -929,7 +929,7 @@ private: return DwarfInstructions::stepWithDwarf(_addressSpace, (pint_t)this->getReg(UNW_REG_IP), (pint_t)_info.unwind_info, - _registers); + _registers, _isSignalFrame); } #endif @@ -995,6 +995,12 @@ private: int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } #endif +#if defined (_LIBUNWIND_TARGET_RISCV) + int stepWithCompactEncoding(Registers_riscv &) { + return UNW_EINVAL; + } +#endif + bool compactSaysUseDwarf(uint32_t *offset=NULL) const { R dummy; return compactSaysUseDwarf(dummy, offset); @@ -1061,6 +1067,12 @@ private: bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } #endif +#if defined (_LIBUNWIND_TARGET_RISCV) + bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const { + return true; + } +#endif + #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) @@ -1127,6 +1139,12 @@ private: compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } #endif +#if defined (_LIBUNWIND_TARGET_RISCV) + compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { + return 0; + } +#endif + #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) @@ -1222,11 +1240,6 @@ template bool UnwindCursor::isSignalFrame() { #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) #if defined(_LIBUNWIND_ARM_EHABI) -struct EHABIIndexEntry { - uint32_t functionOffset; - uint32_t data; -}; - template struct EHABISectionIterator { typedef EHABISectionIterator _Self; @@ -1991,7 +2004,10 @@ int UnwindCursor::step() { template void UnwindCursor::getInfo(unw_proc_info_t *info) { - *info = _info; + if (_unwindInfoMissing) + memset(info, 0, sizeof(*info)); + else + *info = _info; } template diff --git a/lib/libunwind/src/UnwindLevel1-gcc-ext.c b/lib/libunwind/src/UnwindLevel1-gcc-ext.c index 63e4083a45..008df81566 100644 --- a/lib/libunwind/src/UnwindLevel1-gcc-ext.c +++ b/lib/libunwind/src/UnwindLevel1-gcc-ext.c @@ -221,7 +221,14 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) { _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *ipBefore) { _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p)", (void *)context); - *ipBefore = 0; + int isSignalFrame = __unw_is_signal_frame((unw_cursor_t *)context); + // Negative means some kind of error (probably UNW_ENOINFO), but we have no + // good way to report that, and this maintains backward compatibility with the + // implementation that hard-coded zero in every case, even signal frames. + if (isSignalFrame <= 0) + *ipBefore = 0; + else + *ipBefore = 1; return _Unwind_GetIP(context); } diff --git a/lib/libunwind/src/UnwindRegistersRestore.S b/lib/libunwind/src/UnwindRegistersRestore.S index 8122bf3e1b..cbb2fd4470 100644 --- a/lib/libunwind/src/UnwindRegistersRestore.S +++ b/lib/libunwind/src/UnwindRegistersRestore.S @@ -1029,6 +1029,87 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) jmp %o7 nop +#elif defined(__riscv) && __riscv_xlen == 64 + +// +// void libunwind::Registers_riscv::jumpto() +// +// On entry: +// thread_state pointer is in a0 +// + .p2align 2 +DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) +#if defined(__riscv_flen) && __riscv_flen == 64 + fld f0, (8 * 32 + 8 * 0)(a0) + fld f1, (8 * 32 + 8 * 1)(a0) + fld f2, (8 * 32 + 8 * 2)(a0) + fld f3, (8 * 32 + 8 * 3)(a0) + fld f4, (8 * 32 + 8 * 4)(a0) + fld f5, (8 * 32 + 8 * 5)(a0) + fld f6, (8 * 32 + 8 * 6)(a0) + fld f7, (8 * 32 + 8 * 7)(a0) + fld f8, (8 * 32 + 8 * 8)(a0) + fld f9, (8 * 32 + 8 * 9)(a0) + fld f10, (8 * 32 + 8 * 10)(a0) + fld f11, (8 * 32 + 8 * 11)(a0) + fld f12, (8 * 32 + 8 * 12)(a0) + fld f13, (8 * 32 + 8 * 13)(a0) + fld f14, (8 * 32 + 8 * 14)(a0) + fld f15, (8 * 32 + 8 * 15)(a0) + fld f16, (8 * 32 + 8 * 16)(a0) + fld f17, (8 * 32 + 8 * 17)(a0) + fld f18, (8 * 32 + 8 * 18)(a0) + fld f19, (8 * 32 + 8 * 19)(a0) + fld f20, (8 * 32 + 8 * 20)(a0) + fld f21, (8 * 32 + 8 * 21)(a0) + fld f22, (8 * 32 + 8 * 22)(a0) + fld f23, (8 * 32 + 8 * 23)(a0) + fld f24, (8 * 32 + 8 * 24)(a0) + fld f25, (8 * 32 + 8 * 25)(a0) + fld f26, (8 * 32 + 8 * 26)(a0) + fld f27, (8 * 32 + 8 * 27)(a0) + fld f28, (8 * 32 + 8 * 28)(a0) + fld f29, (8 * 32 + 8 * 29)(a0) + fld f30, (8 * 32 + 8 * 30)(a0) + fld f31, (8 * 32 + 8 * 31)(a0) +#endif + + // x0 is zero + ld x1, (8 * 1)(a0) + ld x2, (8 * 2)(a0) + ld x3, (8 * 3)(a0) + ld x4, (8 * 4)(a0) + ld x5, (8 * 5)(a0) + ld x6, (8 * 6)(a0) + ld x7, (8 * 7)(a0) + ld x8, (8 * 8)(a0) + ld x9, (8 * 9)(a0) + // skip a0 for now + ld x11, (8 * 11)(a0) + ld x12, (8 * 12)(a0) + ld x13, (8 * 13)(a0) + ld x14, (8 * 14)(a0) + ld x15, (8 * 15)(a0) + ld x16, (8 * 16)(a0) + ld x17, (8 * 17)(a0) + ld x18, (8 * 18)(a0) + ld x19, (8 * 19)(a0) + ld x20, (8 * 20)(a0) + ld x21, (8 * 21)(a0) + ld x22, (8 * 22)(a0) + ld x23, (8 * 23)(a0) + ld x24, (8 * 24)(a0) + ld x25, (8 * 25)(a0) + ld x26, (8 * 26)(a0) + ld x27, (8 * 27)(a0) + ld x28, (8 * 28)(a0) + ld x29, (8 * 29)(a0) + ld x30, (8 * 30)(a0) + ld x31, (8 * 31)(a0) + ld x10, (8 * 10)(a0) // restore a0 + + ret // jump to ra + #endif #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ diff --git a/lib/libunwind/src/UnwindRegistersSave.S b/lib/libunwind/src/UnwindRegistersSave.S index 54505e53ba..da91abc233 100644 --- a/lib/libunwind/src/UnwindRegistersSave.S +++ b/lib/libunwind/src/UnwindRegistersSave.S @@ -974,6 +974,86 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) std %i6, [%o0 + 120] jmp %o7 clr %o0 // return UNW_ESUCCESS + +#elif defined(__riscv) && __riscv_xlen == 64 + +# +# extern int __unw_getcontext(unw_context_t* thread_state) +# +# On entry: +# thread_state pointer is in a0 +# +DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) + // x0 is zero + sd x1, (8 * 1)(a0) + sd x2, (8 * 2)(a0) + sd x3, (8 * 3)(a0) + sd x4, (8 * 4)(a0) + sd x5, (8 * 5)(a0) + sd x6, (8 * 6)(a0) + sd x7, (8 * 7)(a0) + sd x8, (8 * 8)(a0) + sd x9, (8 * 9)(a0) + sd x10, (8 * 10)(a0) + sd x11, (8 * 11)(a0) + sd x12, (8 * 12)(a0) + sd x13, (8 * 13)(a0) + sd x14, (8 * 14)(a0) + sd x15, (8 * 15)(a0) + sd x16, (8 * 16)(a0) + sd x17, (8 * 17)(a0) + sd x18, (8 * 18)(a0) + sd x19, (8 * 19)(a0) + sd x20, (8 * 20)(a0) + sd x21, (8 * 21)(a0) + sd x22, (8 * 22)(a0) + sd x23, (8 * 23)(a0) + sd x24, (8 * 24)(a0) + sd x25, (8 * 25)(a0) + sd x26, (8 * 26)(a0) + sd x27, (8 * 27)(a0) + sd x28, (8 * 28)(a0) + sd x29, (8 * 29)(a0) + sd x30, (8 * 30)(a0) + sd x31, (8 * 31)(a0) + +#if defined(__riscv_flen) && __riscv_flen == 64 + fsd f0, (8 * 32 + 8 * 0)(a0) + fsd f1, (8 * 32 + 8 * 1)(a0) + fsd f2, (8 * 32 + 8 * 2)(a0) + fsd f3, (8 * 32 + 8 * 3)(a0) + fsd f4, (8 * 32 + 8 * 4)(a0) + fsd f5, (8 * 32 + 8 * 5)(a0) + fsd f6, (8 * 32 + 8 * 6)(a0) + fsd f7, (8 * 32 + 8 * 7)(a0) + fsd f8, (8 * 32 + 8 * 8)(a0) + fsd f9, (8 * 32 + 8 * 9)(a0) + fsd f10, (8 * 32 + 8 * 10)(a0) + fsd f11, (8 * 32 + 8 * 11)(a0) + fsd f12, (8 * 32 + 8 * 12)(a0) + fsd f13, (8 * 32 + 8 * 13)(a0) + fsd f14, (8 * 32 + 8 * 14)(a0) + fsd f15, (8 * 32 + 8 * 15)(a0) + fsd f16, (8 * 32 + 8 * 16)(a0) + fsd f17, (8 * 32 + 8 * 17)(a0) + fsd f18, (8 * 32 + 8 * 18)(a0) + fsd f19, (8 * 32 + 8 * 19)(a0) + fsd f20, (8 * 32 + 8 * 20)(a0) + fsd f21, (8 * 32 + 8 * 21)(a0) + fsd f22, (8 * 32 + 8 * 22)(a0) + fsd f23, (8 * 32 + 8 * 23)(a0) + fsd f24, (8 * 32 + 8 * 24)(a0) + fsd f25, (8 * 32 + 8 * 25)(a0) + fsd f26, (8 * 32 + 8 * 26)(a0) + fsd f27, (8 * 32 + 8 * 27)(a0) + fsd f28, (8 * 32 + 8 * 28)(a0) + fsd f29, (8 * 32 + 8 * 29)(a0) + fsd f30, (8 * 32 + 8 * 30)(a0) + fsd f31, (8 * 32 + 8 * 31)(a0) +#endif + + li a0, 0 // return UNW_ESUCCESS + ret // jump to ra #endif WEAK_ALIAS(__unw_getcontext, unw_getcontext) diff --git a/lib/libunwind/src/config.h b/lib/libunwind/src/config.h index 09bb261647..dcd3cef945 100644 --- a/lib/libunwind/src/config.h +++ b/lib/libunwind/src/config.h @@ -103,7 +103,8 @@ defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \ (!defined(__APPLE__) && defined(__arm__)) || \ (defined(__arm64__) || defined(__aarch64__)) || \ - defined(__mips__) + defined(__mips__) || \ + defined(__riscv) #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 c90032bd66..1ee58ad197 100644 --- a/lib/libunwind/src/libunwind.cpp +++ b/lib/libunwind/src/libunwind.cpp @@ -58,6 +58,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, # warning The MIPS architecture is not supported with this ABI and environment! #elif defined(__sparc__) # define REGISTER_KIND Registers_sparc +#elif defined(__riscv) && __riscv_xlen == 64 +# define REGISTER_KIND Registers_riscv #else # error Architecture not supported #endif @@ -171,8 +173,7 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor, co->getInfo(info); if (info->end_ip == 0) return UNW_ENOINFO; - else - return UNW_ESUCCESS; + return UNW_ESUCCESS; } _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_info, unw_get_proc_info) @@ -194,8 +195,7 @@ _LIBUNWIND_HIDDEN int __unw_get_proc_name(unw_cursor_t *cursor, char *buf, AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->getFunctionName(buf, bufLen, offset)) return UNW_ESUCCESS; - else - return UNW_EUNSPEC; + return UNW_EUNSPEC; } _LIBUNWIND_WEAK_ALIAS(__unw_get_proc_name, unw_get_proc_name)