Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR for llvm/llvm-project#53612 #11

Open
wants to merge 1 commit into
base: release/14.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions libunwind/include/__libunwind_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 31
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143
Expand Down Expand Up @@ -125,6 +126,12 @@
# 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_HIGHEST_DWARF_REGISTER \
_LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64
#define _LIBUNWIND_CONTEXT_SIZE 33
#define _LIBUNWIND_CURSOR_SIZE 45
# elif defined(__sparc__)
#define _LIBUNWIND_TARGET_SPARC 1
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC
Expand Down Expand Up @@ -165,6 +172,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_TARGET_VE 1
Expand Down
19 changes: 19 additions & 0 deletions libunwind/src/DwarfInstructions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ class DwarfInstructions {
}
};

template <typename R>
auto getSparcWCookie(const R &r, int) -> decltype(r.getWCookie()) {
return r.getWCookie();
}
template <typename R> uint64_t getSparcWCookie(const R &, long) {
return 0;
}

template <typename A, typename R>
typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
Expand All @@ -83,6 +90,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: // sparc64 specific
return addressSpace.getP(cfa + (pint_t)savedReg.value) ^
getSparcWCookie(registers, 0);

case CFI_Parser<A>::kRegisterAtExpression:
return (pint_t)addressSpace.getRegister(evaluateExpression(
(pint_t)savedReg.value, addressSpace, registers, cfa));
Expand Down Expand Up @@ -124,6 +135,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister(
case CFI_Parser<A>::kRegisterIsExpression:
case CFI_Parser<A>::kRegisterUnused:
case CFI_Parser<A>::kRegisterOffsetFromCFA:
case CFI_Parser<A>::kRegisterInCFADecrypt:
// FIX ME
break;
}
Expand All @@ -148,6 +160,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
case CFI_Parser<A>::kRegisterUndefined:
case CFI_Parser<A>::kRegisterOffsetFromCFA:
case CFI_Parser<A>::kRegisterInRegister:
case CFI_Parser<A>::kRegisterInCFADecrypt:
// FIX ME
break;
}
Expand Down Expand Up @@ -266,6 +279,12 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
}
#endif

#if defined(_LIBUNWIND_TARGET_SPARC64)
// Skip call site instruction and delay slot.
if (R::getArch() == REGISTERS_SPARC64)
returnAddress += 8;
#endif

#if defined(_LIBUNWIND_TARGET_PPC64)
#define PPC64_ELFV1_R2_LOAD_INST_ENCODING 0xe8410028u // ld r2,40(r1)
#define PPC64_ELFV1_R2_OFFSET 40
Expand Down
27 changes: 26 additions & 1 deletion libunwind/src/DwarfParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class CFI_Parser {
kRegisterUnused,
kRegisterUndefined,
kRegisterInCFA,
kRegisterInCFADecrypt, // sparc64 specific
kRegisterOffsetFromCFA,
kRegisterInRegister,
kRegisterAtExpression,
Expand Down Expand Up @@ -733,7 +734,8 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
"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,
Expand Down Expand Up @@ -767,8 +769,31 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
}
break;
#endif

#if defined(_LIBUNWIND_TARGET_SPARC64)
// case DW_CFA_GNU_window_save:
case REGISTERS_SPARC64:
// Don't save %o0-%o7 on sparc64.
// https://reviews.llvm.org/D32450#736405

for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) {
if (reg == UNW_SPARC_I7)
results->setRegister(
reg, kRegisterInCFADecrypt,
static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)),
initialState);
else
results->setRegister(
reg, kRegisterInCFA,
static_cast<int64_t>((reg - UNW_SPARC_L0) * sizeof(pint_t)),
initialState);
}
_LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save\n");
break;
#endif
}
break;

#else
(void)arch;
#endif
Expand Down
186 changes: 186 additions & 0 deletions libunwind/src/Registers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum {
REGISTERS_MIPS_O32,
REGISTERS_MIPS_NEWABI,
REGISTERS_SPARC,
REGISTERS_SPARC64,
REGISTERS_HEXAGON,
REGISTERS_RISCV,
REGISTERS_VE,
Expand Down Expand Up @@ -3586,6 +3587,191 @@ inline const char *Registers_sparc::getRegisterName(int regNum) {
}
#endif // _LIBUNWIND_TARGET_SPARC

#if defined(_LIBUNWIND_TARGET_SPARC64)
/// Registers_sparc64 holds the register state of a thread in a 64-bit
/// sparc process.
class _LIBUNWIND_HIDDEN Registers_sparc64 {
public:
Registers_sparc64() = default;
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 _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
}
static int getArch() { return REGISTERS_SPARC64; }

uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }
void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }
uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }
void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }
uint64_t getWCookie() const { return _wcookie; }

