summaryrefslogtreecommitdiff
path: root/libunwind
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2018-01-02 20:10:54 +0000
committerMartin Storsjo <martin@martin.st>2018-01-02 20:10:54 +0000
commitfb30fd7d6600f759b09232ffd30b2c986b60e8fb (patch)
tree2c57cb6b7f600ac252315595519b6b6cb4a2da28 /libunwind
parent679f282608a94e151caeee2f60c1d38f1d175254 (diff)
[PPC64] Port to ppc64le - initial version
Initial working version of libunwind for PowerPC 64. Tested on little-endian ppc64 host only. Based on the existing PowerPC 32 code. It supports: - context save/restore (unw_getcontext, unw_init_local, unw_resume) - read/write from/to saved registers - backtrace (unw_step) Patch by Leandro Lupori! Differential Revision: https://reviews.llvm.org/D41386
Diffstat (limited to 'libunwind')
-rw-r--r--libunwind/include/__libunwind_config.h11
-rw-r--r--libunwind/include/libunwind.h114
-rw-r--r--libunwind/src/AddressSpace.hpp7
-rw-r--r--libunwind/src/Registers.hpp577
-rw-r--r--libunwind/src/UnwindCursor.hpp19
-rw-r--r--libunwind/src/UnwindRegistersRestore.S95
-rw-r--r--libunwind/src/UnwindRegistersSave.S103
-rw-r--r--libunwind/src/assembly.h4
-rw-r--r--libunwind/src/config.h4
-rw-r--r--libunwind/src/libunwind.cpp2
10 files changed, 931 insertions, 5 deletions
diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h
index 69a49961a6e..1c254d69c0c 100644
--- a/libunwind/include/__libunwind_config.h
+++ b/libunwind/include/__libunwind_config.h
@@ -18,6 +18,7 @@
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 8
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 32
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC 112
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64 110
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 95
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM 287
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 31
@@ -39,6 +40,11 @@
# define _LIBUNWIND_CURSOR_SIZE 33
# endif
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64
+# elif defined(__powerpc64__)
+# define _LIBUNWIND_TARGET_PPC64 1
+# define _LIBUNWIND_CONTEXT_SIZE 136
+# define _LIBUNWIND_CURSOR_SIZE 148
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64
# elif defined(__ppc__)
# define _LIBUNWIND_TARGET_PPC 1
# define _LIBUNWIND_CONTEXT_SIZE 117
@@ -84,13 +90,14 @@
# define _LIBUNWIND_TARGET_I386
# define _LIBUNWIND_TARGET_X86_64 1
# define _LIBUNWIND_TARGET_PPC 1
+# define _LIBUNWIND_TARGET_PPC64 1
# define _LIBUNWIND_TARGET_AARCH64 1
# define _LIBUNWIND_TARGET_ARM 1
# define _LIBUNWIND_TARGET_OR1K 1
# define _LIBUNWIND_TARGET_MIPS_O32 1
# define _LIBUNWIND_TARGET_MIPS_N64 1
-# define _LIBUNWIND_CONTEXT_SIZE 128
-# define _LIBUNWIND_CURSOR_SIZE 140
+# define _LIBUNWIND_CONTEXT_SIZE 136
+# define _LIBUNWIND_CURSOR_SIZE 148
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
#endif // _LIBUNWIND_IS_NATIVE_ONLY
diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h
index 9011d55460c..29cf62e4335 100644
--- a/libunwind/include/libunwind.h
+++ b/libunwind/include/libunwind.h
@@ -325,6 +325,120 @@ enum {
UNW_PPC_SPEFSCR = 112
};
+// 64-bit ppc register numbers
+enum {
+ UNW_PPC64_R0 = 0,
+ UNW_PPC64_R1 = 1,
+ UNW_PPC64_R2 = 2,
+ UNW_PPC64_R3 = 3,
+ UNW_PPC64_R4 = 4,
+ UNW_PPC64_R5 = 5,
+ UNW_PPC64_R6 = 6,
+ UNW_PPC64_R7 = 7,
+ UNW_PPC64_R8 = 8,
+ UNW_PPC64_R9 = 9,
+ UNW_PPC64_R10 = 10,
+ UNW_PPC64_R11 = 11,
+ UNW_PPC64_R12 = 12,
+ UNW_PPC64_R13 = 13,
+ UNW_PPC64_R14 = 14,
+ UNW_PPC64_R15 = 15,
+ UNW_PPC64_R16 = 16,
+ UNW_PPC64_R17 = 17,
+ UNW_PPC64_R18 = 18,
+ UNW_PPC64_R19 = 19,
+ UNW_PPC64_R20 = 20,
+ UNW_PPC64_R21 = 21,
+ UNW_PPC64_R22 = 22,
+ UNW_PPC64_R23 = 23,
+ UNW_PPC64_R24 = 24,
+ UNW_PPC64_R25 = 25,
+ UNW_PPC64_R26 = 26,
+ UNW_PPC64_R27 = 27,
+ UNW_PPC64_R28 = 28,
+ UNW_PPC64_R29 = 29,
+ UNW_PPC64_R30 = 30,
+ UNW_PPC64_R31 = 31,
+ UNW_PPC64_F0 = 32,
+ UNW_PPC64_F1 = 33,
+ UNW_PPC64_F2 = 34,
+ UNW_PPC64_F3 = 35,
+ UNW_PPC64_F4 = 36,
+ UNW_PPC64_F5 = 37,
+ UNW_PPC64_F6 = 38,
+ UNW_PPC64_F7 = 39,
+ UNW_PPC64_F8 = 40,
+ UNW_PPC64_F9 = 41,
+ UNW_PPC64_F10 = 42,
+ UNW_PPC64_F11 = 43,
+ UNW_PPC64_F12 = 44,
+ UNW_PPC64_F13 = 45,
+ UNW_PPC64_F14 = 46,
+ UNW_PPC64_F15 = 47,
+ UNW_PPC64_F16 = 48,
+ UNW_PPC64_F17 = 49,
+ UNW_PPC64_F18 = 50,
+ UNW_PPC64_F19 = 51,
+ UNW_PPC64_F20 = 52,
+ UNW_PPC64_F21 = 53,
+ UNW_PPC64_F22 = 54,
+ UNW_PPC64_F23 = 55,
+ UNW_PPC64_F24 = 56,
+ UNW_PPC64_F25 = 57,
+ UNW_PPC64_F26 = 58,
+ UNW_PPC64_F27 = 59,
+ UNW_PPC64_F28 = 60,
+ UNW_PPC64_F29 = 61,
+ UNW_PPC64_F30 = 62,
+ UNW_PPC64_F31 = 63,
+ UNW_PPC64_LR = 64,
+ UNW_PPC64_CTR = 65,
+ UNW_PPC64_CR0 = 66,
+ UNW_PPC64_CR1 = 67,
+ UNW_PPC64_CR2 = 68,
+ UNW_PPC64_CR3 = 69,
+ UNW_PPC64_CR4 = 70,
+ UNW_PPC64_CR5 = 71,
+ UNW_PPC64_CR6 = 72,
+ UNW_PPC64_CR7 = 73,
+ UNW_PPC64_XER = 74,
+ UNW_PPC64_V0 = 75,
+ UNW_PPC64_V1 = 76,
+ UNW_PPC64_V2 = 77,
+ UNW_PPC64_V3 = 78,
+ UNW_PPC64_V4 = 79,
+ UNW_PPC64_V5 = 80,
+ UNW_PPC64_V6 = 81,
+ UNW_PPC64_V7 = 82,
+ UNW_PPC64_V8 = 83,
+ UNW_PPC64_V9 = 84,
+ UNW_PPC64_V10 = 85,
+ UNW_PPC64_V11 = 86,
+ UNW_PPC64_V12 = 87,
+ UNW_PPC64_V13 = 88,
+ UNW_PPC64_V14 = 89,
+ UNW_PPC64_V15 = 90,
+ UNW_PPC64_V16 = 91,
+ UNW_PPC64_V17 = 92,
+ UNW_PPC64_V18 = 93,
+ UNW_PPC64_V19 = 94,
+ UNW_PPC64_V20 = 95,
+ UNW_PPC64_V21 = 96,
+ UNW_PPC64_V22 = 97,
+ UNW_PPC64_V23 = 98,
+ UNW_PPC64_V24 = 99,
+ UNW_PPC64_V25 = 100,
+ UNW_PPC64_V26 = 101,
+ UNW_PPC64_V27 = 102,
+ UNW_PPC64_V28 = 103,
+ UNW_PPC64_V29 = 104,
+ UNW_PPC64_V30 = 105,
+ UNW_PPC64_V31 = 106,
+ UNW_PPC64_VRSAVE = 107,
+ UNW_PPC64_VSCR = 108,
+ UNW_PPC64_FPSCR = 109
+};
+
// 64-bit ARM64 registers
enum {
UNW_ARM64_X0 = 0,
diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp
index 24914fa329a..384fc9a32da 100644
--- a/libunwind/src/AddressSpace.hpp
+++ b/libunwind/src/AddressSpace.hpp
@@ -697,6 +697,13 @@ struct unw_addr_space_ppc : public unw_addr_space {
RemoteAddressSpace<Pointer32<BigEndian>> oas;
};
+/// unw_addr_space_ppc is the concrete instance that a unw_addr_space_t points
+/// to when examining a 64-bit PowerPC process.
+struct unw_addr_space_ppc64 : public unw_addr_space {
+ unw_addr_space_ppc64(task_t task) : oas(task) {}
+ RemoteAddressSpace<Pointer64<LittleEndian>> oas;
+};
+
#endif // UNW_REMOTE
} // namespace libunwind
diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index d881e200782..ab596391f5b 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -1106,6 +1106,583 @@ 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
+/// process.
+class _LIBUNWIND_HIDDEN Registers_ppc64 {
+public:
+ Registers_ppc64();
+ Registers_ppc64(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_PPC64; }
+
+ uint64_t getSP() const { return _registers.__r1; }
+ void setSP(uint64_t value) { _registers.__r1 = value; }
+ uint64_t getIP() const { return _registers.__srr0; }
+ void setIP(uint64_t value) { _registers.__srr0 = value; }
+
+private:
+ struct ppc64_thread_state_t {
+ uint64_t __srr0; /* Instruction address register (PC) */
+ uint64_t __srr1; /* Machine state register (supervisor) */
+ uint64_t __r0;
+ uint64_t __r1;
+ uint64_t __r2;
+ uint64_t __r3;
+ uint64_t __r4;
+ uint64_t __r5;
+ uint64_t __r6;
+ uint64_t __r7;
+ uint64_t __r8;
+ uint64_t __r9;
+ uint64_t __r10;
+ uint64_t __r11;
+ uint64_t __r12;
+ uint64_t __r13;
+ uint64_t __r14;
+ uint64_t __r15;
+ uint64_t __r16;
+ uint64_t __r17;
+ uint64_t __r18;
+ uint64_t __r19;
+ uint64_t __r20;
+ uint64_t __r21;
+ uint64_t __r22;
+ uint64_t __r23;
+ uint64_t __r24;
+ uint64_t __r25;
+ uint64_t __r26;
+ uint64_t __r27;
+ uint64_t __r28;
+ 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 */
+ };
+
+ struct ppc64_float_state_t {
+ double __fpregs[32];
+ uint64_t __fpscr; /* floating point status register */
+ };
+
+ ppc64_thread_state_t _registers;
+ ppc64_float_state_t _floatRegisters;
+ v128 _vectorRegisters[32];
+};
+
+inline Registers_ppc64::Registers_ppc64(const void *registers) {
+ static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),
+ "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));
+}
+
+inline Registers_ppc64::Registers_ppc64() {
+ memset(&_registers, 0, sizeof(_registers));
+ memset(&_floatRegisters, 0, sizeof(_floatRegisters));
+ memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));
+}
+
+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_LR:
+ case UNW_PPC64_CTR:
+ return true;
+ }
+
+ if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)
+ return true;
+ if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)
+ return true;
+
+ return false;
+}
+
+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:
+ return _registers.__r1;
+ case UNW_PPC64_R2:
+ return _registers.__r2;
+ case UNW_PPC64_R3:
+ return _registers.__r3;
+ case UNW_PPC64_R4:
+ return _registers.__r4;
+ case UNW_PPC64_R5:
+ return _registers.__r5;
+ case UNW_PPC64_R6:
+ return _registers.__r6;
+ case UNW_PPC64_R7:
+ return _registers.__r7;
+ case UNW_PPC64_R8:
+ return _registers.__r8;
+ case UNW_PPC64_R9:
+ return _registers.__r9;
+ case UNW_PPC64_R10:
+ return _registers.__r10;
+ case UNW_PPC64_R11:
+ return _registers.__r11;
+ case UNW_PPC64_R12:
+ return _registers.__r12;
+ case UNW_PPC64_R13:
+ return _registers.__r13;
+ case UNW_PPC64_R14:
+ return _registers.__r14;
+ case UNW_PPC64_R15:
+ return _registers.__r15;
+ case UNW_PPC64_R16:
+ return _registers.__r16;
+ case UNW_PPC64_R17:
+ return _registers.__r17;
+ case UNW_PPC64_R18:
+ return _registers.__r18;
+ case UNW_PPC64_R19:
+ return _registers.__r19;
+ case UNW_PPC64_R20:
+ return _registers.__r20;
+ case UNW_PPC64_R21:
+ return _registers.__r21;
+ case UNW_PPC64_R22:
+ return _registers.__r22;
+ case UNW_PPC64_R23:
+ return _registers.__r23;
+ case UNW_PPC64_R24:
+ return _registers.__r24;
+ case UNW_PPC64_R25:
+ return _registers.__r25;
+ case UNW_PPC64_R26:
+ return _registers.__r26;
+ case UNW_PPC64_R27:
+ return _registers.__r27;
+ case UNW_PPC64_R28:
+ return _registers.__r28;
+ case UNW_PPC64_R29:
+ return _registers.__r29;
+ case UNW_PPC64_R30:
+ 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:
+ return (_registers.__cr & 0x0F000000);
+ case UNW_PPC64_CR2:
+ return (_registers.__cr & 0x00F00000);
+ case UNW_PPC64_CR3:
+ return (_registers.__cr & 0x000F0000);
+ case UNW_PPC64_CR4:
+ return (_registers.__cr & 0x0000F000);
+ case UNW_PPC64_CR5:
+ return (_registers.__cr & 0x00000F00);
+ case UNW_PPC64_CR6:
+ return (_registers.__cr & 0x000000F0);
+ case UNW_PPC64_CR7:
+ return (_registers.__cr & 0x0000000F);
+ case UNW_PPC64_VRSAVE:
+ return _registers.__vrsave;
+ case UNW_PPC64_FPSCR:
+ return _floatRegisters.__fpscr;
+ }
+ _LIBUNWIND_ABORT("unsupported ppc64 register");
+}
+
+inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {
+ switch (regNum) {
+ 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:
+ _registers.__r1 = value;
+ return;
+ case UNW_PPC64_R2:
+ _registers.__r2 = value;
+ return;
+ case UNW_PPC64_R3:
+ _registers.__r3 = value;
+ return;
+ case UNW_PPC64_R4:
+ _registers.__r4 = value;
+ return;
+ case UNW_PPC64_R5:
+ _registers.__r5 = value;
+ return;
+ case UNW_PPC64_R6:
+ _registers.__r6 = value;
+ return;
+ case UNW_PPC64_R7:
+ _registers.__r7 = value;
+ return;
+ case UNW_PPC64_R8:
+ _registers.__r8 = value;
+ return;
+ case UNW_PPC64_R9:
+ _registers.__r9 = value;
+ return;
+ case UNW_PPC64_R10:
+ _registers.__r10 = value;
+ return;
+ case UNW_PPC64_R11:
+ _registers.__r11 = value;
+ return;
+ case UNW_PPC64_R12:
+ _registers.__r12 = value;
+ return;
+ case UNW_PPC64_R13:
+ _registers.__r13 = value;
+ return;
+ case UNW_PPC64_R14:
+ _registers.__r14 = value;
+ return;
+ case UNW_PPC64_R15:
+ _registers.__r15 = value;
+ return;
+ case UNW_PPC64_R16:
+ _registers.__r16 = value;
+ return;
+ case UNW_PPC64_R17:
+ _registers.__r17 = value;
+ return;
+ case UNW_PPC64_R18:
+ _registers.__r18 = value;
+ return;
+ case UNW_PPC64_R19:
+ _registers.__r19 = value;
+ return;
+ case UNW_PPC64_R20:
+ _registers.__r20 = value;
+ return;
+ case UNW_PPC64_R21:
+ _registers.__r21 = value;
+ return;
+ case UNW_PPC64_R22:
+ _registers.__r22 = value;
+ return;
+ case UNW_PPC64_R23:
+ _registers.__r23 = value;
+ return;
+ case UNW_PPC64_R24:
+ _registers.__r24 = value;
+ return;
+ case UNW_PPC64_R25:
+ _registers.__r25 = value;
+ return;
+ case UNW_PPC64_R26:
+ _registers.__r26 = value;
+ return;
+ case UNW_PPC64_R27:
+ _registers.__r27 = value;
+ return;
+ case UNW_PPC64_R28:
+ _registers.__r28 = value;
+ return;
+ case UNW_PPC64_R29:
+ _registers.__r29 = value;
+ return;
+ case UNW_PPC64_R30:
+ _registers.__r30 = value;
+ return;
+ 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);
+ return;
+ case UNW_PPC64_CR1:
+ _registers.__cr &= 0xF0FFFFFF;
+ _registers.__cr |= (value & 0x0F000000);
+ return;
+ case UNW_PPC64_CR2:
+ _registers.__cr &= 0xFF0FFFFF;
+ _registers.__cr |= (value & 0x00F00000);
+ return;
+ case UNW_PPC64_CR3:
+ _registers.__cr &= 0xFFF0FFFF;
+ _registers.__cr |= (value & 0x000F0000);
+ return;
+ case UNW_PPC64_CR4:
+ _registers.__cr &= 0xFFFF0FFF;
+ _registers.__cr |= (value & 0x0000F000);
+ return;
+ case UNW_PPC64_CR5:
+ _registers.__cr &= 0xFFFFF0FF;
+ _registers.__cr |= (value & 0x00000F00);
+ return;
+ case UNW_PPC64_CR6:
+ _registers.__cr &= 0xFFFFFF0F;
+ _registers.__cr |= (value & 0x000000F0);
+ return;
+ case UNW_PPC64_CR7:
+ _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
+ 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;
+}
+
+inline double Registers_ppc64::getFloatRegister(int regNum) const {
+ assert(validFloatRegister(regNum));
+ return _floatRegisters.__fpregs[regNum - UNW_PPC64_F0];
+}
+
+inline void Registers_ppc64::setFloatRegister(int regNum, double value) {
+ assert(validFloatRegister(regNum));
+ _floatRegisters.__fpregs[regNum - UNW_PPC64_F0] = 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;
+}
+
+inline v128 Registers_ppc64::getVectorRegister(int regNum) const {
+ assert(validVectorRegister(regNum));
+ v128 result = _vectorRegisters[regNum - UNW_PPC64_V0];
+ return result;
+}
+
+inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {
+ assert(validVectorRegister(regNum));
+ _vectorRegisters[regNum - UNW_PPC64_V0] = value;
+}
+
+inline const char *Registers_ppc64::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_REG_IP:
+ return "ip";
+ case UNW_REG_SP:
+ return "sp";
+ case UNW_PPC64_R0:
+ return "r0";
+ case UNW_PPC64_R1:
+ return "r1";
+ case UNW_PPC64_R2:
+ return "r2";
+ case UNW_PPC64_R3:
+ return "r3";
+ case UNW_PPC64_R4:
+ return "r4";
+ case UNW_PPC64_R5:
+ return "r5";
+ case UNW_PPC64_R6:
+ return "r6";
+ case UNW_PPC64_R7:
+ return "r7";
+ case UNW_PPC64_R8:
+ return "r8";
+ case UNW_PPC64_R9:
+ return "r9";
+ case UNW_PPC64_R10:
+ return "r10";
+ case UNW_PPC64_R11:
+ return "r11";
+ case UNW_PPC64_R12:
+ return "r12";
+ case UNW_PPC64_R13:
+ return "r13";
+ case UNW_PPC64_R14:
+ return "r14";
+ case UNW_PPC64_R15:
+ return "r15";
+ case UNW_PPC64_R16:
+ return "r16";
+ case UNW_PPC64_R17:
+ return "r17";
+ case UNW_PPC64_R18:
+ return "r18";
+ case UNW_PPC64_R19:
+ return "r19";
+ case UNW_PPC64_R20:
+ return "r20";
+ case UNW_PPC64_R21:
+ return "r21";
+ case UNW_PPC64_R22:
+ return "r22";
+ case UNW_PPC64_R23:
+ return "r23";
+ case UNW_PPC64_R24:
+ return "r24";
+ case UNW_PPC64_R25:
+ return "r25";
+ case UNW_PPC64_R26:
+ return "r26";
+ case UNW_PPC64_R27:
+ return "r27";
+ case UNW_PPC64_R28:
+ return "r28";
+ case UNW_PPC64_R29:
+ return "r29";
+ case UNW_PPC64_R30:
+ return "r30";
+ case UNW_PPC64_R31:
+ return "r31";
+ case UNW_PPC64_F0:
+ return "fp0";
+ case UNW_PPC64_F1:
+ return "fp1";
+ case UNW_PPC64_F2:
+ return "fp2";
+ case UNW_PPC64_F3:
+ return "fp3";
+ case UNW_PPC64_F4:
+ return "fp4";
+ case UNW_PPC64_F5:
+ return "fp5";
+ case UNW_PPC64_F6:
+ return "fp6";
+ case UNW_PPC64_F7:
+ return "fp7";
+ case UNW_PPC64_F8:
+ return "fp8";
+ case UNW_PPC64_F9:
+ return "fp9";
+ case UNW_PPC64_F10:
+ return "fp10";
+ case UNW_PPC64_F11:
+ return "fp11";
+ case UNW_PPC64_F12:
+ return "fp12";
+ case UNW_PPC64_F13:
+ return "fp13";
+ case UNW_PPC64_F14:
+ return "fp14";
+ case UNW_PPC64_F15:
+ return "fp15";
+ case UNW_PPC64_F16:
+ return "fp16";
+ case UNW_PPC64_F17:
+ return "fp17";
+ case UNW_PPC64_F18:
+ return "fp18";
+ case UNW_PPC64_F19:
+ return "fp19";
+ case UNW_PPC64_F20:
+ return "fp20";
+ case UNW_PPC64_F21:
+ return "fp21";
+ case UNW_PPC64_F22:
+ return "fp22";
+ case UNW_PPC64_F23:
+ return "fp23";
+ case UNW_PPC64_F24:
+ return "fp24";
+ case UNW_PPC64_F25:
+ return "fp25";
+ case UNW_PPC64_F26:
+ return "fp26";
+ case UNW_PPC64_F27:
+ return "fp27";
+ case UNW_PPC64_F28:
+ return "fp28";
+ case UNW_PPC64_F29:
+ return "fp29";
+ case UNW_PPC64_F30:
+ 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";
+ }
+}
+#endif // _LIBUNWIND_TARGET_PPC64
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
/// Registers_arm64 holds the register state of a thread in a 64-bit arm
diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp
index f09bd2347af..6300b995a3a 100644
--- a/libunwind/src/UnwindCursor.hpp
+++ b/libunwind/src/UnwindCursor.hpp
@@ -501,6 +501,13 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_PPC64)
+ int stepWithCompactEncoding(Registers_ppc64 &) {
+ return UNW_EINVAL;
+ }
+#endif
+
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
int stepWithCompactEncoding(Registers_arm64 &) {
return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
@@ -553,6 +560,12 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_PPC64)
+ bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {
+ return true;
+ }
+#endif
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
@@ -601,6 +614,12 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_PPC64)
+ compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {
+ return 0;
+ }
+#endif
+
#if defined(_LIBUNWIND_TARGET_AARCH64)
compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
return UNWIND_ARM64_MODE_DWARF;
diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S
index bd797f62914..34c4b2de2a0 100644
--- a/libunwind/src/UnwindRegistersRestore.S
+++ b/libunwind/src/UnwindRegistersRestore.S
@@ -128,6 +128,101 @@ DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv)
ret # rip was saved here
+#elif defined(__powerpc64__)
+
+DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
+//
+// void libunwind::Registers_ppc64::jumpto()
+//
+// On entry:
+// thread_state pointer is in r3
+//
+
+ // restore integral registers
+ // skip r0 for now
+ // skip r1 for now
+ ld %r2, 32(%r3)
+ // 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
+ mtcr %r0
+ ld %r0, 296(%r3) // __ctr
+ mtctr %r0
+ ld %r0, 0(%r3) // __ssr0
+ mtctr %r0
+
+ ld %r0, 16(%r3)
+ ld %r5, 56(%r3)
+ ld %r4, 48(%r3)
+ ld %r1, 24(%r3)
+ ld %r3, 40(%r3)
+ bctr
+
#elif defined(__ppc__)
DEFINE_LIBUNWIND_PRIVATE_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S
index 4583f505b29..d6247394fe9 100644
--- a/libunwind/src/UnwindRegistersSave.S
+++ b/libunwind/src/UnwindRegistersSave.S
@@ -237,6 +237,109 @@ DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
teq $0, $0
+#elif defined(__powerpc64__)
+
+//
+// extern int unw_getcontext(unw_context_t* thread_state)
+//
+// On entry:
+// thread_state pointer is in r3
+//
+DEFINE_LIBUNWIND_FUNCTION(unw_getcontext)
+ std %r0, 16(%r3)
+ 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)
+
+ mfcr %r0
+ std %r0, 272(%r3)
+
+ mfxer %r0
+ std %r0, 280(%r3)
+
+ mflr %r0
+ std %r0, 288(%r3)
+
+ mfctr %r0
+ std %r0, 296(%r3)
+
+ mfvrsave %r0
+ std %r0, 304(%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
+
+
+ li %r3, 0 // return UNW_ESUCCESS
+ blr
+
+
#elif defined(__ppc__)
;
diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h
index 2b2269cc05f..ba099cbe809 100644
--- a/libunwind/src/assembly.h
+++ b/libunwind/src/assembly.h
@@ -16,7 +16,9 @@
#ifndef UNWIND_ASSEMBLY_H
#define UNWIND_ASSEMBLY_H
-#if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
+#if defined(__powerpc64__)
+#define SEPARATOR ;
+#elif defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
#define SEPARATOR @
#elif defined(__arm64__)
#define SEPARATOR %%
diff --git a/libunwind/src/config.h b/libunwind/src/config.h
index 01ea60472ad..9dcaa44e6ad 100644
--- a/libunwind/src/config.h
+++ b/libunwind/src/config.h
@@ -63,12 +63,12 @@
#define _LIBUNWIND_BUILD_SJLJ_APIS
#endif
-#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__)
#define _LIBUNWIND_SUPPORT_FRAME_APIS
#endif
#if defined(__i386__) || defined(__x86_64__) || \
- defined(__ppc__) || defined(__ppc64__) || \
+ defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \
(!defined(__APPLE__) && defined(__arm__)) || \
(defined(__arm64__) || defined(__aarch64__)) || \
defined(__mips__)
diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index 0b7fb4019e1..de57569658a 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -51,6 +51,8 @@ _LIBUNWIND_EXPORT int unw_init_local(unw_cursor_t *cursor,
# define REGISTER_KIND Registers_x86
#elif defined(__x86_64__)
# define REGISTER_KIND Registers_x86_64
+#elif defined(__powerpc64__)
+# define REGISTER_KIND Registers_ppc64
#elif defined(__ppc__)
# define REGISTER_KIND Registers_ppc
#elif defined(__aarch64__)