| Index: third_party/libc++abi/src/Unwind/Registers.hpp
|
| ===================================================================
|
| --- third_party/libc++abi/src/Unwind/Registers.hpp (revision 0)
|
| +++ third_party/libc++abi/src/Unwind/Registers.hpp (revision 0)
|
| @@ -0,0 +1,1278 @@
|
| +//===----------------------------- Registers.hpp --------------------------===//
|
| +//
|
| +// The LLVM Compiler Infrastructure
|
| +//
|
| +// This file is dual licensed under the MIT and the University of Illinois Open
|
| +// Source Licenses. See LICENSE.TXT for details.
|
| +//
|
| +//
|
| +// Models register sets for supported processors.
|
| +//
|
| +//===----------------------------------------------------------------------===//
|
| +
|
| +#ifndef __REGISTERS_HPP__
|
| +#define __REGISTERS_HPP__
|
| +
|
| +#include <stdint.h>
|
| +#include <strings.h>
|
| +
|
| +#include "libunwind.h"
|
| +#include "config.h"
|
| +
|
| +namespace libunwind {
|
| +
|
| +// For emulating 128-bit registers
|
| +struct v128 { uint32_t vec[4]; };
|
| +
|
| +
|
| +/// Registers_x86 holds the register state of a thread in a 32-bit intel
|
| +/// process.
|
| +class _LIBUNWIND_HIDDEN Registers_x86 {
|
| +public:
|
| + Registers_x86();
|
| + Registers_x86(const void *registers);
|
| +
|
| + bool validRegister(int num) const;
|
| + uint32_t getRegister(int num) const;
|
| + void setRegister(int num, uint32_t value);
|
| + bool validFloatRegister(int) const { return false; }
|
| + double getFloatRegister(int num) const;
|
| + void setFloatRegister(int num, double value);
|
| + bool validVectorRegister(int) const { return false; }
|
| + v128 getVectorRegister(int num) const;
|
| + void setVectorRegister(int num, v128 value);
|
| + const char *getRegisterName(int num);
|
| + void jumpto();
|
| +
|
| + uint32_t getSP() const { return _registers.__esp; }
|
| + void setSP(uint32_t value) { _registers.__esp = value; }
|
| + uint32_t getIP() const { return _registers.__eip; }
|
| + void setIP(uint32_t value) { _registers.__eip = value; }
|
| + uint32_t getEBP() const { return _registers.__ebp; }
|
| + void setEBP(uint32_t value) { _registers.__ebp = value; }
|
| + uint32_t getEBX() const { return _registers.__ebx; }
|
| + void setEBX(uint32_t value) { _registers.__ebx = value; }
|
| + uint32_t getECX() const { return _registers.__ecx; }
|
| + void setECX(uint32_t value) { _registers.__ecx = value; }
|
| + uint32_t getEDX() const { return _registers.__edx; }
|
| + void setEDX(uint32_t value) { _registers.__edx = value; }
|
| + uint32_t getESI() const { return _registers.__esi; }
|
| + void setESI(uint32_t value) { _registers.__esi = value; }
|
| + uint32_t getEDI() const { return _registers.__edi; }
|
| + void setEDI(uint32_t value) { _registers.__edi = value; }
|
| +
|
| +private:
|
| + struct GPRs {
|
| + unsigned int __eax;
|
| + unsigned int __ebx;
|
| + unsigned int __ecx;
|
| + unsigned int __edx;
|
| + unsigned int __edi;
|
| + unsigned int __esi;
|
| + unsigned int __ebp;
|
| + unsigned int __esp;
|
| + unsigned int __ss;
|
| + unsigned int __eflags;
|
| + unsigned int __eip;
|
| + unsigned int __cs;
|
| + unsigned int __ds;
|
| + unsigned int __es;
|
| + unsigned int __fs;
|
| + unsigned int __gs;
|
| + };
|
| +
|
| + GPRs _registers;
|
| +};
|
| +
|
| +inline Registers_x86::Registers_x86(const void *registers) {
|
| + static_assert(sizeof(Registers_x86) < sizeof(unw_context_t),
|
| + "x86 registers do not fit into unw_context_t");
|
| + _registers = *((GPRs *)registers);
|
| +}
|
| +
|
| +inline Registers_x86::Registers_x86() {
|
| + bzero(&_registers, sizeof(_registers));
|
| +}
|
| +
|
| +inline bool Registers_x86::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 > 7)
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +inline uint32_t Registers_x86::getRegister(int regNum) const {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + return _registers.__eip;
|
| + case UNW_REG_SP:
|
| + return _registers.__esp;
|
| + case UNW_X86_EAX:
|
| + return _registers.__eax;
|
| + case UNW_X86_ECX:
|
| + return _registers.__ecx;
|
| + case UNW_X86_EDX:
|
| + return _registers.__edx;
|
| + case UNW_X86_EBX:
|
| + return _registers.__ebx;
|
| + case UNW_X86_EBP:
|
| + return _registers.__ebp;
|
| + case UNW_X86_ESP:
|
| + return _registers.__esp;
|
| + case UNW_X86_ESI:
|
| + return _registers.__esi;
|
| + case UNW_X86_EDI:
|
| + return _registers.__edi;
|
| + }
|
| + _LIBUNWIND_ABORT("unsupported x86 register");
|
| +}
|
| +
|
| +inline void Registers_x86::setRegister(int regNum, uint32_t value) {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + _registers.__eip = value;
|
| + return;
|
| + case UNW_REG_SP:
|
| + _registers.__esp = value;
|
| + return;
|
| + case UNW_X86_EAX:
|
| + _registers.__eax = value;
|
| + return;
|
| + case UNW_X86_ECX:
|
| + _registers.__ecx = value;
|
| + return;
|
| + case UNW_X86_EDX:
|
| + _registers.__edx = value;
|
| + return;
|
| + case UNW_X86_EBX:
|
| + _registers.__ebx = value;
|
| + return;
|
| + case UNW_X86_EBP:
|
| + _registers.__ebp = value;
|
| + return;
|
| + case UNW_X86_ESP:
|
| + _registers.__esp = value;
|
| + return;
|
| + case UNW_X86_ESI:
|
| + _registers.__esi = value;
|
| + return;
|
| + case UNW_X86_EDI:
|
| + _registers.__edi = value;
|
| + return;
|
| + }
|
| + _LIBUNWIND_ABORT("unsupported x86 register");
|
| +}
|
| +
|
| +inline const char *Registers_x86::getRegisterName(int regNum) {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + return "ip";
|
| + case UNW_REG_SP:
|
| + return "esp";
|
| + case UNW_X86_EAX:
|
| + return "eax";
|
| + case UNW_X86_ECX:
|
| + return "ecx";
|
| + case UNW_X86_EDX:
|
| + return "edx";
|
| + case UNW_X86_EBX:
|
| + return "ebx";
|
| + case UNW_X86_EBP:
|
| + return "ebp";
|
| + case UNW_X86_ESP:
|
| + return "esp";
|
| + case UNW_X86_ESI:
|
| + return "esi";
|
| + case UNW_X86_EDI:
|
| + return "edi";
|
| + default:
|
| + return "unknown register";
|
| + }
|
| +}
|
| +
|
| +inline double Registers_x86::getFloatRegister(int) const {
|
| + _LIBUNWIND_ABORT("no x86 float registers");
|
| +}
|
| +
|
| +inline void Registers_x86::setFloatRegister(int, double) {
|
| + _LIBUNWIND_ABORT("no x86 float registers");
|
| +}
|
| +
|
| +inline v128 Registers_x86::getVectorRegister(int) const {
|
| + _LIBUNWIND_ABORT("no x86 vector registers");
|
| +}
|
| +
|
| +inline void Registers_x86::setVectorRegister(int, v128) {
|
| + _LIBUNWIND_ABORT("no x86 vector registers");
|
| +}
|
| +
|
| +
|
| +/// Registers_x86_64 holds the register state of a thread in a 64-bit intel
|
| +/// process.
|
| +class _LIBUNWIND_HIDDEN Registers_x86_64 {
|
| +public:
|
| + Registers_x86_64();
|
| + Registers_x86_64(const void *registers);
|
| +
|
| + bool validRegister(int num) const;
|
| + uint64_t getRegister(int num) const;
|
| + void setRegister(int num, uint64_t value);
|
| + bool validFloatRegister(int) const { return false; }
|
| + double getFloatRegister(int num) const;
|
| + void setFloatRegister(int num, double value);
|
| + bool validVectorRegister(int) const { return false; }
|
| + v128 getVectorRegister(int num) const;
|
| + void setVectorRegister(int num, v128 value);
|
| + const char *getRegisterName(int num);
|
| + void jumpto();
|
| +
|
| + uint64_t getSP() const { return _registers.__rsp; }
|
| + void setSP(uint64_t value) { _registers.__rsp = value; }
|
| + uint64_t getIP() const { return _registers.__rip; }
|
| + void setIP(uint64_t value) { _registers.__rip = value; }
|
| + uint64_t getRBP() const { return _registers.__rbp; }
|
| + void setRBP(uint64_t value) { _registers.__rbp = value; }
|
| + uint64_t getRBX() const { return _registers.__rbx; }
|
| + void setRBX(uint64_t value) { _registers.__rbx = value; }
|
| + uint64_t getR12() const { return _registers.__r12; }
|
| + void setR12(uint64_t value) { _registers.__r12 = value; }
|
| + uint64_t getR13() const { return _registers.__r13; }
|
| + void setR13(uint64_t value) { _registers.__r13 = value; }
|
| + uint64_t getR14() const { return _registers.__r14; }
|
| + void setR14(uint64_t value) { _registers.__r14 = value; }
|
| + uint64_t getR15() const { return _registers.__r15; }
|
| + void setR15(uint64_t value) { _registers.__r15 = value; }
|
| +
|
| +private:
|
| + struct GPRs {
|
| + uint64_t __rax;
|
| + uint64_t __rbx;
|
| + uint64_t __rcx;
|
| + uint64_t __rdx;
|
| + uint64_t __rdi;
|
| + uint64_t __rsi;
|
| + uint64_t __rbp;
|
| + uint64_t __rsp;
|
| + 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 __rip;
|
| + uint64_t __rflags;
|
| + uint64_t __cs;
|
| + uint64_t __fs;
|
| + uint64_t __gs;
|
| + };
|
| + GPRs _registers;
|
| +};
|
| +
|
| +inline Registers_x86_64::Registers_x86_64(const void *registers) {
|
| + static_assert(sizeof(Registers_x86_64) < sizeof(unw_context_t),
|
| + "x86_64 registers do not fit into unw_context_t");
|
| + _registers = *((GPRs *)registers);
|
| +}
|
| +
|
| +inline Registers_x86_64::Registers_x86_64() {
|
| + bzero(&_registers, sizeof(_registers));
|
| +}
|
| +
|
| +inline bool Registers_x86_64::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 > 15)
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +inline uint64_t Registers_x86_64::getRegister(int regNum) const {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + return _registers.__rip;
|
| + case UNW_REG_SP:
|
| + return _registers.__rsp;
|
| + case UNW_X86_64_RAX:
|
| + return _registers.__rax;
|
| + case UNW_X86_64_RDX:
|
| + return _registers.__rdx;
|
| + case UNW_X86_64_RCX:
|
| + return _registers.__rcx;
|
| + case UNW_X86_64_RBX:
|
| + return _registers.__rbx;
|
| + case UNW_X86_64_RSI:
|
| + return _registers.__rsi;
|
| + case UNW_X86_64_RDI:
|
| + return _registers.__rdi;
|
| + case UNW_X86_64_RBP:
|
| + return _registers.__rbp;
|
| + case UNW_X86_64_RSP:
|
| + return _registers.__rsp;
|
| + case UNW_X86_64_R8:
|
| + return _registers.__r8;
|
| + case UNW_X86_64_R9:
|
| + return _registers.__r9;
|
| + case UNW_X86_64_R10:
|
| + return _registers.__r10;
|
| + case UNW_X86_64_R11:
|
| + return _registers.__r11;
|
| + case UNW_X86_64_R12:
|
| + return _registers.__r12;
|
| + case UNW_X86_64_R13:
|
| + return _registers.__r13;
|
| + case UNW_X86_64_R14:
|
| + return _registers.__r14;
|
| + case UNW_X86_64_R15:
|
| + return _registers.__r15;
|
| + }
|
| + _LIBUNWIND_ABORT("unsupported x86_64 register");
|
| +}
|
| +
|
| +inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + _registers.__rip = value;
|
| + return;
|
| + case UNW_REG_SP:
|
| + _registers.__rsp = value;
|
| + return;
|
| + case UNW_X86_64_RAX:
|
| + _registers.__rax = value;
|
| + return;
|
| + case UNW_X86_64_RDX:
|
| + _registers.__rdx = value;
|
| + return;
|
| + case UNW_X86_64_RCX:
|
| + _registers.__rcx = value;
|
| + return;
|
| + case UNW_X86_64_RBX:
|
| + _registers.__rbx = value;
|
| + return;
|
| + case UNW_X86_64_RSI:
|
| + _registers.__rsi = value;
|
| + return;
|
| + case UNW_X86_64_RDI:
|
| + _registers.__rdi = value;
|
| + return;
|
| + case UNW_X86_64_RBP:
|
| + _registers.__rbp = value;
|
| + return;
|
| + case UNW_X86_64_RSP:
|
| + _registers.__rsp = value;
|
| + return;
|
| + case UNW_X86_64_R8:
|
| + _registers.__r8 = value;
|
| + return;
|
| + case UNW_X86_64_R9:
|
| + _registers.__r9 = value;
|
| + return;
|
| + case UNW_X86_64_R10:
|
| + _registers.__r10 = value;
|
| + return;
|
| + case UNW_X86_64_R11:
|
| + _registers.__r11 = value;
|
| + return;
|
| + case UNW_X86_64_R12:
|
| + _registers.__r12 = value;
|
| + return;
|
| + case UNW_X86_64_R13:
|
| + _registers.__r13 = value;
|
| + return;
|
| + case UNW_X86_64_R14:
|
| + _registers.__r14 = value;
|
| + return;
|
| + case UNW_X86_64_R15:
|
| + _registers.__r15 = value;
|
| + return;
|
| + }
|
| + _LIBUNWIND_ABORT("unsupported x86_64 register");
|
| +}
|
| +
|
| +inline const char *Registers_x86_64::getRegisterName(int regNum) {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + return "rip";
|
| + case UNW_REG_SP:
|
| + return "rsp";
|
| + case UNW_X86_64_RAX:
|
| + return "rax";
|
| + case UNW_X86_64_RDX:
|
| + return "rdx";
|
| + case UNW_X86_64_RCX:
|
| + return "rcx";
|
| + case UNW_X86_64_RBX:
|
| + return "rbx";
|
| + case UNW_X86_64_RSI:
|
| + return "rsi";
|
| + case UNW_X86_64_RDI:
|
| + return "rdi";
|
| + case UNW_X86_64_RBP:
|
| + return "rbp";
|
| + case UNW_X86_64_RSP:
|
| + return "rsp";
|
| + case UNW_X86_64_R8:
|
| + return "r8";
|
| + case UNW_X86_64_R9:
|
| + return "r9";
|
| + case UNW_X86_64_R10:
|
| + return "r10";
|
| + case UNW_X86_64_R11:
|
| + return "r11";
|
| + case UNW_X86_64_R12:
|
| + return "r12";
|
| + case UNW_X86_64_R13:
|
| + return "r13";
|
| + case UNW_X86_64_R14:
|
| + return "r14";
|
| + case UNW_X86_64_R15:
|
| + return "r15";
|
| + default:
|
| + return "unknown register";
|
| + }
|
| +}
|
| +
|
| +inline double Registers_x86_64::getFloatRegister(int) const {
|
| + _LIBUNWIND_ABORT("no x86_64 float registers");
|
| +}
|
| +
|
| +inline void Registers_x86_64::setFloatRegister(int, double) {
|
| + _LIBUNWIND_ABORT("no x86_64 float registers");
|
| +}
|
| +
|
| +inline v128 Registers_x86_64::getVectorRegister(int) const {
|
| + _LIBUNWIND_ABORT("no x86_64 vector registers");
|
| +}
|
| +
|
| +inline void Registers_x86_64::setVectorRegister(int, v128) {
|
| + _LIBUNWIND_ABORT("no x86_64 vector registers");
|
| +}
|
| +
|
| +
|
| +/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC
|
| +/// process.
|
| +class _LIBUNWIND_HIDDEN Registers_ppc {
|
| +public:
|
| + Registers_ppc();
|
| + Registers_ppc(const void *registers);
|
| +
|
| + bool validRegister(int num) const;
|
| + uint32_t getRegister(int num) const;
|
| + void setRegister(int num, uint32_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();
|
| +
|
| + uint64_t getSP() const { return _registers.__r1; }
|
| + void setSP(uint32_t value) { _registers.__r1 = value; }
|
| + uint64_t getIP() const { return _registers.__srr0; }
|
| + void setIP(uint32_t value) { _registers.__srr0 = value; }
|
| +
|
| +private:
|
| + struct ppc_thread_state_t {
|
| + unsigned int __srr0; /* Instruction address register (PC) */
|
| + unsigned int __srr1; /* Machine state register (supervisor) */
|
| + unsigned int __r0;
|
| + unsigned int __r1;
|
| + unsigned int __r2;
|
| + unsigned int __r3;
|
| + unsigned int __r4;
|
| + unsigned int __r5;
|
| + unsigned int __r6;
|
| + unsigned int __r7;
|
| + unsigned int __r8;
|
| + unsigned int __r9;
|
| + unsigned int __r10;
|
| + unsigned int __r11;
|
| + unsigned int __r12;
|
| + unsigned int __r13;
|
| + unsigned int __r14;
|
| + unsigned int __r15;
|
| + unsigned int __r16;
|
| + unsigned int __r17;
|
| + unsigned int __r18;
|
| + unsigned int __r19;
|
| + unsigned int __r20;
|
| + unsigned int __r21;
|
| + unsigned int __r22;
|
| + unsigned int __r23;
|
| + unsigned int __r24;
|
| + unsigned int __r25;
|
| + unsigned int __r26;
|
| + unsigned int __r27;
|
| + unsigned int __r28;
|
| + unsigned int __r29;
|
| + unsigned int __r30;
|
| + unsigned int __r31;
|
| + unsigned int __cr; /* Condition register */
|
| + unsigned int __xer; /* User's integer exception register */
|
| + unsigned int __lr; /* Link register */
|
| + unsigned int __ctr; /* Count register */
|
| + unsigned int __mq; /* MQ register (601 only) */
|
| + unsigned int __vrsave; /* Vector Save Register */
|
| + };
|
| +
|
| + struct ppc_float_state_t {
|
| + double __fpregs[32];
|
| +
|
| + unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */
|
| + unsigned int __fpscr; /* floating point status register */
|
| + };
|
| +
|
| + ppc_thread_state_t _registers;
|
| + ppc_float_state_t _floatRegisters;
|
| + v128 _vectorRegisters[32]; // offset 424
|
| +};
|
| +
|
| +inline Registers_ppc::Registers_ppc(const void *registers) {
|
| + static_assert(sizeof(Registers_ppc) < sizeof(unw_context_t),
|
| + "ppc registers do not fit into unw_context_t");
|
| + _registers = *((ppc_thread_state_t *)registers);
|
| + _floatRegisters = *((ppc_float_state_t *)((char *)registers + 160));
|
| + memcpy(_vectorRegisters, ((char *)registers + 424), sizeof(_vectorRegisters));
|
| +}
|
| +
|
| +inline Registers_ppc::Registers_ppc() {
|
| + bzero(&_registers, sizeof(_registers));
|
| + bzero(&_floatRegisters, sizeof(_floatRegisters));
|
| + bzero(&_vectorRegisters, sizeof(_vectorRegisters));
|
| +}
|
| +
|
| +inline bool Registers_ppc::validRegister(int regNum) const {
|
| + if (regNum == UNW_REG_IP)
|
| + return true;
|
| + if (regNum == UNW_REG_SP)
|
| + return true;
|
| + if (regNum == UNW_PPC_VRSAVE)
|
| + return true;
|
| + if (regNum < 0)
|
| + return false;
|
| + if (regNum <= UNW_PPC_R31)
|
| + return true;
|
| + if (regNum == UNW_PPC_MQ)
|
| + return true;
|
| + if (regNum == UNW_PPC_LR)
|
| + return true;
|
| + if (regNum == UNW_PPC_CTR)
|
| + return true;
|
| + if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))
|
| + return true;
|
| + return false;
|
| +}
|
| +
|
| +inline uint32_t Registers_ppc::getRegister(int regNum) const {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + return _registers.__srr0;
|
| + case UNW_REG_SP:
|
| + return _registers.__r1;
|
| + case UNW_PPC_R0:
|
| + return _registers.__r0;
|
| + case UNW_PPC_R1:
|
| + return _registers.__r1;
|
| + case UNW_PPC_R2:
|
| + return _registers.__r2;
|
| + case UNW_PPC_R3:
|
| + return _registers.__r3;
|
| + case UNW_PPC_R4:
|
| + return _registers.__r4;
|
| + case UNW_PPC_R5:
|
| + return _registers.__r5;
|
| + case UNW_PPC_R6:
|
| + return _registers.__r6;
|
| + case UNW_PPC_R7:
|
| + return _registers.__r7;
|
| + case UNW_PPC_R8:
|
| + return _registers.__r8;
|
| + case UNW_PPC_R9:
|
| + return _registers.__r9;
|
| + case UNW_PPC_R10:
|
| + return _registers.__r10;
|
| + case UNW_PPC_R11:
|
| + return _registers.__r11;
|
| + case UNW_PPC_R12:
|
| + return _registers.__r12;
|
| + case UNW_PPC_R13:
|
| + return _registers.__r13;
|
| + case UNW_PPC_R14:
|
| + return _registers.__r14;
|
| + case UNW_PPC_R15:
|
| + return _registers.__r15;
|
| + case UNW_PPC_R16:
|
| + return _registers.__r16;
|
| + case UNW_PPC_R17:
|
| + return _registers.__r17;
|
| + case UNW_PPC_R18:
|
| + return _registers.__r18;
|
| + case UNW_PPC_R19:
|
| + return _registers.__r19;
|
| + case UNW_PPC_R20:
|
| + return _registers.__r20;
|
| + case UNW_PPC_R21:
|
| + return _registers.__r21;
|
| + case UNW_PPC_R22:
|
| + return _registers.__r22;
|
| + case UNW_PPC_R23:
|
| + return _registers.__r23;
|
| + case UNW_PPC_R24:
|
| + return _registers.__r24;
|
| + case UNW_PPC_R25:
|
| + return _registers.__r25;
|
| + case UNW_PPC_R26:
|
| + return _registers.__r26;
|
| + case UNW_PPC_R27:
|
| + return _registers.__r27;
|
| + case UNW_PPC_R28:
|
| + return _registers.__r28;
|
| + case UNW_PPC_R29:
|
| + return _registers.__r29;
|
| + case UNW_PPC_R30:
|
| + return _registers.__r30;
|
| + case UNW_PPC_R31:
|
| + return _registers.__r31;
|
| + case UNW_PPC_LR:
|
| + return _registers.__lr;
|
| + case UNW_PPC_CR0:
|
| + return (_registers.__cr & 0xF0000000);
|
| + case UNW_PPC_CR1:
|
| + return (_registers.__cr & 0x0F000000);
|
| + case UNW_PPC_CR2:
|
| + return (_registers.__cr & 0x00F00000);
|
| + case UNW_PPC_CR3:
|
| + return (_registers.__cr & 0x000F0000);
|
| + case UNW_PPC_CR4:
|
| + return (_registers.__cr & 0x0000F000);
|
| + case UNW_PPC_CR5:
|
| + return (_registers.__cr & 0x00000F00);
|
| + case UNW_PPC_CR6:
|
| + return (_registers.__cr & 0x000000F0);
|
| + case UNW_PPC_CR7:
|
| + return (_registers.__cr & 0x0000000F);
|
| + case UNW_PPC_VRSAVE:
|
| + return _registers.__vrsave;
|
| + }
|
| + _LIBUNWIND_ABORT("unsupported ppc register");
|
| +}
|
| +
|
| +inline void Registers_ppc::setRegister(int regNum, uint32_t value) {
|
| + //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + _registers.__srr0 = value;
|
| + return;
|
| + case UNW_REG_SP:
|
| + _registers.__r1 = value;
|
| + return;
|
| + case UNW_PPC_R0:
|
| + _registers.__r0 = value;
|
| + return;
|
| + case UNW_PPC_R1:
|
| + _registers.__r1 = value;
|
| + return;
|
| + case UNW_PPC_R2:
|
| + _registers.__r2 = value;
|
| + return;
|
| + case UNW_PPC_R3:
|
| + _registers.__r3 = value;
|
| + return;
|
| + case UNW_PPC_R4:
|
| + _registers.__r4 = value;
|
| + return;
|
| + case UNW_PPC_R5:
|
| + _registers.__r5 = value;
|
| + return;
|
| + case UNW_PPC_R6:
|
| + _registers.__r6 = value;
|
| + return;
|
| + case UNW_PPC_R7:
|
| + _registers.__r7 = value;
|
| + return;
|
| + case UNW_PPC_R8:
|
| + _registers.__r8 = value;
|
| + return;
|
| + case UNW_PPC_R9:
|
| + _registers.__r9 = value;
|
| + return;
|
| + case UNW_PPC_R10:
|
| + _registers.__r10 = value;
|
| + return;
|
| + case UNW_PPC_R11:
|
| + _registers.__r11 = value;
|
| + return;
|
| + case UNW_PPC_R12:
|
| + _registers.__r12 = value;
|
| + return;
|
| + case UNW_PPC_R13:
|
| + _registers.__r13 = value;
|
| + return;
|
| + case UNW_PPC_R14:
|
| + _registers.__r14 = value;
|
| + return;
|
| + case UNW_PPC_R15:
|
| + _registers.__r15 = value;
|
| + return;
|
| + case UNW_PPC_R16:
|
| + _registers.__r16 = value;
|
| + return;
|
| + case UNW_PPC_R17:
|
| + _registers.__r17 = value;
|
| + return;
|
| + case UNW_PPC_R18:
|
| + _registers.__r18 = value;
|
| + return;
|
| + case UNW_PPC_R19:
|
| + _registers.__r19 = value;
|
| + return;
|
| + case UNW_PPC_R20:
|
| + _registers.__r20 = value;
|
| + return;
|
| + case UNW_PPC_R21:
|
| + _registers.__r21 = value;
|
| + return;
|
| + case UNW_PPC_R22:
|
| + _registers.__r22 = value;
|
| + return;
|
| + case UNW_PPC_R23:
|
| + _registers.__r23 = value;
|
| + return;
|
| + case UNW_PPC_R24:
|
| + _registers.__r24 = value;
|
| + return;
|
| + case UNW_PPC_R25:
|
| + _registers.__r25 = value;
|
| + return;
|
| + case UNW_PPC_R26:
|
| + _registers.__r26 = value;
|
| + return;
|
| + case UNW_PPC_R27:
|
| + _registers.__r27 = value;
|
| + return;
|
| + case UNW_PPC_R28:
|
| + _registers.__r28 = value;
|
| + return;
|
| + case UNW_PPC_R29:
|
| + _registers.__r29 = value;
|
| + return;
|
| + case UNW_PPC_R30:
|
| + _registers.__r30 = value;
|
| + return;
|
| + case UNW_PPC_R31:
|
| + _registers.__r31 = value;
|
| + return;
|
| + case UNW_PPC_MQ:
|
| + _registers.__mq = value;
|
| + return;
|
| + case UNW_PPC_LR:
|
| + _registers.__lr = value;
|
| + return;
|
| + case UNW_PPC_CTR:
|
| + _registers.__ctr = value;
|
| + return;
|
| + case UNW_PPC_CR0:
|
| + _registers.__cr &= 0x0FFFFFFF;
|
| + _registers.__cr |= (value & 0xF0000000);
|
| + return;
|
| + case UNW_PPC_CR1:
|
| + _registers.__cr &= 0xF0FFFFFF;
|
| + _registers.__cr |= (value & 0x0F000000);
|
| + return;
|
| + case UNW_PPC_CR2:
|
| + _registers.__cr &= 0xFF0FFFFF;
|
| + _registers.__cr |= (value & 0x00F00000);
|
| + return;
|
| + case UNW_PPC_CR3:
|
| + _registers.__cr &= 0xFFF0FFFF;
|
| + _registers.__cr |= (value & 0x000F0000);
|
| + return;
|
| + case UNW_PPC_CR4:
|
| + _registers.__cr &= 0xFFFF0FFF;
|
| + _registers.__cr |= (value & 0x0000F000);
|
| + return;
|
| + case UNW_PPC_CR5:
|
| + _registers.__cr &= 0xFFFFF0FF;
|
| + _registers.__cr |= (value & 0x00000F00);
|
| + return;
|
| + case UNW_PPC_CR6:
|
| + _registers.__cr &= 0xFFFFFF0F;
|
| + _registers.__cr |= (value & 0x000000F0);
|
| + return;
|
| + case UNW_PPC_CR7:
|
| + _registers.__cr &= 0xFFFFFFF0;
|
| + _registers.__cr |= (value & 0x0000000F);
|
| + return;
|
| + case UNW_PPC_VRSAVE:
|
| + _registers.__vrsave = value;
|
| + return;
|
| + // not saved
|
| + return;
|
| + case UNW_PPC_XER:
|
| + _registers.__xer = value;
|
| + return;
|
| + case UNW_PPC_AP:
|
| + case UNW_PPC_VSCR:
|
| + case UNW_PPC_SPEFSCR:
|
| + // not saved
|
| + return;
|
| + }
|
| + _LIBUNWIND_ABORT("unsupported ppc register");
|
| +}
|
| +
|
| +inline bool Registers_ppc::validFloatRegister(int regNum) const {
|
| + if (regNum < UNW_PPC_F0)
|
| + return false;
|
| + if (regNum > UNW_PPC_F31)
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +inline double Registers_ppc::getFloatRegister(int regNum) const {
|
| + assert(validFloatRegister(regNum));
|
| + return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];
|
| +}
|
| +
|
| +inline void Registers_ppc::setFloatRegister(int regNum, double value) {
|
| + assert(validFloatRegister(regNum));
|
| + _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;
|
| +}
|
| +
|
| +inline bool Registers_ppc::validVectorRegister(int regNum) const {
|
| + if (regNum < UNW_PPC_V0)
|
| + return false;
|
| + if (regNum > UNW_PPC_V31)
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +inline v128 Registers_ppc::getVectorRegister(int regNum) const {
|
| + assert(validVectorRegister(regNum));
|
| + v128 result = _vectorRegisters[regNum - UNW_PPC_V0];
|
| + return result;
|
| +}
|
| +
|
| +inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {
|
| + assert(validVectorRegister(regNum));
|
| + _vectorRegisters[regNum - UNW_PPC_V0] = value;
|
| +}
|
| +
|
| +inline const char *Registers_ppc::getRegisterName(int regNum) {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + return "ip";
|
| + case UNW_REG_SP:
|
| + return "sp";
|
| + case UNW_PPC_R0:
|
| + return "r0";
|
| + case UNW_PPC_R1:
|
| + return "r1";
|
| + case UNW_PPC_R2:
|
| + return "r2";
|
| + case UNW_PPC_R3:
|
| + return "r3";
|
| + case UNW_PPC_R4:
|
| + return "r4";
|
| + case UNW_PPC_R5:
|
| + return "r5";
|
| + case UNW_PPC_R6:
|
| + return "r6";
|
| + case UNW_PPC_R7:
|
| + return "r7";
|
| + case UNW_PPC_R8:
|
| + return "r8";
|
| + case UNW_PPC_R9:
|
| + return "r9";
|
| + case UNW_PPC_R10:
|
| + return "r10";
|
| + case UNW_PPC_R11:
|
| + return "r11";
|
| + case UNW_PPC_R12:
|
| + return "r12";
|
| + case UNW_PPC_R13:
|
| + return "r13";
|
| + case UNW_PPC_R14:
|
| + return "r14";
|
| + case UNW_PPC_R15:
|
| + return "r15";
|
| + case UNW_PPC_R16:
|
| + return "r16";
|
| + case UNW_PPC_R17:
|
| + return "r17";
|
| + case UNW_PPC_R18:
|
| + return "r18";
|
| + case UNW_PPC_R19:
|
| + return "r19";
|
| + case UNW_PPC_R20:
|
| + return "r20";
|
| + case UNW_PPC_R21:
|
| + return "r21";
|
| + case UNW_PPC_R22:
|
| + return "r22";
|
| + case UNW_PPC_R23:
|
| + return "r23";
|
| + case UNW_PPC_R24:
|
| + return "r24";
|
| + case UNW_PPC_R25:
|
| + return "r25";
|
| + case UNW_PPC_R26:
|
| + return "r26";
|
| + case UNW_PPC_R27:
|
| + return "r27";
|
| + case UNW_PPC_R28:
|
| + return "r28";
|
| + case UNW_PPC_R29:
|
| + return "r29";
|
| + case UNW_PPC_R30:
|
| + return "r30";
|
| + case UNW_PPC_R31:
|
| + return "r31";
|
| + case UNW_PPC_F0:
|
| + return "fp0";
|
| + case UNW_PPC_F1:
|
| + return "fp1";
|
| + case UNW_PPC_F2:
|
| + return "fp2";
|
| + case UNW_PPC_F3:
|
| + return "fp3";
|
| + case UNW_PPC_F4:
|
| + return "fp4";
|
| + case UNW_PPC_F5:
|
| + return "fp5";
|
| + case UNW_PPC_F6:
|
| + return "fp6";
|
| + case UNW_PPC_F7:
|
| + return "fp7";
|
| + case UNW_PPC_F8:
|
| + return "fp8";
|
| + case UNW_PPC_F9:
|
| + return "fp9";
|
| + case UNW_PPC_F10:
|
| + return "fp10";
|
| + case UNW_PPC_F11:
|
| + return "fp11";
|
| + case UNW_PPC_F12:
|
| + return "fp12";
|
| + case UNW_PPC_F13:
|
| + return "fp13";
|
| + case UNW_PPC_F14:
|
| + return "fp14";
|
| + case UNW_PPC_F15:
|
| + return "fp15";
|
| + case UNW_PPC_F16:
|
| + return "fp16";
|
| + case UNW_PPC_F17:
|
| + return "fp17";
|
| + case UNW_PPC_F18:
|
| + return "fp18";
|
| + case UNW_PPC_F19:
|
| + return "fp19";
|
| + case UNW_PPC_F20:
|
| + return "fp20";
|
| + case UNW_PPC_F21:
|
| + return "fp21";
|
| + case UNW_PPC_F22:
|
| + return "fp22";
|
| + case UNW_PPC_F23:
|
| + return "fp23";
|
| + case UNW_PPC_F24:
|
| + return "fp24";
|
| + case UNW_PPC_F25:
|
| + return "fp25";
|
| + case UNW_PPC_F26:
|
| + return "fp26";
|
| + case UNW_PPC_F27:
|
| + return "fp27";
|
| + case UNW_PPC_F28:
|
| + return "fp28";
|
| + case UNW_PPC_F29:
|
| + return "fp29";
|
| + case UNW_PPC_F30:
|
| + return "fp30";
|
| + case UNW_PPC_F31:
|
| + return "fp31";
|
| + case UNW_PPC_LR:
|
| + return "lr";
|
| + default:
|
| + return "unknown register";
|
| + }
|
| +
|
| +}
|
| +
|
| +
|
| +/// Registers_arm64 holds the register state of a thread in a 64-bit arm
|
| +/// process.
|
| +class _LIBUNWIND_HIDDEN Registers_arm64 {
|
| +public:
|
| + Registers_arm64();
|
| + Registers_arm64(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();
|
| +
|
| + uint64_t getSP() const { return _registers.__sp; }
|
| + void setSP(uint64_t value) { _registers.__sp = value; }
|
| + uint64_t getIP() const { return _registers.__pc; }
|
| + void setIP(uint64_t value) { _registers.__pc = value; }
|
| + uint64_t getFP() const { return _registers.__fp; }
|
| + void setFP(uint64_t value) { _registers.__fp = value; }
|
| +
|
| +private:
|
| + struct GPRs {
|
| + uint64_t __x[29]; // x0-x28
|
| + uint64_t __fp; // Frame pointer x29
|
| + uint64_t __lr; // Link register x30
|
| + uint64_t __sp; // Stack pointer x31
|
| + uint64_t __pc; // Program counter
|
| + uint64_t padding; // 16-byte align
|
| + };
|
| +
|
| + GPRs _registers;
|
| + double _vectorHalfRegisters[32];
|
| + // Currently only the lower double in 128-bit vectore registers
|
| + // is perserved during unwinding. We could define new register
|
| + // numbers (> 96) which mean whole vector registers, then this
|
| + // struct would need to change to contain whole vector registers.
|
| +};
|
| +
|
| +inline Registers_arm64::Registers_arm64(const void *registers) {
|
| + static_assert(sizeof(Registers_arm64) < sizeof(unw_context_t),
|
| + "arm64 registers do not fit into unw_context_t");
|
| + memcpy(&_registers, registers, sizeof(_registers));
|
| + memcpy(_vectorHalfRegisters, (((char *)registers) + 0x110),
|
| + sizeof(_vectorHalfRegisters));
|
| +}
|
| +
|
| +inline Registers_arm64::Registers_arm64() {
|
| + bzero(&_registers, sizeof(_registers));
|
| + bzero(&_registers, sizeof(_vectorHalfRegisters));
|
| +}
|
| +
|
| +inline bool Registers_arm64::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 > 95)
|
| + return false;
|
| + if ((regNum > 31) && (regNum < 64))
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +inline uint64_t Registers_arm64::getRegister(int regNum) const {
|
| + if (regNum == UNW_REG_IP)
|
| + return _registers.__pc;
|
| + if (regNum == UNW_REG_SP)
|
| + return _registers.__sp;
|
| + if ((regNum >= 0) && (regNum < 32))
|
| + return _registers.__x[regNum];
|
| + _LIBUNWIND_ABORT("unsupported arm64 register");
|
| +}
|
| +
|
| +inline void Registers_arm64::setRegister(int regNum, uint64_t value) {
|
| + if (regNum == UNW_REG_IP)
|
| + _registers.__pc = value;
|
| + else if (regNum == UNW_REG_SP)
|
| + _registers.__sp = value;
|
| + else if ((regNum >= 0) && (regNum < 32))
|
| + _registers.__x[regNum] = value;
|
| + else
|
| + _LIBUNWIND_ABORT("unsupported arm64 register");
|
| +}
|
| +
|
| +inline const char *Registers_arm64::getRegisterName(int regNum) {
|
| + switch (regNum) {
|
| + case UNW_REG_IP:
|
| + return "pc";
|
| + case UNW_REG_SP:
|
| + return "sp";
|
| + case UNW_ARM64_X0:
|
| + return "x0";
|
| + case UNW_ARM64_X1:
|
| + return "x1";
|
| + case UNW_ARM64_X2:
|
| + return "x2";
|
| + case UNW_ARM64_X3:
|
| + return "x3";
|
| + case UNW_ARM64_X4:
|
| + return "x4";
|
| + case UNW_ARM64_X5:
|
| + return "x5";
|
| + case UNW_ARM64_X6:
|
| + return "x6";
|
| + case UNW_ARM64_X7:
|
| + return "x7";
|
| + case UNW_ARM64_X8:
|
| + return "x8";
|
| + case UNW_ARM64_X9:
|
| + return "x9";
|
| + case UNW_ARM64_X10:
|
| + return "x10";
|
| + case UNW_ARM64_X11:
|
| + return "x11";
|
| + case UNW_ARM64_X12:
|
| + return "x12";
|
| + case UNW_ARM64_X13:
|
| + return "x13";
|
| + case UNW_ARM64_X14:
|
| + return "x14";
|
| + case UNW_ARM64_X15:
|
| + return "x15";
|
| + case UNW_ARM64_X16:
|
| + return "x16";
|
| + case UNW_ARM64_X17:
|
| + return "x17";
|
| + case UNW_ARM64_X18:
|
| + return "x18";
|
| + case UNW_ARM64_X19:
|
| + return "x19";
|
| + case UNW_ARM64_X20:
|
| + return "x20";
|
| + case UNW_ARM64_X21:
|
| + return "x21";
|
| + case UNW_ARM64_X22:
|
| + return "x22";
|
| + case UNW_ARM64_X23:
|
| + return "x23";
|
| + case UNW_ARM64_X24:
|
| + return "x24";
|
| + case UNW_ARM64_X25:
|
| + return "x25";
|
| + case UNW_ARM64_X26:
|
| + return "x26";
|
| + case UNW_ARM64_X27:
|
| + return "x27";
|
| + case UNW_ARM64_X28:
|
| + return "x28";
|
| + case UNW_ARM64_X29:
|
| + return "fp";
|
| + case UNW_ARM64_X30:
|
| + return "lr";
|
| + case UNW_ARM64_X31:
|
| + return "sp";
|
| + case UNW_ARM64_D0:
|
| + return "d0";
|
| + case UNW_ARM64_D1:
|
| + return "d1";
|
| + case UNW_ARM64_D2:
|
| + return "d2";
|
| + case UNW_ARM64_D3:
|
| + return "d3";
|
| + case UNW_ARM64_D4:
|
| + return "d4";
|
| + case UNW_ARM64_D5:
|
| + return "d5";
|
| + case UNW_ARM64_D6:
|
| + return "d6";
|
| + case UNW_ARM64_D7:
|
| + return "d7";
|
| + case UNW_ARM64_D8:
|
| + return "d8";
|
| + case UNW_ARM64_D9:
|
| + return "d9";
|
| + case UNW_ARM64_D10:
|
| + return "d10";
|
| + case UNW_ARM64_D11:
|
| + return "d11";
|
| + case UNW_ARM64_D12:
|
| + return "d12";
|
| + case UNW_ARM64_D13:
|
| + return "d13";
|
| + case UNW_ARM64_D14:
|
| + return "d14";
|
| + case UNW_ARM64_D15:
|
| + return "d15";
|
| + case UNW_ARM64_D16:
|
| + return "d16";
|
| + case UNW_ARM64_D17:
|
| + return "d17";
|
| + case UNW_ARM64_D18:
|
| + return "d18";
|
| + case UNW_ARM64_D19:
|
| + return "d19";
|
| + case UNW_ARM64_D20:
|
| + return "d20";
|
| + case UNW_ARM64_D21:
|
| + return "d21";
|
| + case UNW_ARM64_D22:
|
| + return "d22";
|
| + case UNW_ARM64_D23:
|
| + return "d23";
|
| + case UNW_ARM64_D24:
|
| + return "d24";
|
| + case UNW_ARM64_D25:
|
| + return "d25";
|
| + case UNW_ARM64_D26:
|
| + return "d26";
|
| + case UNW_ARM64_D27:
|
| + return "d27";
|
| + case UNW_ARM64_D28:
|
| + return "d28";
|
| + case UNW_ARM64_D29:
|
| + return "d29";
|
| + case UNW_ARM64_D30:
|
| + return "d30";
|
| + case UNW_ARM64_D31:
|
| + return "d31";
|
| + default:
|
| + return "unknown register";
|
| + }
|
| +}
|
| +
|
| +inline bool Registers_arm64::validFloatRegister(int regNum) const {
|
| + if (regNum < UNW_ARM64_D0)
|
| + return false;
|
| + if (regNum > UNW_ARM64_D31)
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +inline double Registers_arm64::getFloatRegister(int regNum) const {
|
| + assert(validFloatRegister(regNum));
|
| + return _vectorHalfRegisters[regNum - UNW_ARM64_D0];
|
| +}
|
| +
|
| +inline void Registers_arm64::setFloatRegister(int regNum, double value) {
|
| + assert(validFloatRegister(regNum));
|
| + _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value;
|
| +}
|
| +
|
| +inline bool Registers_arm64::validVectorRegister(int) const {
|
| + return false;
|
| +}
|
| +
|
| +inline v128 Registers_arm64::getVectorRegister(int) const {
|
| + _LIBUNWIND_ABORT("no arm64 vector register support yet");
|
| +}
|
| +
|
| +inline void Registers_arm64::setVectorRegister(int, v128) {
|
| + _LIBUNWIND_ABORT("no arm64 vector register support yet");
|
| +}
|
| +
|
| +} // namespace libunwind
|
| +
|
| +#endif // __REGISTERS_HPP__
|
|
|