private:
struct sparc64_thread_state_t {
uint64_t __regs[32];
};

sparc64_thread_state_t _registers{};
uint64_t _wcookie = 0;
};

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, registers, sizeof(_registers));
memcpy(&_wcookie,
static_cast<const uint8_t *>(registers) + sizeof(_registers),
sizeof(_wcookie));
}

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 <= UNW_SPARC_I7)
return true;
return false;
}

inline uint64_t Registers_sparc64::getRegister(int regNum) const {
if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)
return _registers.__regs[regNum];

switch (regNum) {
case UNW_REG_IP:
return _registers.__regs[UNW_SPARC_O7];
case UNW_REG_SP:
return _registers.__regs[UNW_SPARC_O6] + 2047;
}
_LIBUNWIND_ABORT("unsupported sparc64 register");
}

inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {
if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {
_registers.__regs[regNum] = value;
return;
}

switch (regNum) {
case UNW_REG_IP:
_registers.__regs[UNW_SPARC_O7] = value;
return;
case UNW_REG_SP:
_registers.__regs[UNW_SPARC_O6] = 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) {
switch (regNum) {
case UNW_REG_IP:
return "pc";
case UNW_SPARC_G0:
return "g0";
case UNW_SPARC_G1:
return "g1";
case UNW_SPARC_G2:
return "g2";
case UNW_SPARC_G3:
return "g3";
case UNW_SPARC_G4:
return "g4";
case UNW_SPARC_G5:
return "g5";
case UNW_SPARC_G6:
return "g6";
case UNW_SPARC_G7:
return "g7";
case UNW_SPARC_O0:
return "o0";
case UNW_SPARC_O1:
return "o1";
case UNW_SPARC_O2:
return "o2";
case UNW_SPARC_O3:
return "o3";
case UNW_SPARC_O4:
return "o4";
case UNW_SPARC_O5:
return "o5";
case UNW_REG_SP:
case UNW_SPARC_O6:
return "o6";
case UNW_SPARC_O7:
return "o7";
case UNW_SPARC_L0:
return "l0";
case UNW_SPARC_L1:
return "l1";
case UNW_SPARC_L2:
return "l2";
case UNW_SPARC_L3:
return "l3";
case UNW_SPARC_L4:
return "l4";
case UNW_SPARC_L5:
return "l5";
case UNW_SPARC_L6:
return "l6";
case UNW_SPARC_L7:
return "l7";
case UNW_SPARC_I0:
return "i0";
case UNW_SPARC_I1:
return "i1";
case UNW_SPARC_I2:
return "i2";
case UNW_SPARC_I3:
return "i3";
case UNW_SPARC_I4:
return "i4";
case UNW_SPARC_I5:
return "i5";
case UNW_SPARC_I6:
return "i6";
case UNW_SPARC_I7:
return "i7";
default:
return "unknown register";
}
}
#endif // _LIBUNWIND_TARGET_SPARC64

#if defined(_LIBUNWIND_TARGET_HEXAGON)
/// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6
/// process.
Expand Down
16 changes: 16 additions & 0 deletions libunwind/src/UnwindCursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,10 @@ class UnwindCursor : public AbstractUnwindCursor{
int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
#endif

#if defined(_LIBUNWIND_TARGET_SPARC64)
int stepWithCompactEncoding(Registers_sparc64 &) { return UNW_EINVAL; }
#endif

#if defined (_LIBUNWIND_TARGET_RISCV)
int stepWithCompactEncoding(Registers_riscv &) {
return UNW_EINVAL;
Expand Down Expand Up @@ -1104,6 +1108,12 @@ class UnwindCursor : public AbstractUnwindCursor{
bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
#endif

#if defined(_LIBUNWIND_TARGET_SPARC64)
bool compactSaysUseDwarf(Registers_sparc64 &, uint32_t *) const {
return true;
}
#endif

#if defined (_LIBUNWIND_TARGET_RISCV)
bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const {
return true;
Expand Down Expand Up @@ -1182,6 +1192,12 @@ class UnwindCursor : public AbstractUnwindCursor{
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;
Expand Down
Loading