5508 lines · plain
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//8// Models register sets for supported processors.9//10//===----------------------------------------------------------------------===//11 12#ifndef __REGISTERS_HPP__13#define __REGISTERS_HPP__14 15#include <stdint.h>16#include <string.h>17 18#include "config.h"19#include "libunwind.h"20#include "libunwind_ext.h"21#include "shadow_stack_unwind.h"22 23#if __has_include(<sys/auxv.h>)24#include <sys/auxv.h>25#define HAVE_SYS_AUXV_H26#endif27 28namespace libunwind {29 30// For emulating 128-bit registers31struct v128 { uint32_t vec[4]; };32 33enum {34 REGISTERS_X86,35 REGISTERS_X86_64,36 REGISTERS_PPC,37 REGISTERS_PPC64,38 REGISTERS_ARM64,39 REGISTERS_ARM,40 REGISTERS_OR1K,41 REGISTERS_MIPS_O32,42 REGISTERS_MIPS_NEWABI,43 REGISTERS_SPARC,44 REGISTERS_SPARC64,45 REGISTERS_HEXAGON,46 REGISTERS_RISCV,47 REGISTERS_VE,48 REGISTERS_S390X,49 REGISTERS_LOONGARCH,50};51 52#if defined(_LIBUNWIND_TARGET_I386)53class _LIBUNWIND_HIDDEN Registers_x86;54extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);55 56#if defined(_LIBUNWIND_USE_CET)57extern "C" void *__libunwind_shstk_get_jump_target() {58 return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);59}60#endif61 62/// Registers_x86 holds the register state of a thread in a 32-bit intel63/// process.64class _LIBUNWIND_HIDDEN Registers_x86 {65public:66 Registers_x86();67 Registers_x86(const void *registers);68 69 typedef uint32_t reg_t;70 typedef uint32_t link_reg_t;71 72 bool validRegister(int num) const;73 uint32_t getRegister(int num) const;74 void setRegister(int num, uint32_t value);75 bool validFloatRegister(int) const { return false; }76 double getFloatRegister(int num) const;77 void setFloatRegister(int num, double value);78 bool validVectorRegister(int) const { return false; }79 v128 getVectorRegister(int num) const;80 void setVectorRegister(int num, v128 value);81 static const char *getRegisterName(int num);82 void jumpto() { __libunwind_Registers_x86_jumpto(this); }83 static constexpr int lastDwarfRegNum() {84 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86;85 }86 static int getArch() { return REGISTERS_X86; }87 88 uint32_t getSP() const { return _registers.__esp; }89 void setSP(uint32_t value) { _registers.__esp = value; }90 uint32_t getIP() const { return _registers.__eip; }91 void setIP(uint32_t value) { _registers.__eip = value; }92 uint32_t getEBP() const { return _registers.__ebp; }93 void setEBP(uint32_t value) { _registers.__ebp = value; }94 uint32_t getEBX() const { return _registers.__ebx; }95 void setEBX(uint32_t value) { _registers.__ebx = value; }96 uint32_t getECX() const { return _registers.__ecx; }97 void setECX(uint32_t value) { _registers.__ecx = value; }98 uint32_t getEDX() const { return _registers.__edx; }99 void setEDX(uint32_t value) { _registers.__edx = value; }100 uint32_t getESI() const { return _registers.__esi; }101 void setESI(uint32_t value) { _registers.__esi = value; }102 uint32_t getEDI() const { return _registers.__edi; }103 void setEDI(uint32_t value) { _registers.__edi = value; }104 105private:106 struct GPRs {107 unsigned int __eax;108 unsigned int __ebx;109 unsigned int __ecx;110 unsigned int __edx;111 unsigned int __edi;112 unsigned int __esi;113 unsigned int __ebp;114 unsigned int __esp;115 unsigned int __ss;116 unsigned int __eflags;117 unsigned int __eip;118 unsigned int __cs;119 unsigned int __ds;120 unsigned int __es;121 unsigned int __fs;122 unsigned int __gs;123 };124 125 GPRs _registers;126};127 128inline Registers_x86::Registers_x86(const void *registers) {129 static_assert((check_fit<Registers_x86, unw_context_t>::does_fit),130 "x86 registers do not fit into unw_context_t");131 memcpy(&_registers, registers, sizeof(_registers));132}133 134inline Registers_x86::Registers_x86() {135 memset(&_registers, 0, sizeof(_registers));136}137 138inline bool Registers_x86::validRegister(int regNum) const {139 if (regNum == UNW_REG_IP)140 return true;141 if (regNum == UNW_REG_SP)142 return true;143 if (regNum < 0)144 return false;145 if (regNum > 7)146 return false;147 return true;148}149 150inline uint32_t Registers_x86::getRegister(int regNum) const {151 switch (regNum) {152 case UNW_REG_IP:153 return _registers.__eip;154 case UNW_REG_SP:155 return _registers.__esp;156 case UNW_X86_EAX:157 return _registers.__eax;158 case UNW_X86_ECX:159 return _registers.__ecx;160 case UNW_X86_EDX:161 return _registers.__edx;162 case UNW_X86_EBX:163 return _registers.__ebx;164#if !defined(__APPLE__)165 case UNW_X86_ESP:166#else167 case UNW_X86_EBP:168#endif169 return _registers.__ebp;170#if !defined(__APPLE__)171 case UNW_X86_EBP:172#else173 case UNW_X86_ESP:174#endif175 return _registers.__esp;176 case UNW_X86_ESI:177 return _registers.__esi;178 case UNW_X86_EDI:179 return _registers.__edi;180 }181 _LIBUNWIND_ABORT("unsupported x86 register");182}183 184inline void Registers_x86::setRegister(int regNum, uint32_t value) {185 switch (regNum) {186 case UNW_REG_IP:187 _registers.__eip = value;188 return;189 case UNW_REG_SP:190 _registers.__esp = value;191 return;192 case UNW_X86_EAX:193 _registers.__eax = value;194 return;195 case UNW_X86_ECX:196 _registers.__ecx = value;197 return;198 case UNW_X86_EDX:199 _registers.__edx = value;200 return;201 case UNW_X86_EBX:202 _registers.__ebx = value;203 return;204#if !defined(__APPLE__)205 case UNW_X86_ESP:206#else207 case UNW_X86_EBP:208#endif209 _registers.__ebp = value;210 return;211#if !defined(__APPLE__)212 case UNW_X86_EBP:213#else214 case UNW_X86_ESP:215#endif216 _registers.__esp = value;217 return;218 case UNW_X86_ESI:219 _registers.__esi = value;220 return;221 case UNW_X86_EDI:222 _registers.__edi = value;223 return;224 }225 _LIBUNWIND_ABORT("unsupported x86 register");226}227 228inline const char *Registers_x86::getRegisterName(int regNum) {229 switch (regNum) {230 case UNW_REG_IP:231 return "ip";232 case UNW_REG_SP:233 return "esp";234 case UNW_X86_EAX:235 return "eax";236 case UNW_X86_ECX:237 return "ecx";238 case UNW_X86_EDX:239 return "edx";240 case UNW_X86_EBX:241 return "ebx";242 case UNW_X86_EBP:243 return "ebp";244 case UNW_X86_ESP:245 return "esp";246 case UNW_X86_ESI:247 return "esi";248 case UNW_X86_EDI:249 return "edi";250 default:251 return "unknown register";252 }253}254 255inline double Registers_x86::getFloatRegister(int) const {256 _LIBUNWIND_ABORT("no x86 float registers");257}258 259inline void Registers_x86::setFloatRegister(int, double) {260 _LIBUNWIND_ABORT("no x86 float registers");261}262 263inline v128 Registers_x86::getVectorRegister(int) const {264 _LIBUNWIND_ABORT("no x86 vector registers");265}266 267inline void Registers_x86::setVectorRegister(int, v128) {268 _LIBUNWIND_ABORT("no x86 vector registers");269}270#endif // _LIBUNWIND_TARGET_I386271 272 273#if defined(_LIBUNWIND_TARGET_X86_64)274/// Registers_x86_64 holds the register state of a thread in a 64-bit intel275/// process.276class _LIBUNWIND_HIDDEN Registers_x86_64;277extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);278 279#if defined(_LIBUNWIND_USE_CET)280extern "C" void *__libunwind_shstk_get_jump_target() {281 return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);282}283#endif284 285class _LIBUNWIND_HIDDEN Registers_x86_64 {286public:287 Registers_x86_64();288 Registers_x86_64(const void *registers);289 290 typedef uint64_t reg_t;291 typedef uint64_t link_reg_t;292 293 bool validRegister(int num) const;294 uint64_t getRegister(int num) const;295 void setRegister(int num, uint64_t value);296 bool validFloatRegister(int) const { return false; }297 double getFloatRegister(int num) const;298 void setFloatRegister(int num, double value);299 bool validVectorRegister(int) const;300 v128 getVectorRegister(int num) const;301 void setVectorRegister(int num, v128 value);302 static const char *getRegisterName(int num);303 void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }304 static constexpr int lastDwarfRegNum() {305 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64;306 }307 static int getArch() { return REGISTERS_X86_64; }308 309 uint64_t getSP() const { return _registers.__rsp; }310 void setSP(uint64_t value) { _registers.__rsp = value; }311 uint64_t getIP() const { return _registers.__rip; }312 void setIP(uint64_t value) { _registers.__rip = value; }313 uint64_t getRBP() const { return _registers.__rbp; }314 void setRBP(uint64_t value) { _registers.__rbp = value; }315 uint64_t getRBX() const { return _registers.__rbx; }316 void setRBX(uint64_t value) { _registers.__rbx = value; }317 uint64_t getR12() const { return _registers.__r12; }318 void setR12(uint64_t value) { _registers.__r12 = value; }319 uint64_t getR13() const { return _registers.__r13; }320 void setR13(uint64_t value) { _registers.__r13 = value; }321 uint64_t getR14() const { return _registers.__r14; }322 void setR14(uint64_t value) { _registers.__r14 = value; }323 uint64_t getR15() const { return _registers.__r15; }324 void setR15(uint64_t value) { _registers.__r15 = value; }325 326private:327 struct GPRs {328 uint64_t __rax;329 uint64_t __rbx;330 uint64_t __rcx;331 uint64_t __rdx;332 uint64_t __rdi;333 uint64_t __rsi;334 uint64_t __rbp;335 uint64_t __rsp;336 uint64_t __r8;337 uint64_t __r9;338 uint64_t __r10;339 uint64_t __r11;340 uint64_t __r12;341 uint64_t __r13;342 uint64_t __r14;343 uint64_t __r15;344 uint64_t __rip;345 uint64_t __rflags;346 uint64_t __cs;347 uint64_t __fs;348 uint64_t __gs;349#if defined(_WIN64)350 uint64_t __padding; // 16-byte align351#endif352 };353 GPRs _registers;354#if defined(_WIN64)355 v128 _xmm[16];356#endif357};358 359inline Registers_x86_64::Registers_x86_64(const void *registers) {360 static_assert((check_fit<Registers_x86_64, unw_context_t>::does_fit),361 "x86_64 registers do not fit into unw_context_t");362 memcpy(&_registers, registers, sizeof(_registers));363}364 365inline Registers_x86_64::Registers_x86_64() {366 memset(&_registers, 0, sizeof(_registers));367}368 369inline bool Registers_x86_64::validRegister(int regNum) const {370 if (regNum == UNW_REG_IP)371 return true;372 if (regNum == UNW_REG_SP)373 return true;374 if (regNum < 0)375 return false;376 if (regNum > 16)377 return false;378 return true;379}380 381inline uint64_t Registers_x86_64::getRegister(int regNum) const {382 switch (regNum) {383 case UNW_REG_IP:384 case UNW_X86_64_RIP:385 return _registers.__rip;386 case UNW_REG_SP:387 return _registers.__rsp;388 case UNW_X86_64_RAX:389 return _registers.__rax;390 case UNW_X86_64_RDX:391 return _registers.__rdx;392 case UNW_X86_64_RCX:393 return _registers.__rcx;394 case UNW_X86_64_RBX:395 return _registers.__rbx;396 case UNW_X86_64_RSI:397 return _registers.__rsi;398 case UNW_X86_64_RDI:399 return _registers.__rdi;400 case UNW_X86_64_RBP:401 return _registers.__rbp;402 case UNW_X86_64_RSP:403 return _registers.__rsp;404 case UNW_X86_64_R8:405 return _registers.__r8;406 case UNW_X86_64_R9:407 return _registers.__r9;408 case UNW_X86_64_R10:409 return _registers.__r10;410 case UNW_X86_64_R11:411 return _registers.__r11;412 case UNW_X86_64_R12:413 return _registers.__r12;414 case UNW_X86_64_R13:415 return _registers.__r13;416 case UNW_X86_64_R14:417 return _registers.__r14;418 case UNW_X86_64_R15:419 return _registers.__r15;420 }421 _LIBUNWIND_ABORT("unsupported x86_64 register");422}423 424inline void Registers_x86_64::setRegister(int regNum, uint64_t value) {425 switch (regNum) {426 case UNW_REG_IP:427 case UNW_X86_64_RIP:428 _registers.__rip = value;429 return;430 case UNW_REG_SP:431 _registers.__rsp = value;432 return;433 case UNW_X86_64_RAX:434 _registers.__rax = value;435 return;436 case UNW_X86_64_RDX:437 _registers.__rdx = value;438 return;439 case UNW_X86_64_RCX:440 _registers.__rcx = value;441 return;442 case UNW_X86_64_RBX:443 _registers.__rbx = value;444 return;445 case UNW_X86_64_RSI:446 _registers.__rsi = value;447 return;448 case UNW_X86_64_RDI:449 _registers.__rdi = value;450 return;451 case UNW_X86_64_RBP:452 _registers.__rbp = value;453 return;454 case UNW_X86_64_RSP:455 _registers.__rsp = value;456 return;457 case UNW_X86_64_R8:458 _registers.__r8 = value;459 return;460 case UNW_X86_64_R9:461 _registers.__r9 = value;462 return;463 case UNW_X86_64_R10:464 _registers.__r10 = value;465 return;466 case UNW_X86_64_R11:467 _registers.__r11 = value;468 return;469 case UNW_X86_64_R12:470 _registers.__r12 = value;471 return;472 case UNW_X86_64_R13:473 _registers.__r13 = value;474 return;475 case UNW_X86_64_R14:476 _registers.__r14 = value;477 return;478 case UNW_X86_64_R15:479 _registers.__r15 = value;480 return;481 }482 _LIBUNWIND_ABORT("unsupported x86_64 register");483}484 485inline const char *Registers_x86_64::getRegisterName(int regNum) {486 switch (regNum) {487 case UNW_REG_IP:488 case UNW_X86_64_RIP:489 return "rip";490 case UNW_REG_SP:491 return "rsp";492 case UNW_X86_64_RAX:493 return "rax";494 case UNW_X86_64_RDX:495 return "rdx";496 case UNW_X86_64_RCX:497 return "rcx";498 case UNW_X86_64_RBX:499 return "rbx";500 case UNW_X86_64_RSI:501 return "rsi";502 case UNW_X86_64_RDI:503 return "rdi";504 case UNW_X86_64_RBP:505 return "rbp";506 case UNW_X86_64_RSP:507 return "rsp";508 case UNW_X86_64_R8:509 return "r8";510 case UNW_X86_64_R9:511 return "r9";512 case UNW_X86_64_R10:513 return "r10";514 case UNW_X86_64_R11:515 return "r11";516 case UNW_X86_64_R12:517 return "r12";518 case UNW_X86_64_R13:519 return "r13";520 case UNW_X86_64_R14:521 return "r14";522 case UNW_X86_64_R15:523 return "r15";524 case UNW_X86_64_XMM0:525 return "xmm0";526 case UNW_X86_64_XMM1:527 return "xmm1";528 case UNW_X86_64_XMM2:529 return "xmm2";530 case UNW_X86_64_XMM3:531 return "xmm3";532 case UNW_X86_64_XMM4:533 return "xmm4";534 case UNW_X86_64_XMM5:535 return "xmm5";536 case UNW_X86_64_XMM6:537 return "xmm6";538 case UNW_X86_64_XMM7:539 return "xmm7";540 case UNW_X86_64_XMM8:541 return "xmm8";542 case UNW_X86_64_XMM9:543 return "xmm9";544 case UNW_X86_64_XMM10:545 return "xmm10";546 case UNW_X86_64_XMM11:547 return "xmm11";548 case UNW_X86_64_XMM12:549 return "xmm12";550 case UNW_X86_64_XMM13:551 return "xmm13";552 case UNW_X86_64_XMM14:553 return "xmm14";554 case UNW_X86_64_XMM15:555 return "xmm15";556 default:557 return "unknown register";558 }559}560 561inline double Registers_x86_64::getFloatRegister(int) const {562 _LIBUNWIND_ABORT("no x86_64 float registers");563}564 565inline void Registers_x86_64::setFloatRegister(int, double) {566 _LIBUNWIND_ABORT("no x86_64 float registers");567}568 569inline bool Registers_x86_64::validVectorRegister(int regNum) const {570#if defined(_WIN64)571 if (regNum < UNW_X86_64_XMM0)572 return false;573 if (regNum > UNW_X86_64_XMM15)574 return false;575 return true;576#else577 (void)regNum; // suppress unused parameter warning578 return false;579#endif580}581 582inline v128 Registers_x86_64::getVectorRegister(int regNum) const {583#if defined(_WIN64)584 assert(validVectorRegister(regNum));585 return _xmm[regNum - UNW_X86_64_XMM0];586#else587 (void)regNum; // suppress unused parameter warning588 _LIBUNWIND_ABORT("no x86_64 vector registers");589#endif590}591 592inline void Registers_x86_64::setVectorRegister(int regNum, v128 value) {593#if defined(_WIN64)594 assert(validVectorRegister(regNum));595 _xmm[regNum - UNW_X86_64_XMM0] = value;596#else597 (void)regNum; (void)value; // suppress unused parameter warnings598 _LIBUNWIND_ABORT("no x86_64 vector registers");599#endif600}601#endif // _LIBUNWIND_TARGET_X86_64602 603 604#if defined(_LIBUNWIND_TARGET_PPC)605/// Registers_ppc holds the register state of a thread in a 32-bit PowerPC606/// process.607class _LIBUNWIND_HIDDEN Registers_ppc {608public:609 Registers_ppc();610 Registers_ppc(const void *registers);611 612 typedef uint32_t reg_t;613 typedef uint32_t link_reg_t;614 615 bool validRegister(int num) const;616 uint32_t getRegister(int num) const;617 void setRegister(int num, uint32_t value);618 bool validFloatRegister(int num) const;619 double getFloatRegister(int num) const;620 void setFloatRegister(int num, double value);621 bool validVectorRegister(int num) const;622 v128 getVectorRegister(int num) const;623 void setVectorRegister(int num, v128 value);624 static const char *getRegisterName(int num);625 void jumpto();626 static constexpr int lastDwarfRegNum() {627 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC;628 }629 static int getArch() { return REGISTERS_PPC; }630 631 uint64_t getSP() const { return _registers.__r1; }632 void setSP(uint32_t value) { _registers.__r1 = value; }633 uint64_t getIP() const { return _registers.__srr0; }634 void setIP(uint32_t value) { _registers.__srr0 = value; }635 uint64_t getCR() const { return _registers.__cr; }636 void setCR(uint32_t value) { _registers.__cr = value; }637 uint64_t getLR() const { return _registers.__lr; }638 void setLR(uint32_t value) { _registers.__lr = value; }639 640private:641 struct ppc_thread_state_t {642 unsigned int __srr0; /* Instruction address register (PC) */643 unsigned int __srr1; /* Machine state register (supervisor) */644 unsigned int __r0;645 unsigned int __r1;646 unsigned int __r2;647 unsigned int __r3;648 unsigned int __r4;649 unsigned int __r5;650 unsigned int __r6;651 unsigned int __r7;652 unsigned int __r8;653 unsigned int __r9;654 unsigned int __r10;655 unsigned int __r11;656 unsigned int __r12;657 unsigned int __r13;658 unsigned int __r14;659 unsigned int __r15;660 unsigned int __r16;661 unsigned int __r17;662 unsigned int __r18;663 unsigned int __r19;664 unsigned int __r20;665 unsigned int __r21;666 unsigned int __r22;667 unsigned int __r23;668 unsigned int __r24;669 unsigned int __r25;670 unsigned int __r26;671 unsigned int __r27;672 unsigned int __r28;673 unsigned int __r29;674 unsigned int __r30;675 unsigned int __r31;676 unsigned int __cr; /* Condition register */677 unsigned int __xer; /* User's integer exception register */678 unsigned int __lr; /* Link register */679 unsigned int __ctr; /* Count register */680 unsigned int __mq; /* MQ register (601 only) */681 unsigned int __vrsave; /* Vector Save Register */682 };683 684 struct ppc_float_state_t {685 double __fpregs[32];686 687 unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */688 unsigned int __fpscr; /* floating point status register */689 };690 691 ppc_thread_state_t _registers;692 ppc_float_state_t _floatRegisters;693 v128 _vectorRegisters[32]; // offset 424694};695 696inline Registers_ppc::Registers_ppc(const void *registers) {697 static_assert((check_fit<Registers_ppc, unw_context_t>::does_fit),698 "ppc registers do not fit into unw_context_t");699 memcpy(&_registers, static_cast<const uint8_t *>(registers),700 sizeof(_registers));701 static_assert(sizeof(ppc_thread_state_t) == 160,702 "expected float register offset to be 160");703 memcpy(&_floatRegisters,704 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t),705 sizeof(_floatRegisters));706 static_assert(sizeof(ppc_thread_state_t) + sizeof(ppc_float_state_t) == 424,707 "expected vector register offset to be 424 bytes");708 memcpy(_vectorRegisters,709 static_cast<const uint8_t *>(registers) + sizeof(ppc_thread_state_t) +710 sizeof(ppc_float_state_t),711 sizeof(_vectorRegisters));712}713 714inline Registers_ppc::Registers_ppc() {715 memset(&_registers, 0, sizeof(_registers));716 memset(&_floatRegisters, 0, sizeof(_floatRegisters));717 memset(&_vectorRegisters, 0, sizeof(_vectorRegisters));718}719 720inline bool Registers_ppc::validRegister(int regNum) const {721 if (regNum == UNW_REG_IP)722 return true;723 if (regNum == UNW_REG_SP)724 return true;725 if (regNum == UNW_PPC_VRSAVE)726 return true;727 if (regNum < 0)728 return false;729 if (regNum <= UNW_PPC_R31)730 return true;731 if (regNum == UNW_PPC_MQ)732 return true;733 if (regNum == UNW_PPC_LR)734 return true;735 if (regNum == UNW_PPC_CTR)736 return true;737 if ((UNW_PPC_CR0 <= regNum) && (regNum <= UNW_PPC_CR7))738 return true;739 return false;740}741 742inline uint32_t Registers_ppc::getRegister(int regNum) const {743 switch (regNum) {744 case UNW_REG_IP:745 return _registers.__srr0;746 case UNW_REG_SP:747 return _registers.__r1;748 case UNW_PPC_R0:749 return _registers.__r0;750 case UNW_PPC_R1:751 return _registers.__r1;752 case UNW_PPC_R2:753 return _registers.__r2;754 case UNW_PPC_R3:755 return _registers.__r3;756 case UNW_PPC_R4:757 return _registers.__r4;758 case UNW_PPC_R5:759 return _registers.__r5;760 case UNW_PPC_R6:761 return _registers.__r6;762 case UNW_PPC_R7:763 return _registers.__r7;764 case UNW_PPC_R8:765 return _registers.__r8;766 case UNW_PPC_R9:767 return _registers.__r9;768 case UNW_PPC_R10:769 return _registers.__r10;770 case UNW_PPC_R11:771 return _registers.__r11;772 case UNW_PPC_R12:773 return _registers.__r12;774 case UNW_PPC_R13:775 return _registers.__r13;776 case UNW_PPC_R14:777 return _registers.__r14;778 case UNW_PPC_R15:779 return _registers.__r15;780 case UNW_PPC_R16:781 return _registers.__r16;782 case UNW_PPC_R17:783 return _registers.__r17;784 case UNW_PPC_R18:785 return _registers.__r18;786 case UNW_PPC_R19:787 return _registers.__r19;788 case UNW_PPC_R20:789 return _registers.__r20;790 case UNW_PPC_R21:791 return _registers.__r21;792 case UNW_PPC_R22:793 return _registers.__r22;794 case UNW_PPC_R23:795 return _registers.__r23;796 case UNW_PPC_R24:797 return _registers.__r24;798 case UNW_PPC_R25:799 return _registers.__r25;800 case UNW_PPC_R26:801 return _registers.__r26;802 case UNW_PPC_R27:803 return _registers.__r27;804 case UNW_PPC_R28:805 return _registers.__r28;806 case UNW_PPC_R29:807 return _registers.__r29;808 case UNW_PPC_R30:809 return _registers.__r30;810 case UNW_PPC_R31:811 return _registers.__r31;812 case UNW_PPC_LR:813 return _registers.__lr;814 case UNW_PPC_CR0:815 return (_registers.__cr & 0xF0000000);816 case UNW_PPC_CR1:817 return (_registers.__cr & 0x0F000000);818 case UNW_PPC_CR2:819 return (_registers.__cr & 0x00F00000);820 case UNW_PPC_CR3:821 return (_registers.__cr & 0x000F0000);822 case UNW_PPC_CR4:823 return (_registers.__cr & 0x0000F000);824 case UNW_PPC_CR5:825 return (_registers.__cr & 0x00000F00);826 case UNW_PPC_CR6:827 return (_registers.__cr & 0x000000F0);828 case UNW_PPC_CR7:829 return (_registers.__cr & 0x0000000F);830 case UNW_PPC_VRSAVE:831 return _registers.__vrsave;832 }833 _LIBUNWIND_ABORT("unsupported ppc register");834}835 836inline void Registers_ppc::setRegister(int regNum, uint32_t value) {837 //fprintf(stderr, "Registers_ppc::setRegister(%d, 0x%08X)\n", regNum, value);838 switch (regNum) {839 case UNW_REG_IP:840 _registers.__srr0 = value;841 return;842 case UNW_REG_SP:843 _registers.__r1 = value;844 return;845 case UNW_PPC_R0:846 _registers.__r0 = value;847 return;848 case UNW_PPC_R1:849 _registers.__r1 = value;850 return;851 case UNW_PPC_R2:852 _registers.__r2 = value;853 return;854 case UNW_PPC_R3:855 _registers.__r3 = value;856 return;857 case UNW_PPC_R4:858 _registers.__r4 = value;859 return;860 case UNW_PPC_R5:861 _registers.__r5 = value;862 return;863 case UNW_PPC_R6:864 _registers.__r6 = value;865 return;866 case UNW_PPC_R7:867 _registers.__r7 = value;868 return;869 case UNW_PPC_R8:870 _registers.__r8 = value;871 return;872 case UNW_PPC_R9:873 _registers.__r9 = value;874 return;875 case UNW_PPC_R10:876 _registers.__r10 = value;877 return;878 case UNW_PPC_R11:879 _registers.__r11 = value;880 return;881 case UNW_PPC_R12:882 _registers.__r12 = value;883 return;884 case UNW_PPC_R13:885 _registers.__r13 = value;886 return;887 case UNW_PPC_R14:888 _registers.__r14 = value;889 return;890 case UNW_PPC_R15:891 _registers.__r15 = value;892 return;893 case UNW_PPC_R16:894 _registers.__r16 = value;895 return;896 case UNW_PPC_R17:897 _registers.__r17 = value;898 return;899 case UNW_PPC_R18:900 _registers.__r18 = value;901 return;902 case UNW_PPC_R19:903 _registers.__r19 = value;904 return;905 case UNW_PPC_R20:906 _registers.__r20 = value;907 return;908 case UNW_PPC_R21:909 _registers.__r21 = value;910 return;911 case UNW_PPC_R22:912 _registers.__r22 = value;913 return;914 case UNW_PPC_R23:915 _registers.__r23 = value;916 return;917 case UNW_PPC_R24:918 _registers.__r24 = value;919 return;920 case UNW_PPC_R25:921 _registers.__r25 = value;922 return;923 case UNW_PPC_R26:924 _registers.__r26 = value;925 return;926 case UNW_PPC_R27:927 _registers.__r27 = value;928 return;929 case UNW_PPC_R28:930 _registers.__r28 = value;931 return;932 case UNW_PPC_R29:933 _registers.__r29 = value;934 return;935 case UNW_PPC_R30:936 _registers.__r30 = value;937 return;938 case UNW_PPC_R31:939 _registers.__r31 = value;940 return;941 case UNW_PPC_MQ:942 _registers.__mq = value;943 return;944 case UNW_PPC_LR:945 _registers.__lr = value;946 return;947 case UNW_PPC_CTR:948 _registers.__ctr = value;949 return;950 case UNW_PPC_CR0:951 _registers.__cr &= 0x0FFFFFFF;952 _registers.__cr |= (value & 0xF0000000);953 return;954 case UNW_PPC_CR1:955 _registers.__cr &= 0xF0FFFFFF;956 _registers.__cr |= (value & 0x0F000000);957 return;958 case UNW_PPC_CR2:959 _registers.__cr &= 0xFF0FFFFF;960 _registers.__cr |= (value & 0x00F00000);961 return;962 case UNW_PPC_CR3:963 _registers.__cr &= 0xFFF0FFFF;964 _registers.__cr |= (value & 0x000F0000);965 return;966 case UNW_PPC_CR4:967 _registers.__cr &= 0xFFFF0FFF;968 _registers.__cr |= (value & 0x0000F000);969 return;970 case UNW_PPC_CR5:971 _registers.__cr &= 0xFFFFF0FF;972 _registers.__cr |= (value & 0x00000F00);973 return;974 case UNW_PPC_CR6:975 _registers.__cr &= 0xFFFFFF0F;976 _registers.__cr |= (value & 0x000000F0);977 return;978 case UNW_PPC_CR7:979 _registers.__cr &= 0xFFFFFFF0;980 _registers.__cr |= (value & 0x0000000F);981 return;982 case UNW_PPC_VRSAVE:983 _registers.__vrsave = value;984 return;985 // not saved986 return;987 case UNW_PPC_XER:988 _registers.__xer = value;989 return;990 case UNW_PPC_AP:991 case UNW_PPC_VSCR:992 case UNW_PPC_SPEFSCR:993 // not saved994 return;995 }996 _LIBUNWIND_ABORT("unsupported ppc register");997}998 999inline bool Registers_ppc::validFloatRegister(int regNum) const {1000 if (regNum < UNW_PPC_F0)1001 return false;1002 if (regNum > UNW_PPC_F31)1003 return false;1004 return true;1005}1006 1007inline double Registers_ppc::getFloatRegister(int regNum) const {1008 assert(validFloatRegister(regNum));1009 return _floatRegisters.__fpregs[regNum - UNW_PPC_F0];1010}1011 1012inline void Registers_ppc::setFloatRegister(int regNum, double value) {1013 assert(validFloatRegister(regNum));1014 _floatRegisters.__fpregs[regNum - UNW_PPC_F0] = value;1015}1016 1017inline bool Registers_ppc::validVectorRegister(int regNum) const {1018 if (regNum < UNW_PPC_V0)1019 return false;1020 if (regNum > UNW_PPC_V31)1021 return false;1022 return true;1023}1024 1025inline v128 Registers_ppc::getVectorRegister(int regNum) const {1026 assert(validVectorRegister(regNum));1027 v128 result = _vectorRegisters[regNum - UNW_PPC_V0];1028 return result;1029}1030 1031inline void Registers_ppc::setVectorRegister(int regNum, v128 value) {1032 assert(validVectorRegister(regNum));1033 _vectorRegisters[regNum - UNW_PPC_V0] = value;1034}1035 1036inline const char *Registers_ppc::getRegisterName(int regNum) {1037 switch (regNum) {1038 case UNW_REG_IP:1039 return "ip";1040 case UNW_REG_SP:1041 return "sp";1042 case UNW_PPC_R0:1043 return "r0";1044 case UNW_PPC_R1:1045 return "r1";1046 case UNW_PPC_R2:1047 return "r2";1048 case UNW_PPC_R3:1049 return "r3";1050 case UNW_PPC_R4:1051 return "r4";1052 case UNW_PPC_R5:1053 return "r5";1054 case UNW_PPC_R6:1055 return "r6";1056 case UNW_PPC_R7:1057 return "r7";1058 case UNW_PPC_R8:1059 return "r8";1060 case UNW_PPC_R9:1061 return "r9";1062 case UNW_PPC_R10:1063 return "r10";1064 case UNW_PPC_R11:1065 return "r11";1066 case UNW_PPC_R12:1067 return "r12";1068 case UNW_PPC_R13:1069 return "r13";1070 case UNW_PPC_R14:1071 return "r14";1072 case UNW_PPC_R15:1073 return "r15";1074 case UNW_PPC_R16:1075 return "r16";1076 case UNW_PPC_R17:1077 return "r17";1078 case UNW_PPC_R18:1079 return "r18";1080 case UNW_PPC_R19:1081 return "r19";1082 case UNW_PPC_R20:1083 return "r20";1084 case UNW_PPC_R21:1085 return "r21";1086 case UNW_PPC_R22:1087 return "r22";1088 case UNW_PPC_R23:1089 return "r23";1090 case UNW_PPC_R24:1091 return "r24";1092 case UNW_PPC_R25:1093 return "r25";1094 case UNW_PPC_R26:1095 return "r26";1096 case UNW_PPC_R27:1097 return "r27";1098 case UNW_PPC_R28:1099 return "r28";1100 case UNW_PPC_R29:1101 return "r29";1102 case UNW_PPC_R30:1103 return "r30";1104 case UNW_PPC_R31:1105 return "r31";1106 case UNW_PPC_F0:1107 return "fp0";1108 case UNW_PPC_F1:1109 return "fp1";1110 case UNW_PPC_F2:1111 return "fp2";1112 case UNW_PPC_F3:1113 return "fp3";1114 case UNW_PPC_F4:1115 return "fp4";1116 case UNW_PPC_F5:1117 return "fp5";1118 case UNW_PPC_F6:1119 return "fp6";1120 case UNW_PPC_F7:1121 return "fp7";1122 case UNW_PPC_F8:1123 return "fp8";1124 case UNW_PPC_F9:1125 return "fp9";1126 case UNW_PPC_F10:1127 return "fp10";1128 case UNW_PPC_F11:1129 return "fp11";1130 case UNW_PPC_F12:1131 return "fp12";1132 case UNW_PPC_F13:1133 return "fp13";1134 case UNW_PPC_F14:1135 return "fp14";1136 case UNW_PPC_F15:1137 return "fp15";1138 case UNW_PPC_F16:1139 return "fp16";1140 case UNW_PPC_F17:1141 return "fp17";1142 case UNW_PPC_F18:1143 return "fp18";1144 case UNW_PPC_F19:1145 return "fp19";1146 case UNW_PPC_F20:1147 return "fp20";1148 case UNW_PPC_F21:1149 return "fp21";1150 case UNW_PPC_F22:1151 return "fp22";1152 case UNW_PPC_F23:1153 return "fp23";1154 case UNW_PPC_F24:1155 return "fp24";1156 case UNW_PPC_F25:1157 return "fp25";1158 case UNW_PPC_F26:1159 return "fp26";1160 case UNW_PPC_F27:1161 return "fp27";1162 case UNW_PPC_F28:1163 return "fp28";1164 case UNW_PPC_F29:1165 return "fp29";1166 case UNW_PPC_F30:1167 return "fp30";1168 case UNW_PPC_F31:1169 return "fp31";1170 case UNW_PPC_LR:1171 return "lr";1172 default:1173 return "unknown register";1174 }1175 1176}1177#endif // _LIBUNWIND_TARGET_PPC1178 1179#if defined(_LIBUNWIND_TARGET_PPC64)1180/// Registers_ppc64 holds the register state of a thread in a 64-bit PowerPC1181/// process.1182class _LIBUNWIND_HIDDEN Registers_ppc64 {1183public:1184 Registers_ppc64();1185 Registers_ppc64(const void *registers);1186 1187 typedef uint64_t reg_t;1188 typedef uint64_t link_reg_t;1189 1190 bool validRegister(int num) const;1191 uint64_t getRegister(int num) const;1192 void setRegister(int num, uint64_t value);1193 bool validFloatRegister(int num) const;1194 double getFloatRegister(int num) const;1195 void setFloatRegister(int num, double value);1196 bool validVectorRegister(int num) const;1197 v128 getVectorRegister(int num) const;1198 void setVectorRegister(int num, v128 value);1199 static const char *getRegisterName(int num);1200 void jumpto();1201 static constexpr int lastDwarfRegNum() {1202 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64;1203 }1204 static int getArch() { return REGISTERS_PPC64; }1205 1206 uint64_t getSP() const { return _registers.__r1; }1207 void setSP(uint64_t value) { _registers.__r1 = value; }1208 uint64_t getIP() const { return _registers.__srr0; }1209 void setIP(uint64_t value) { _registers.__srr0 = value; }1210 uint64_t getCR() const { return _registers.__cr; }1211 void setCR(uint64_t value) { _registers.__cr = value; }1212 uint64_t getLR() const { return _registers.__lr; }1213 void setLR(uint64_t value) { _registers.__lr = value; }1214 1215private:1216 struct ppc64_thread_state_t {1217 uint64_t __srr0; // Instruction address register (PC)1218 uint64_t __srr1; // Machine state register (supervisor)1219 uint64_t __r0;1220 uint64_t __r1;1221 uint64_t __r2;1222 uint64_t __r3;1223 uint64_t __r4;1224 uint64_t __r5;1225 uint64_t __r6;1226 uint64_t __r7;1227 uint64_t __r8;1228 uint64_t __r9;1229 uint64_t __r10;1230 uint64_t __r11;1231 uint64_t __r12;1232 uint64_t __r13;1233 uint64_t __r14;1234 uint64_t __r15;1235 uint64_t __r16;1236 uint64_t __r17;1237 uint64_t __r18;1238 uint64_t __r19;1239 uint64_t __r20;1240 uint64_t __r21;1241 uint64_t __r22;1242 uint64_t __r23;1243 uint64_t __r24;1244 uint64_t __r25;1245 uint64_t __r26;1246 uint64_t __r27;1247 uint64_t __r28;1248 uint64_t __r29;1249 uint64_t __r30;1250 uint64_t __r31;1251 uint64_t __cr; // Condition register1252 uint64_t __xer; // User's integer exception register1253 uint64_t __lr; // Link register1254 uint64_t __ctr; // Count register1255 uint64_t __vrsave; // Vector Save Register1256 };1257 1258 union ppc64_vsr_t {1259 struct asfloat_s {1260 double f;1261 uint64_t v2;1262 } asfloat;1263 v128 v;1264 };1265 1266 ppc64_thread_state_t _registers;1267 ppc64_vsr_t _vectorScalarRegisters[64];1268 1269 static int getVectorRegNum(int num);1270};1271 1272inline Registers_ppc64::Registers_ppc64(const void *registers) {1273 static_assert((check_fit<Registers_ppc64, unw_context_t>::does_fit),1274 "ppc64 registers do not fit into unw_context_t");1275 memcpy(&_registers, static_cast<const uint8_t *>(registers),1276 sizeof(_registers));1277 static_assert(sizeof(_registers) == 312,1278 "expected vector scalar register offset to be 312");1279 memcpy(&_vectorScalarRegisters,1280 static_cast<const uint8_t *>(registers) + sizeof(_registers),1281 sizeof(_vectorScalarRegisters));1282 static_assert(sizeof(_registers) +1283 sizeof(_vectorScalarRegisters) == 1336,1284 "expected vector register offset to be 1336 bytes");1285}1286 1287inline Registers_ppc64::Registers_ppc64() {1288 memset(&_registers, 0, sizeof(_registers));1289 memset(&_vectorScalarRegisters, 0, sizeof(_vectorScalarRegisters));1290}1291 1292inline bool Registers_ppc64::validRegister(int regNum) const {1293 switch (regNum) {1294 case UNW_REG_IP:1295 case UNW_REG_SP:1296 case UNW_PPC64_XER:1297 case UNW_PPC64_LR:1298 case UNW_PPC64_CTR:1299 case UNW_PPC64_VRSAVE:1300 return true;1301 }1302 1303 if (regNum >= UNW_PPC64_R0 && regNum <= UNW_PPC64_R31)1304 return true;1305 if (regNum >= UNW_PPC64_CR0 && regNum <= UNW_PPC64_CR7)1306 return true;1307 1308 return false;1309}1310 1311inline uint64_t Registers_ppc64::getRegister(int regNum) const {1312 switch (regNum) {1313 case UNW_REG_IP:1314 return _registers.__srr0;1315 case UNW_PPC64_R0:1316 return _registers.__r0;1317 case UNW_PPC64_R1:1318 case UNW_REG_SP:1319 return _registers.__r1;1320 case UNW_PPC64_R2:1321 return _registers.__r2;1322 case UNW_PPC64_R3:1323 return _registers.__r3;1324 case UNW_PPC64_R4:1325 return _registers.__r4;1326 case UNW_PPC64_R5:1327 return _registers.__r5;1328 case UNW_PPC64_R6:1329 return _registers.__r6;1330 case UNW_PPC64_R7:1331 return _registers.__r7;1332 case UNW_PPC64_R8:1333 return _registers.__r8;1334 case UNW_PPC64_R9:1335 return _registers.__r9;1336 case UNW_PPC64_R10:1337 return _registers.__r10;1338 case UNW_PPC64_R11:1339 return _registers.__r11;1340 case UNW_PPC64_R12:1341 return _registers.__r12;1342 case UNW_PPC64_R13:1343 return _registers.__r13;1344 case UNW_PPC64_R14:1345 return _registers.__r14;1346 case UNW_PPC64_R15:1347 return _registers.__r15;1348 case UNW_PPC64_R16:1349 return _registers.__r16;1350 case UNW_PPC64_R17:1351 return _registers.__r17;1352 case UNW_PPC64_R18:1353 return _registers.__r18;1354 case UNW_PPC64_R19:1355 return _registers.__r19;1356 case UNW_PPC64_R20:1357 return _registers.__r20;1358 case UNW_PPC64_R21:1359 return _registers.__r21;1360 case UNW_PPC64_R22:1361 return _registers.__r22;1362 case UNW_PPC64_R23:1363 return _registers.__r23;1364 case UNW_PPC64_R24:1365 return _registers.__r24;1366 case UNW_PPC64_R25:1367 return _registers.__r25;1368 case UNW_PPC64_R26:1369 return _registers.__r26;1370 case UNW_PPC64_R27:1371 return _registers.__r27;1372 case UNW_PPC64_R28:1373 return _registers.__r28;1374 case UNW_PPC64_R29:1375 return _registers.__r29;1376 case UNW_PPC64_R30:1377 return _registers.__r30;1378 case UNW_PPC64_R31:1379 return _registers.__r31;1380 case UNW_PPC64_CR0:1381 return (_registers.__cr & 0xF0000000);1382 case UNW_PPC64_CR1:1383 return (_registers.__cr & 0x0F000000);1384 case UNW_PPC64_CR2:1385 return (_registers.__cr & 0x00F00000);1386 case UNW_PPC64_CR3:1387 return (_registers.__cr & 0x000F0000);1388 case UNW_PPC64_CR4:1389 return (_registers.__cr & 0x0000F000);1390 case UNW_PPC64_CR5:1391 return (_registers.__cr & 0x00000F00);1392 case UNW_PPC64_CR6:1393 return (_registers.__cr & 0x000000F0);1394 case UNW_PPC64_CR7:1395 return (_registers.__cr & 0x0000000F);1396 case UNW_PPC64_XER:1397 return _registers.__xer;1398 case UNW_PPC64_LR:1399 return _registers.__lr;1400 case UNW_PPC64_CTR:1401 return _registers.__ctr;1402 case UNW_PPC64_VRSAVE:1403 return _registers.__vrsave;1404 }1405 _LIBUNWIND_ABORT("unsupported ppc64 register");1406}1407 1408inline void Registers_ppc64::setRegister(int regNum, uint64_t value) {1409 switch (regNum) {1410 case UNW_REG_IP:1411 _registers.__srr0 = value;1412 return;1413 case UNW_PPC64_R0:1414 _registers.__r0 = value;1415 return;1416 case UNW_PPC64_R1:1417 case UNW_REG_SP:1418 _registers.__r1 = value;1419 return;1420 case UNW_PPC64_R2:1421 _registers.__r2 = value;1422 return;1423 case UNW_PPC64_R3:1424 _registers.__r3 = value;1425 return;1426 case UNW_PPC64_R4:1427 _registers.__r4 = value;1428 return;1429 case UNW_PPC64_R5:1430 _registers.__r5 = value;1431 return;1432 case UNW_PPC64_R6:1433 _registers.__r6 = value;1434 return;1435 case UNW_PPC64_R7:1436 _registers.__r7 = value;1437 return;1438 case UNW_PPC64_R8:1439 _registers.__r8 = value;1440 return;1441 case UNW_PPC64_R9:1442 _registers.__r9 = value;1443 return;1444 case UNW_PPC64_R10:1445 _registers.__r10 = value;1446 return;1447 case UNW_PPC64_R11:1448 _registers.__r11 = value;1449 return;1450 case UNW_PPC64_R12:1451 _registers.__r12 = value;1452 return;1453 case UNW_PPC64_R13:1454 _registers.__r13 = value;1455 return;1456 case UNW_PPC64_R14:1457 _registers.__r14 = value;1458 return;1459 case UNW_PPC64_R15:1460 _registers.__r15 = value;1461 return;1462 case UNW_PPC64_R16:1463 _registers.__r16 = value;1464 return;1465 case UNW_PPC64_R17:1466 _registers.__r17 = value;1467 return;1468 case UNW_PPC64_R18:1469 _registers.__r18 = value;1470 return;1471 case UNW_PPC64_R19:1472 _registers.__r19 = value;1473 return;1474 case UNW_PPC64_R20:1475 _registers.__r20 = value;1476 return;1477 case UNW_PPC64_R21:1478 _registers.__r21 = value;1479 return;1480 case UNW_PPC64_R22:1481 _registers.__r22 = value;1482 return;1483 case UNW_PPC64_R23:1484 _registers.__r23 = value;1485 return;1486 case UNW_PPC64_R24:1487 _registers.__r24 = value;1488 return;1489 case UNW_PPC64_R25:1490 _registers.__r25 = value;1491 return;1492 case UNW_PPC64_R26:1493 _registers.__r26 = value;1494 return;1495 case UNW_PPC64_R27:1496 _registers.__r27 = value;1497 return;1498 case UNW_PPC64_R28:1499 _registers.__r28 = value;1500 return;1501 case UNW_PPC64_R29:1502 _registers.__r29 = value;1503 return;1504 case UNW_PPC64_R30:1505 _registers.__r30 = value;1506 return;1507 case UNW_PPC64_R31:1508 _registers.__r31 = value;1509 return;1510 case UNW_PPC64_CR0:1511 _registers.__cr &= 0x0FFFFFFF;1512 _registers.__cr |= (value & 0xF0000000);1513 return;1514 case UNW_PPC64_CR1:1515 _registers.__cr &= 0xF0FFFFFF;1516 _registers.__cr |= (value & 0x0F000000);1517 return;1518 case UNW_PPC64_CR2:1519 _registers.__cr &= 0xFF0FFFFF;1520 _registers.__cr |= (value & 0x00F00000);1521 return;1522 case UNW_PPC64_CR3:1523 _registers.__cr &= 0xFFF0FFFF;1524 _registers.__cr |= (value & 0x000F0000);1525 return;1526 case UNW_PPC64_CR4:1527 _registers.__cr &= 0xFFFF0FFF;1528 _registers.__cr |= (value & 0x0000F000);1529 return;1530 case UNW_PPC64_CR5:1531 _registers.__cr &= 0xFFFFF0FF;1532 _registers.__cr |= (value & 0x00000F00);1533 return;1534 case UNW_PPC64_CR6:1535 _registers.__cr &= 0xFFFFFF0F;1536 _registers.__cr |= (value & 0x000000F0);1537 return;1538 case UNW_PPC64_CR7:1539 _registers.__cr &= 0xFFFFFFF0;1540 _registers.__cr |= (value & 0x0000000F);1541 return;1542 case UNW_PPC64_XER:1543 _registers.__xer = value;1544 return;1545 case UNW_PPC64_LR:1546 _registers.__lr = value;1547 return;1548 case UNW_PPC64_CTR:1549 _registers.__ctr = value;1550 return;1551 case UNW_PPC64_VRSAVE:1552 _registers.__vrsave = value;1553 return;1554 }1555 _LIBUNWIND_ABORT("unsupported ppc64 register");1556}1557 1558inline bool Registers_ppc64::validFloatRegister(int regNum) const {1559 return regNum >= UNW_PPC64_F0 && regNum <= UNW_PPC64_F31;1560}1561 1562inline double Registers_ppc64::getFloatRegister(int regNum) const {1563 assert(validFloatRegister(regNum));1564 return _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f;1565}1566 1567inline void Registers_ppc64::setFloatRegister(int regNum, double value) {1568 assert(validFloatRegister(regNum));1569 _vectorScalarRegisters[regNum - UNW_PPC64_F0].asfloat.f = value;1570}1571 1572inline bool Registers_ppc64::validVectorRegister(int regNum) const {1573#if defined(__VSX__)1574 if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31)1575 return true;1576 if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63)1577 return true;1578#elif defined(__ALTIVEC__)1579 if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31)1580 return true;1581#endif1582 return false;1583}1584 1585inline int Registers_ppc64::getVectorRegNum(int num)1586{1587 if (num >= UNW_PPC64_VS0 && num <= UNW_PPC64_VS31)1588 return num - UNW_PPC64_VS0;1589 else1590 return num - UNW_PPC64_VS32 + 32;1591}1592 1593inline v128 Registers_ppc64::getVectorRegister(int regNum) const {1594 assert(validVectorRegister(regNum));1595 return _vectorScalarRegisters[getVectorRegNum(regNum)].v;1596}1597 1598inline void Registers_ppc64::setVectorRegister(int regNum, v128 value) {1599 assert(validVectorRegister(regNum));1600 _vectorScalarRegisters[getVectorRegNum(regNum)].v = value;1601}1602 1603inline const char *Registers_ppc64::getRegisterName(int regNum) {1604 switch (regNum) {1605 case UNW_REG_IP:1606 return "ip";1607 case UNW_REG_SP:1608 return "sp";1609 case UNW_PPC64_R0:1610 return "r0";1611 case UNW_PPC64_R1:1612 return "r1";1613 case UNW_PPC64_R2:1614 return "r2";1615 case UNW_PPC64_R3:1616 return "r3";1617 case UNW_PPC64_R4:1618 return "r4";1619 case UNW_PPC64_R5:1620 return "r5";1621 case UNW_PPC64_R6:1622 return "r6";1623 case UNW_PPC64_R7:1624 return "r7";1625 case UNW_PPC64_R8:1626 return "r8";1627 case UNW_PPC64_R9:1628 return "r9";1629 case UNW_PPC64_R10:1630 return "r10";1631 case UNW_PPC64_R11:1632 return "r11";1633 case UNW_PPC64_R12:1634 return "r12";1635 case UNW_PPC64_R13:1636 return "r13";1637 case UNW_PPC64_R14:1638 return "r14";1639 case UNW_PPC64_R15:1640 return "r15";1641 case UNW_PPC64_R16:1642 return "r16";1643 case UNW_PPC64_R17:1644 return "r17";1645 case UNW_PPC64_R18:1646 return "r18";1647 case UNW_PPC64_R19:1648 return "r19";1649 case UNW_PPC64_R20:1650 return "r20";1651 case UNW_PPC64_R21:1652 return "r21";1653 case UNW_PPC64_R22:1654 return "r22";1655 case UNW_PPC64_R23:1656 return "r23";1657 case UNW_PPC64_R24:1658 return "r24";1659 case UNW_PPC64_R25:1660 return "r25";1661 case UNW_PPC64_R26:1662 return "r26";1663 case UNW_PPC64_R27:1664 return "r27";1665 case UNW_PPC64_R28:1666 return "r28";1667 case UNW_PPC64_R29:1668 return "r29";1669 case UNW_PPC64_R30:1670 return "r30";1671 case UNW_PPC64_R31:1672 return "r31";1673 case UNW_PPC64_CR0:1674 return "cr0";1675 case UNW_PPC64_CR1:1676 return "cr1";1677 case UNW_PPC64_CR2:1678 return "cr2";1679 case UNW_PPC64_CR3:1680 return "cr3";1681 case UNW_PPC64_CR4:1682 return "cr4";1683 case UNW_PPC64_CR5:1684 return "cr5";1685 case UNW_PPC64_CR6:1686 return "cr6";1687 case UNW_PPC64_CR7:1688 return "cr7";1689 case UNW_PPC64_XER:1690 return "xer";1691 case UNW_PPC64_LR:1692 return "lr";1693 case UNW_PPC64_CTR:1694 return "ctr";1695 case UNW_PPC64_VRSAVE:1696 return "vrsave";1697 case UNW_PPC64_F0:1698 return "fp0";1699 case UNW_PPC64_F1:1700 return "fp1";1701 case UNW_PPC64_F2:1702 return "fp2";1703 case UNW_PPC64_F3:1704 return "fp3";1705 case UNW_PPC64_F4:1706 return "fp4";1707 case UNW_PPC64_F5:1708 return "fp5";1709 case UNW_PPC64_F6:1710 return "fp6";1711 case UNW_PPC64_F7:1712 return "fp7";1713 case UNW_PPC64_F8:1714 return "fp8";1715 case UNW_PPC64_F9:1716 return "fp9";1717 case UNW_PPC64_F10:1718 return "fp10";1719 case UNW_PPC64_F11:1720 return "fp11";1721 case UNW_PPC64_F12:1722 return "fp12";1723 case UNW_PPC64_F13:1724 return "fp13";1725 case UNW_PPC64_F14:1726 return "fp14";1727 case UNW_PPC64_F15:1728 return "fp15";1729 case UNW_PPC64_F16:1730 return "fp16";1731 case UNW_PPC64_F17:1732 return "fp17";1733 case UNW_PPC64_F18:1734 return "fp18";1735 case UNW_PPC64_F19:1736 return "fp19";1737 case UNW_PPC64_F20:1738 return "fp20";1739 case UNW_PPC64_F21:1740 return "fp21";1741 case UNW_PPC64_F22:1742 return "fp22";1743 case UNW_PPC64_F23:1744 return "fp23";1745 case UNW_PPC64_F24:1746 return "fp24";1747 case UNW_PPC64_F25:1748 return "fp25";1749 case UNW_PPC64_F26:1750 return "fp26";1751 case UNW_PPC64_F27:1752 return "fp27";1753 case UNW_PPC64_F28:1754 return "fp28";1755 case UNW_PPC64_F29:1756 return "fp29";1757 case UNW_PPC64_F30:1758 return "fp30";1759 case UNW_PPC64_F31:1760 return "fp31";1761 case UNW_PPC64_V0:1762 return "v0";1763 case UNW_PPC64_V1:1764 return "v1";1765 case UNW_PPC64_V2:1766 return "v2";1767 case UNW_PPC64_V3:1768 return "v3";1769 case UNW_PPC64_V4:1770 return "v4";1771 case UNW_PPC64_V5:1772 return "v5";1773 case UNW_PPC64_V6:1774 return "v6";1775 case UNW_PPC64_V7:1776 return "v7";1777 case UNW_PPC64_V8:1778 return "v8";1779 case UNW_PPC64_V9:1780 return "v9";1781 case UNW_PPC64_V10:1782 return "v10";1783 case UNW_PPC64_V11:1784 return "v11";1785 case UNW_PPC64_V12:1786 return "v12";1787 case UNW_PPC64_V13:1788 return "v13";1789 case UNW_PPC64_V14:1790 return "v14";1791 case UNW_PPC64_V15:1792 return "v15";1793 case UNW_PPC64_V16:1794 return "v16";1795 case UNW_PPC64_V17:1796 return "v17";1797 case UNW_PPC64_V18:1798 return "v18";1799 case UNW_PPC64_V19:1800 return "v19";1801 case UNW_PPC64_V20:1802 return "v20";1803 case UNW_PPC64_V21:1804 return "v21";1805 case UNW_PPC64_V22:1806 return "v22";1807 case UNW_PPC64_V23:1808 return "v23";1809 case UNW_PPC64_V24:1810 return "v24";1811 case UNW_PPC64_V25:1812 return "v25";1813 case UNW_PPC64_V26:1814 return "v26";1815 case UNW_PPC64_V27:1816 return "v27";1817 case UNW_PPC64_V28:1818 return "v28";1819 case UNW_PPC64_V29:1820 return "v29";1821 case UNW_PPC64_V30:1822 return "v30";1823 case UNW_PPC64_V31:1824 return "v31";1825 }1826 return "unknown register";1827}1828#endif // _LIBUNWIND_TARGET_PPC641829 1830 1831#if defined(_LIBUNWIND_TARGET_AARCH64)1832/// Registers_arm64 holds the register state of a thread in a 64-bit arm1833/// process.1834class _LIBUNWIND_HIDDEN Registers_arm64;1835extern "C" int64_t __libunwind_Registers_arm64_za_disable();1836extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *,1837 unsigned walkedFrames);1838 1839#if defined(_LIBUNWIND_USE_GCS)1840extern "C" void *__libunwind_shstk_get_jump_target() {1841 return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);1842}1843#endif1844 1845class _LIBUNWIND_HIDDEN Registers_arm64 {1846public:1847 Registers_arm64() = default;1848 Registers_arm64(const void *registers);1849 Registers_arm64(const Registers_arm64 &);1850 Registers_arm64 &operator=(const Registers_arm64 &);1851 1852 typedef uint64_t reg_t;1853 typedef uint64_t __ptrauth_unwind_registers_arm64_link_reg link_reg_t;1854 1855 bool validRegister(int num) const;1856 uint64_t getRegister(int num) const;1857 void setRegister(int num, uint64_t value);1858 bool validFloatRegister(int num) const;1859 double getFloatRegister(int num) const;1860 void setFloatRegister(int num, double value);1861 bool validVectorRegister(int num) const;1862 v128 getVectorRegister(int num) const;1863 void setVectorRegister(int num, v128 value);1864 static const char *getRegisterName(int num);1865 void jumpto(unsigned walkedFrames = 0) {1866 zaDisable();1867 __libunwind_Registers_arm64_jumpto(this, walkedFrames);1868 }1869#ifdef _LIBUNWIND_TRACE_RET_INJECT1870 _LIBUNWIND_TRACE_NO_INLINE1871 void returnto(unsigned walkedFrames) { jumpto(walkedFrames); }1872#endif1873 static constexpr int lastDwarfRegNum() {1874 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;1875 }1876 static int getArch() { return REGISTERS_ARM64; }1877 1878 uint64_t getSP() const { return _registers.__sp; }1879 void setSP(uint64_t value) { _registers.__sp = value; }1880 uint64_t getIP() const {1881 uint64_t value = _registers.__pc;1882#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)1883 // Note the value of the PC was signed to its address in the register state1884 // but everyone else expects it to be sign by the SP, so convert on return.1885 value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc,1886 ptrauth_key_return_address,1887 &_registers.__pc,1888 ptrauth_key_return_address,1889 getSP());1890#endif1891 return value;1892 }1893 void setIP(uint64_t value) {1894#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)1895 // Note the value which was set should have been signed with the SP.1896 // We then resign with the slot we are being stored in to so that both SP1897 // and LR can't be spoofed at the same time.1898 value = (uint64_t)ptrauth_auth_and_resign((void *)value,1899 ptrauth_key_return_address,1900 getSP(),1901 ptrauth_key_return_address,1902 &_registers.__pc);1903#endif1904 _registers.__pc = value;1905 }1906 uint64_t getFP() const { return _registers.__fp; }1907 void setFP(uint64_t value) { _registers.__fp = value; }1908 1909#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)1910 void1911 loadAndAuthenticateLinkRegister(reg_t inplaceAuthedLinkRegister,1912 link_reg_t *referenceAuthedLinkRegister) {1913 // If we are in an arm64/arm64e frame, then the PC should have been signed1914 // with the SP1915 *referenceAuthedLinkRegister =1916 (uint64_t)ptrauth_auth_data((void *)inplaceAuthedLinkRegister,1917 ptrauth_key_return_address,1918 _registers.__sp);1919 }1920#endif1921 1922private:1923 uint64_t lazyGetVG() const;1924 1925 void zaDisable() const {1926 if (!_misc_registers.__has_sme)1927 return;1928 if (__libunwind_Registers_arm64_za_disable() != 0)1929 _LIBUNWIND_ABORT("SME ZA disable failed");1930 }1931 1932 static bool checkHasSME() {1933#if defined(HAVE_SYS_AUXV_H)1934 constexpr int hwcap2_sme = (1 << 23);1935 unsigned long hwcap2 = getauxval(AT_HWCAP2);1936 return (hwcap2 & hwcap2_sme) != 0;1937#endif1938 // TODO: Support other platforms.1939 return false;1940 }1941 1942 struct GPRs {1943 uint64_t __x[29] = {}; // x0-x281944 uint64_t __fp = 0; // Frame pointer x291945 uint64_t __lr = 0; // Link register x301946 uint64_t __sp = 0; // Stack pointer x311947 uint64_t __pc = 0; // Program counter1948 uint64_t __ra_sign_state = 0; // RA sign state register1949 };1950 1951 struct Misc {1952 mutable uint32_t __vg = 0; // Vector Granule1953 bool __has_sme = checkHasSME();1954 };1955 1956 GPRs _registers = {};1957 // Currently only the lower double in 128-bit vectore registers1958 // is perserved during unwinding. We could define new register1959 // numbers (> 96) which mean whole vector registers, then this1960 // struct would need to change to contain whole vector registers.1961 double _vectorHalfRegisters[32] = {};1962 1963 // Miscellaneous/virtual registers. These are stored below the GPRs and FPRs1964 // as they do not correspond to physical registers, so do not need to be1965 // saved/restored in UnwindRegistersRestore.S and UnwindRegistersSave.S, and1966 // we don't want to modify the existing offsets for GPRs and FPRs.1967 Misc _misc_registers;1968};1969 1970inline Registers_arm64::Registers_arm64(const void *registers) {1971 static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit),1972 "arm64 registers do not fit into unw_context_t");1973 memcpy(&_registers, registers, sizeof(_registers));1974 static_assert(sizeof(GPRs) == 0x110,1975 "expected VFP registers to be at offset 272");1976 memcpy(_vectorHalfRegisters,1977 static_cast<const uint8_t *>(registers) + sizeof(GPRs),1978 sizeof(_vectorHalfRegisters));1979 _misc_registers.__vg = 0;1980 1981#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)1982 // We have to do some pointer authentication fixups after this copy,1983 // and as part of that we need to load the source pc without1984 // authenticating so that we maintain the signature for the resigning1985 // performed by setIP.1986 uint64_t pcRegister = 0;1987 memmove(&pcRegister, ((uint8_t *)&_registers) + offsetof(GPRs, __pc),1988 sizeof(pcRegister));1989 setIP(pcRegister);1990#endif1991}1992 1993inline Registers_arm64::Registers_arm64(const Registers_arm64 &other) {1994 *this = other;1995}1996 1997inline Registers_arm64 &1998Registers_arm64::operator=(const Registers_arm64 &other) {1999 memmove(static_cast<void *>(this), &other, sizeof(*this));2000 // We perform this step to ensure that we correctly authenticate and re-sign2001 // the pc after the bitwise copy.2002 setIP(other.getIP());2003 return *this;2004}2005 2006inline bool Registers_arm64::validRegister(int regNum) const {2007 if (regNum == UNW_REG_IP)2008 return true;2009 if (regNum == UNW_REG_SP)2010 return true;2011 if (regNum < 0)2012 return false;2013 if (regNum > 95)2014 return false;2015 if (regNum == UNW_AARCH64_RA_SIGN_STATE)2016 return true;2017 if (regNum == UNW_AARCH64_VG)2018 return true;2019 if ((regNum > 32) && (regNum < 64))2020 return false;2021 return true;2022}2023 2024inline uint64_t Registers_arm64::lazyGetVG() const {2025 if (!_misc_registers.__vg) {2026#if defined(__aarch64__)2027 register uint64_t vg asm("x0");2028 asm(".inst 0x04e0e3e0" // CNTD x02029 : "=r"(vg));2030 _misc_registers.__vg = vg;2031#else2032 _LIBUNWIND_ABORT("arm64 VG undefined");2033#endif2034 }2035 return _misc_registers.__vg;2036}2037 2038inline uint64_t Registers_arm64::getRegister(int regNum) const {2039 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)2040 return getIP();2041 if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)2042 return _registers.__sp;2043 if (regNum == UNW_AARCH64_RA_SIGN_STATE)2044 return _registers.__ra_sign_state;2045 if (regNum == UNW_AARCH64_FP)2046 return getFP();2047 if (regNum == UNW_AARCH64_LR)2048 return _registers.__lr;2049 if (regNum == UNW_AARCH64_VG)2050 return lazyGetVG();2051 if ((regNum >= 0) && (regNum < 29))2052 return _registers.__x[regNum];2053 _LIBUNWIND_ABORT("unsupported arm64 register");2054}2055 2056inline void Registers_arm64::setRegister(int regNum, uint64_t value) {2057 if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC)2058 setIP(value);2059 else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP)2060 _registers.__sp = value;2061 else if (regNum == UNW_AARCH64_RA_SIGN_STATE)2062 _registers.__ra_sign_state = value;2063 else if (regNum == UNW_AARCH64_FP)2064 setFP(value);2065 else if (regNum == UNW_AARCH64_LR)2066 _registers.__lr = value;2067 else if (regNum == UNW_AARCH64_VG)2068 _misc_registers.__vg = value;2069 else if ((regNum >= 0) && (regNum < 29))2070 _registers.__x[regNum] = value;2071 else2072 _LIBUNWIND_ABORT("unsupported arm64 register");2073}2074 2075inline const char *Registers_arm64::getRegisterName(int regNum) {2076 switch (regNum) {2077 case UNW_REG_IP:2078 return "pc";2079 case UNW_REG_SP:2080 return "sp";2081 case UNW_AARCH64_X0:2082 return "x0";2083 case UNW_AARCH64_X1:2084 return "x1";2085 case UNW_AARCH64_X2:2086 return "x2";2087 case UNW_AARCH64_X3:2088 return "x3";2089 case UNW_AARCH64_X4:2090 return "x4";2091 case UNW_AARCH64_X5:2092 return "x5";2093 case UNW_AARCH64_X6:2094 return "x6";2095 case UNW_AARCH64_X7:2096 return "x7";2097 case UNW_AARCH64_X8:2098 return "x8";2099 case UNW_AARCH64_X9:2100 return "x9";2101 case UNW_AARCH64_X10:2102 return "x10";2103 case UNW_AARCH64_X11:2104 return "x11";2105 case UNW_AARCH64_X12:2106 return "x12";2107 case UNW_AARCH64_X13:2108 return "x13";2109 case UNW_AARCH64_X14:2110 return "x14";2111 case UNW_AARCH64_X15:2112 return "x15";2113 case UNW_AARCH64_X16:2114 return "x16";2115 case UNW_AARCH64_X17:2116 return "x17";2117 case UNW_AARCH64_X18:2118 return "x18";2119 case UNW_AARCH64_X19:2120 return "x19";2121 case UNW_AARCH64_X20:2122 return "x20";2123 case UNW_AARCH64_X21:2124 return "x21";2125 case UNW_AARCH64_X22:2126 return "x22";2127 case UNW_AARCH64_X23:2128 return "x23";2129 case UNW_AARCH64_X24:2130 return "x24";2131 case UNW_AARCH64_X25:2132 return "x25";2133 case UNW_AARCH64_X26:2134 return "x26";2135 case UNW_AARCH64_X27:2136 return "x27";2137 case UNW_AARCH64_X28:2138 return "x28";2139 case UNW_AARCH64_FP:2140 return "fp";2141 case UNW_AARCH64_LR:2142 return "lr";2143 case UNW_AARCH64_SP:2144 return "sp";2145 case UNW_AARCH64_PC:2146 return "pc";2147 case UNW_AARCH64_V0:2148 return "d0";2149 case UNW_AARCH64_V1:2150 return "d1";2151 case UNW_AARCH64_V2:2152 return "d2";2153 case UNW_AARCH64_V3:2154 return "d3";2155 case UNW_AARCH64_V4:2156 return "d4";2157 case UNW_AARCH64_V5:2158 return "d5";2159 case UNW_AARCH64_V6:2160 return "d6";2161 case UNW_AARCH64_V7:2162 return "d7";2163 case UNW_AARCH64_V8:2164 return "d8";2165 case UNW_AARCH64_V9:2166 return "d9";2167 case UNW_AARCH64_V10:2168 return "d10";2169 case UNW_AARCH64_V11:2170 return "d11";2171 case UNW_AARCH64_V12:2172 return "d12";2173 case UNW_AARCH64_V13:2174 return "d13";2175 case UNW_AARCH64_V14:2176 return "d14";2177 case UNW_AARCH64_V15:2178 return "d15";2179 case UNW_AARCH64_V16:2180 return "d16";2181 case UNW_AARCH64_V17:2182 return "d17";2183 case UNW_AARCH64_V18:2184 return "d18";2185 case UNW_AARCH64_V19:2186 return "d19";2187 case UNW_AARCH64_V20:2188 return "d20";2189 case UNW_AARCH64_V21:2190 return "d21";2191 case UNW_AARCH64_V22:2192 return "d22";2193 case UNW_AARCH64_V23:2194 return "d23";2195 case UNW_AARCH64_V24:2196 return "d24";2197 case UNW_AARCH64_V25:2198 return "d25";2199 case UNW_AARCH64_V26:2200 return "d26";2201 case UNW_AARCH64_V27:2202 return "d27";2203 case UNW_AARCH64_V28:2204 return "d28";2205 case UNW_AARCH64_V29:2206 return "d29";2207 case UNW_AARCH64_V30:2208 return "d30";2209 case UNW_AARCH64_V31:2210 return "d31";2211 default:2212 return "unknown register";2213 }2214}2215 2216inline bool Registers_arm64::validFloatRegister(int regNum) const {2217 if (regNum < UNW_AARCH64_V0)2218 return false;2219 if (regNum > UNW_AARCH64_V31)2220 return false;2221 return true;2222}2223 2224inline double Registers_arm64::getFloatRegister(int regNum) const {2225 assert(validFloatRegister(regNum));2226 return _vectorHalfRegisters[regNum - UNW_AARCH64_V0];2227}2228 2229inline void Registers_arm64::setFloatRegister(int regNum, double value) {2230 assert(validFloatRegister(regNum));2231 _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value;2232}2233 2234inline bool Registers_arm64::validVectorRegister(int) const {2235 return false;2236}2237 2238inline v128 Registers_arm64::getVectorRegister(int) const {2239 _LIBUNWIND_ABORT("no arm64 vector register support yet");2240}2241 2242inline void Registers_arm64::setVectorRegister(int, v128) {2243 _LIBUNWIND_ABORT("no arm64 vector register support yet");2244}2245#endif // _LIBUNWIND_TARGET_AARCH642246 2247#if defined(_LIBUNWIND_TARGET_ARM)2248/// Registers_arm holds the register state of a thread in a 32-bit arm2249/// process.2250///2251/// NOTE: Assumes VFPv3. On ARM processors without a floating point unit,2252/// this uses more memory than required.2253class _LIBUNWIND_HIDDEN Registers_arm {2254public:2255 Registers_arm();2256 Registers_arm(const void *registers);2257 2258 typedef uint32_t reg_t;2259 typedef uint32_t link_reg_t;2260 2261 bool validRegister(int num) const;2262 uint32_t getRegister(int num) const;2263 void setRegister(int num, uint32_t value);2264 bool validFloatRegister(int num) const;2265 unw_fpreg_t getFloatRegister(int num);2266 void setFloatRegister(int num, unw_fpreg_t value);2267 bool validVectorRegister(int num) const;2268 v128 getVectorRegister(int num) const;2269 void setVectorRegister(int num, v128 value);2270 static const char *getRegisterName(int num);2271 void jumpto() {2272 restoreSavedFloatRegisters();2273 restoreCoreAndJumpTo();2274 }2275 static constexpr int lastDwarfRegNum() {2276 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;2277 }2278 static int getArch() { return REGISTERS_ARM; }2279 2280 uint32_t getSP() const { return _registers.__sp; }2281 void setSP(uint32_t value) { _registers.__sp = value; }2282 uint32_t getIP() const { return _registers.__pc; }2283 void setIP(uint32_t value) { _registers.__pc = value; }2284 2285 void saveVFPAsX() {2286 assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15);2287 _use_X_for_vfp_save = true;2288 }2289 2290 void restoreSavedFloatRegisters() {2291 if (_saved_vfp_d0_d15) {2292 if (_use_X_for_vfp_save)2293 restoreVFPWithFLDMX(_vfp_d0_d15_pad);2294 else2295 restoreVFPWithFLDMD(_vfp_d0_d15_pad);2296 }2297 if (_saved_vfp_d16_d31)2298 restoreVFPv3(_vfp_d16_d31);2299#if defined(__ARM_WMMX)2300 if (_saved_iwmmx)2301 restoreiWMMX(_iwmmx);2302 if (_saved_iwmmx_control)2303 restoreiWMMXControl(_iwmmx_control);2304#endif2305 }2306 2307private:2308 struct GPRs {2309 uint32_t __r[13]; // r0-r122310 uint32_t __sp; // Stack pointer r132311 uint32_t __lr; // Link register r142312 uint32_t __pc; // Program counter r152313 };2314 2315 struct PseudoRegisters {2316 uint32_t __pac; // Return Authentication Code (PAC)2317 };2318 2319 static void saveVFPWithFSTMD(void*);2320 static void saveVFPWithFSTMX(void*);2321 static void saveVFPv3(void*);2322 static void restoreVFPWithFLDMD(void*);2323 static void restoreVFPWithFLDMX(void*);2324 static void restoreVFPv3(void*);2325#if defined(__ARM_WMMX)2326 static void saveiWMMX(void*);2327 static void saveiWMMXControl(uint32_t*);2328 static void restoreiWMMX(void*);2329 static void restoreiWMMXControl(uint32_t*);2330#endif2331 void restoreCoreAndJumpTo();2332 2333 // ARM registers2334 GPRs _registers;2335 PseudoRegisters _pseudo_registers;2336 2337 // We save floating point registers lazily because we can't know ahead of2338 // time which ones are used. See EHABI #4.7.2339 2340 // Whether D0-D15 are saved in the FTSMX instead of FSTMD format.2341 //2342 // See EHABI #7.5 that explains how matching instruction sequences for load2343 // and store need to be used to correctly restore the exact register bits.2344 bool _use_X_for_vfp_save;2345 // Whether VFP D0-D15 are saved.2346 bool _saved_vfp_d0_d15;2347 // Whether VFPv3 D16-D31 are saved.2348 bool _saved_vfp_d16_d31;2349 // VFP registers D0-D15, + padding if saved using FSTMX2350 unw_fpreg_t _vfp_d0_d15_pad[17];2351 // VFPv3 registers D16-D31, always saved using FSTMD2352 unw_fpreg_t _vfp_d16_d31[16];2353#if defined(__ARM_WMMX)2354 // Whether iWMMX data registers are saved.2355 bool _saved_iwmmx;2356 // Whether iWMMX control registers are saved.2357 mutable bool _saved_iwmmx_control;2358 // iWMMX registers2359 unw_fpreg_t _iwmmx[16];2360 // iWMMX control registers2361 mutable uint32_t _iwmmx_control[4];2362#endif2363};2364 2365inline Registers_arm::Registers_arm(const void *registers)2366 : _use_X_for_vfp_save(false),2367 _saved_vfp_d0_d15(false),2368 _saved_vfp_d16_d31(false) {2369 static_assert((check_fit<Registers_arm, unw_context_t>::does_fit),2370 "arm registers do not fit into unw_context_t");2371 // See __unw_getcontext() note about data.2372 memcpy(&_registers, registers, sizeof(_registers));2373 memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));2374 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));2375 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));2376#if defined(__ARM_WMMX)2377 _saved_iwmmx = false;2378 _saved_iwmmx_control = false;2379 memset(&_iwmmx, 0, sizeof(_iwmmx));2380 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));2381#endif2382}2383 2384inline Registers_arm::Registers_arm()2385 : _use_X_for_vfp_save(false),2386 _saved_vfp_d0_d15(false),2387 _saved_vfp_d16_d31(false) {2388 memset(&_registers, 0, sizeof(_registers));2389 memset(&_pseudo_registers, 0, sizeof(_pseudo_registers));2390 memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad));2391 memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31));2392#if defined(__ARM_WMMX)2393 _saved_iwmmx = false;2394 _saved_iwmmx_control = false;2395 memset(&_iwmmx, 0, sizeof(_iwmmx));2396 memset(&_iwmmx_control, 0, sizeof(_iwmmx_control));2397#endif2398}2399 2400inline bool Registers_arm::validRegister(int regNum) const {2401 // Returns true for all non-VFP registers supported by the EHABI2402 // virtual register set (VRS).2403 if (regNum == UNW_REG_IP)2404 return true;2405 2406 if (regNum == UNW_REG_SP)2407 return true;2408 2409 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15)2410 return true;2411 2412#if defined(__ARM_WMMX)2413 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3)2414 return true;2415#endif2416 2417#ifdef __ARM_FEATURE_PAUTH2418 if (regNum == UNW_ARM_RA_AUTH_CODE)2419 return true;2420#endif2421 2422 return false;2423}2424 2425inline uint32_t Registers_arm::getRegister(int regNum) const {2426 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)2427 return _registers.__sp;2428 2429 if (regNum == UNW_ARM_LR)2430 return _registers.__lr;2431 2432 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)2433 return _registers.__pc;2434 2435 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12)2436 return _registers.__r[regNum];2437 2438#if defined(__ARM_WMMX)2439 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {2440 if (!_saved_iwmmx_control) {2441 _saved_iwmmx_control = true;2442 saveiWMMXControl(_iwmmx_control);2443 }2444 return _iwmmx_control[regNum - UNW_ARM_WC0];2445 }2446#endif2447 2448#ifdef __ARM_FEATURE_PAUTH2449 if (regNum == UNW_ARM_RA_AUTH_CODE)2450 return _pseudo_registers.__pac;2451#endif2452 2453 _LIBUNWIND_ABORT("unsupported arm register");2454}2455 2456inline void Registers_arm::setRegister(int regNum, uint32_t value) {2457 if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) {2458 _registers.__sp = value;2459 return;2460 }2461 2462 if (regNum == UNW_ARM_LR) {2463 _registers.__lr = value;2464 return;2465 }2466 2467 if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) {2468 _registers.__pc = value;2469 return;2470 }2471 2472 if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) {2473 _registers.__r[regNum] = value;2474 return;2475 }2476 2477#if defined(__ARM_WMMX)2478 if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) {2479 if (!_saved_iwmmx_control) {2480 _saved_iwmmx_control = true;2481 saveiWMMXControl(_iwmmx_control);2482 }2483 _iwmmx_control[regNum - UNW_ARM_WC0] = value;2484 return;2485 }2486#endif2487 2488 if (regNum == UNW_ARM_RA_AUTH_CODE) {2489 _pseudo_registers.__pac = value;2490 return;2491 }2492 2493 _LIBUNWIND_ABORT("unsupported arm register");2494}2495 2496inline const char *Registers_arm::getRegisterName(int regNum) {2497 switch (regNum) {2498 case UNW_REG_IP:2499 case UNW_ARM_IP: // UNW_ARM_R15 is alias2500 return "pc";2501 case UNW_ARM_LR: // UNW_ARM_R14 is alias2502 return "lr";2503 case UNW_REG_SP:2504 case UNW_ARM_SP: // UNW_ARM_R13 is alias2505 return "sp";2506 case UNW_ARM_R0:2507 return "r0";2508 case UNW_ARM_R1:2509 return "r1";2510 case UNW_ARM_R2:2511 return "r2";2512 case UNW_ARM_R3:2513 return "r3";2514 case UNW_ARM_R4:2515 return "r4";2516 case UNW_ARM_R5:2517 return "r5";2518 case UNW_ARM_R6:2519 return "r6";2520 case UNW_ARM_R7:2521 return "r7";2522 case UNW_ARM_R8:2523 return "r8";2524 case UNW_ARM_R9:2525 return "r9";2526 case UNW_ARM_R10:2527 return "r10";2528 case UNW_ARM_R11:2529 return "r11";2530 case UNW_ARM_R12:2531 return "r12";2532 case UNW_ARM_S0:2533 return "s0";2534 case UNW_ARM_S1:2535 return "s1";2536 case UNW_ARM_S2:2537 return "s2";2538 case UNW_ARM_S3:2539 return "s3";2540 case UNW_ARM_S4:2541 return "s4";2542 case UNW_ARM_S5:2543 return "s5";2544 case UNW_ARM_S6:2545 return "s6";2546 case UNW_ARM_S7:2547 return "s7";2548 case UNW_ARM_S8:2549 return "s8";2550 case UNW_ARM_S9:2551 return "s9";2552 case UNW_ARM_S10:2553 return "s10";2554 case UNW_ARM_S11:2555 return "s11";2556 case UNW_ARM_S12:2557 return "s12";2558 case UNW_ARM_S13:2559 return "s13";2560 case UNW_ARM_S14:2561 return "s14";2562 case UNW_ARM_S15:2563 return "s15";2564 case UNW_ARM_S16:2565 return "s16";2566 case UNW_ARM_S17:2567 return "s17";2568 case UNW_ARM_S18:2569 return "s18";2570 case UNW_ARM_S19:2571 return "s19";2572 case UNW_ARM_S20:2573 return "s20";2574 case UNW_ARM_S21:2575 return "s21";2576 case UNW_ARM_S22:2577 return "s22";2578 case UNW_ARM_S23:2579 return "s23";2580 case UNW_ARM_S24:2581 return "s24";2582 case UNW_ARM_S25:2583 return "s25";2584 case UNW_ARM_S26:2585 return "s26";2586 case UNW_ARM_S27:2587 return "s27";2588 case UNW_ARM_S28:2589 return "s28";2590 case UNW_ARM_S29:2591 return "s29";2592 case UNW_ARM_S30:2593 return "s30";2594 case UNW_ARM_S31:2595 return "s31";2596 case UNW_ARM_D0:2597 return "d0";2598 case UNW_ARM_D1:2599 return "d1";2600 case UNW_ARM_D2:2601 return "d2";2602 case UNW_ARM_D3:2603 return "d3";2604 case UNW_ARM_D4:2605 return "d4";2606 case UNW_ARM_D5:2607 return "d5";2608 case UNW_ARM_D6:2609 return "d6";2610 case UNW_ARM_D7:2611 return "d7";2612 case UNW_ARM_D8:2613 return "d8";2614 case UNW_ARM_D9:2615 return "d9";2616 case UNW_ARM_D10:2617 return "d10";2618 case UNW_ARM_D11:2619 return "d11";2620 case UNW_ARM_D12:2621 return "d12";2622 case UNW_ARM_D13:2623 return "d13";2624 case UNW_ARM_D14:2625 return "d14";2626 case UNW_ARM_D15:2627 return "d15";2628 case UNW_ARM_D16:2629 return "d16";2630 case UNW_ARM_D17:2631 return "d17";2632 case UNW_ARM_D18:2633 return "d18";2634 case UNW_ARM_D19:2635 return "d19";2636 case UNW_ARM_D20:2637 return "d20";2638 case UNW_ARM_D21:2639 return "d21";2640 case UNW_ARM_D22:2641 return "d22";2642 case UNW_ARM_D23:2643 return "d23";2644 case UNW_ARM_D24:2645 return "d24";2646 case UNW_ARM_D25:2647 return "d25";2648 case UNW_ARM_D26:2649 return "d26";2650 case UNW_ARM_D27:2651 return "d27";2652 case UNW_ARM_D28:2653 return "d28";2654 case UNW_ARM_D29:2655 return "d29";2656 case UNW_ARM_D30:2657 return "d30";2658 case UNW_ARM_D31:2659 return "d31";2660 default:2661 return "unknown register";2662 }2663}2664 2665inline bool Registers_arm::validFloatRegister(int regNum) const {2666 // NOTE: Consider the intel MMX registers floating points so the2667 // __unw_get_fpreg can be used to transmit the 64-bit data back.2668 return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31))2669#if defined(__ARM_WMMX)2670 || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15))2671#endif2672 ;2673}2674 2675inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) {2676 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {2677 if (!_saved_vfp_d0_d15) {2678 _saved_vfp_d0_d15 = true;2679 if (_use_X_for_vfp_save)2680 saveVFPWithFSTMX(_vfp_d0_d15_pad);2681 else2682 saveVFPWithFSTMD(_vfp_d0_d15_pad);2683 }2684 return _vfp_d0_d15_pad[regNum - UNW_ARM_D0];2685 }2686 2687 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {2688 if (!_saved_vfp_d16_d31) {2689 _saved_vfp_d16_d31 = true;2690 saveVFPv3(_vfp_d16_d31);2691 }2692 return _vfp_d16_d31[regNum - UNW_ARM_D16];2693 }2694 2695#if defined(__ARM_WMMX)2696 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {2697 if (!_saved_iwmmx) {2698 _saved_iwmmx = true;2699 saveiWMMX(_iwmmx);2700 }2701 return _iwmmx[regNum - UNW_ARM_WR0];2702 }2703#endif2704 2705 _LIBUNWIND_ABORT("Unknown ARM float register");2706}2707 2708inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) {2709 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) {2710 if (!_saved_vfp_d0_d15) {2711 _saved_vfp_d0_d15 = true;2712 if (_use_X_for_vfp_save)2713 saveVFPWithFSTMX(_vfp_d0_d15_pad);2714 else2715 saveVFPWithFSTMD(_vfp_d0_d15_pad);2716 }2717 _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value;2718 return;2719 }2720 2721 if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) {2722 if (!_saved_vfp_d16_d31) {2723 _saved_vfp_d16_d31 = true;2724 saveVFPv3(_vfp_d16_d31);2725 }2726 _vfp_d16_d31[regNum - UNW_ARM_D16] = value;2727 return;2728 }2729 2730#if defined(__ARM_WMMX)2731 if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) {2732 if (!_saved_iwmmx) {2733 _saved_iwmmx = true;2734 saveiWMMX(_iwmmx);2735 }2736 _iwmmx[regNum - UNW_ARM_WR0] = value;2737 return;2738 }2739#endif2740 2741 _LIBUNWIND_ABORT("Unknown ARM float register");2742}2743 2744inline bool Registers_arm::validVectorRegister(int) const {2745 return false;2746}2747 2748inline v128 Registers_arm::getVectorRegister(int) const {2749 _LIBUNWIND_ABORT("ARM vector support not implemented");2750}2751 2752inline void Registers_arm::setVectorRegister(int, v128) {2753 _LIBUNWIND_ABORT("ARM vector support not implemented");2754}2755#endif // _LIBUNWIND_TARGET_ARM2756 2757 2758#if defined(_LIBUNWIND_TARGET_OR1K)2759/// Registers_or1k holds the register state of a thread in an OpenRISC10002760/// process.2761class _LIBUNWIND_HIDDEN Registers_or1k {2762public:2763 Registers_or1k();2764 Registers_or1k(const void *registers);2765 2766 typedef uint32_t reg_t;2767 typedef uint32_t link_reg_t;2768 2769 bool validRegister(int num) const;2770 uint32_t getRegister(int num) const;2771 void setRegister(int num, uint32_t value);2772 bool validFloatRegister(int num) const;2773 double getFloatRegister(int num) const;2774 void setFloatRegister(int num, double value);2775 bool validVectorRegister(int num) const;2776 v128 getVectorRegister(int num) const;2777 void setVectorRegister(int num, v128 value);2778 static const char *getRegisterName(int num);2779 void jumpto();2780 static constexpr int lastDwarfRegNum() {2781 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;2782 }2783 static int getArch() { return REGISTERS_OR1K; }2784 2785 uint64_t getSP() const { return _registers.__r[1]; }2786 void setSP(uint32_t value) { _registers.__r[1] = value; }2787 uint64_t getIP() const { return _registers.__pc; }2788 void setIP(uint32_t value) { _registers.__pc = value; }2789 2790private:2791 struct or1k_thread_state_t {2792 unsigned int __r[32]; // r0-r312793 unsigned int __pc; // Program counter2794 unsigned int __epcr; // Program counter at exception2795 };2796 2797 or1k_thread_state_t _registers;2798};2799 2800inline Registers_or1k::Registers_or1k(const void *registers) {2801 static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit),2802 "or1k registers do not fit into unw_context_t");2803 memcpy(&_registers, static_cast<const uint8_t *>(registers),2804 sizeof(_registers));2805}2806 2807inline Registers_or1k::Registers_or1k() {2808 memset(&_registers, 0, sizeof(_registers));2809}2810 2811inline bool Registers_or1k::validRegister(int regNum) const {2812 if (regNum == UNW_REG_IP)2813 return true;2814 if (regNum == UNW_REG_SP)2815 return true;2816 if (regNum < 0)2817 return false;2818 if (regNum <= UNW_OR1K_R31)2819 return true;2820 if (regNum == UNW_OR1K_EPCR)2821 return true;2822 return false;2823}2824 2825inline uint32_t Registers_or1k::getRegister(int regNum) const {2826 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31)2827 return _registers.__r[regNum - UNW_OR1K_R0];2828 2829 switch (regNum) {2830 case UNW_REG_IP:2831 return _registers.__pc;2832 case UNW_REG_SP:2833 return _registers.__r[1];2834 case UNW_OR1K_EPCR:2835 return _registers.__epcr;2836 }2837 _LIBUNWIND_ABORT("unsupported or1k register");2838}2839 2840inline void Registers_or1k::setRegister(int regNum, uint32_t value) {2841 if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) {2842 _registers.__r[regNum - UNW_OR1K_R0] = value;2843 return;2844 }2845 2846 switch (regNum) {2847 case UNW_REG_IP:2848 _registers.__pc = value;2849 return;2850 case UNW_REG_SP:2851 _registers.__r[1] = value;2852 return;2853 case UNW_OR1K_EPCR:2854 _registers.__epcr = value;2855 return;2856 }2857 _LIBUNWIND_ABORT("unsupported or1k register");2858}2859 2860inline bool Registers_or1k::validFloatRegister(int /* regNum */) const {2861 return false;2862}2863 2864inline double Registers_or1k::getFloatRegister(int /* regNum */) const {2865 _LIBUNWIND_ABORT("or1k float support not implemented");2866}2867 2868inline void Registers_or1k::setFloatRegister(int /* regNum */,2869 double /* value */) {2870 _LIBUNWIND_ABORT("or1k float support not implemented");2871}2872 2873inline bool Registers_or1k::validVectorRegister(int /* regNum */) const {2874 return false;2875}2876 2877inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const {2878 _LIBUNWIND_ABORT("or1k vector support not implemented");2879}2880 2881inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) {2882 _LIBUNWIND_ABORT("or1k vector support not implemented");2883}2884 2885inline const char *Registers_or1k::getRegisterName(int regNum) {2886 switch (regNum) {2887 case UNW_OR1K_R0:2888 return "r0";2889 case UNW_OR1K_R1:2890 return "r1";2891 case UNW_OR1K_R2:2892 return "r2";2893 case UNW_OR1K_R3:2894 return "r3";2895 case UNW_OR1K_R4:2896 return "r4";2897 case UNW_OR1K_R5:2898 return "r5";2899 case UNW_OR1K_R6:2900 return "r6";2901 case UNW_OR1K_R7:2902 return "r7";2903 case UNW_OR1K_R8:2904 return "r8";2905 case UNW_OR1K_R9:2906 return "r9";2907 case UNW_OR1K_R10:2908 return "r10";2909 case UNW_OR1K_R11:2910 return "r11";2911 case UNW_OR1K_R12:2912 return "r12";2913 case UNW_OR1K_R13:2914 return "r13";2915 case UNW_OR1K_R14:2916 return "r14";2917 case UNW_OR1K_R15:2918 return "r15";2919 case UNW_OR1K_R16:2920 return "r16";2921 case UNW_OR1K_R17:2922 return "r17";2923 case UNW_OR1K_R18:2924 return "r18";2925 case UNW_OR1K_R19:2926 return "r19";2927 case UNW_OR1K_R20:2928 return "r20";2929 case UNW_OR1K_R21:2930 return "r21";2931 case UNW_OR1K_R22:2932 return "r22";2933 case UNW_OR1K_R23:2934 return "r23";2935 case UNW_OR1K_R24:2936 return "r24";2937 case UNW_OR1K_R25:2938 return "r25";2939 case UNW_OR1K_R26:2940 return "r26";2941 case UNW_OR1K_R27:2942 return "r27";2943 case UNW_OR1K_R28:2944 return "r28";2945 case UNW_OR1K_R29:2946 return "r29";2947 case UNW_OR1K_R30:2948 return "r30";2949 case UNW_OR1K_R31:2950 return "r31";2951 case UNW_OR1K_EPCR:2952 return "EPCR";2953 default:2954 return "unknown register";2955 }2956 2957}2958#endif // _LIBUNWIND_TARGET_OR1K2959 2960#if defined(_LIBUNWIND_TARGET_MIPS_O32)2961/// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS2962/// process.2963class _LIBUNWIND_HIDDEN Registers_mips_o32 {2964public:2965 Registers_mips_o32();2966 Registers_mips_o32(const void *registers);2967 2968 typedef uint32_t reg_t;2969 typedef uint32_t link_reg_t;2970 2971 bool validRegister(int num) const;2972 uint32_t getRegister(int num) const;2973 void setRegister(int num, uint32_t value);2974 bool validFloatRegister(int num) const;2975 double getFloatRegister(int num) const;2976 void setFloatRegister(int num, double value);2977 bool validVectorRegister(int num) const;2978 v128 getVectorRegister(int num) const;2979 void setVectorRegister(int num, v128 value);2980 static const char *getRegisterName(int num);2981 void jumpto();2982 static constexpr int lastDwarfRegNum() {2983 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;2984 }2985 static int getArch() { return REGISTERS_MIPS_O32; }2986 2987 uint32_t getSP() const { return _registers.__r[29]; }2988 void setSP(uint32_t value) { _registers.__r[29] = value; }2989 uint32_t getIP() const { return _registers.__pc; }2990 void setIP(uint32_t value) { _registers.__pc = value; }2991 2992private:2993 struct mips_o32_thread_state_t {2994 uint32_t __r[32];2995 uint32_t __pc;2996 uint32_t __hi;2997 uint32_t __lo;2998 };2999 3000 mips_o32_thread_state_t _registers;3001#ifdef __mips_hard_float3002 /// O32 with 32-bit floating point registers only uses half of this3003 /// space. However, using the same layout for 32-bit vs 64-bit3004 /// floating point registers results in a single context size for3005 /// O32 with hard float.3006 uint32_t _padding;3007 double _floats[32];3008#endif3009};3010 3011inline Registers_mips_o32::Registers_mips_o32(const void *registers) {3012 static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit),3013 "mips_o32 registers do not fit into unw_context_t");3014 memcpy(&_registers, static_cast<const uint8_t *>(registers),3015 sizeof(_registers));3016}3017 3018inline Registers_mips_o32::Registers_mips_o32() {3019 memset(&_registers, 0, sizeof(_registers));3020}3021 3022inline bool Registers_mips_o32::validRegister(int regNum) const {3023 if (regNum == UNW_REG_IP)3024 return true;3025 if (regNum == UNW_REG_SP)3026 return true;3027 if (regNum < 0)3028 return false;3029 if (regNum <= UNW_MIPS_R31)3030 return true;3031#if __mips_isa_rev < 63032 if (regNum == UNW_MIPS_HI)3033 return true;3034 if (regNum == UNW_MIPS_LO)3035 return true;3036#endif3037#if defined(__mips_hard_float) && __mips_fpr == 323038 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)3039 return true;3040#endif3041 // FIXME: DSP accumulator registers, MSA registers3042 return false;3043}3044 3045inline uint32_t Registers_mips_o32::getRegister(int regNum) const {3046 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)3047 return _registers.__r[regNum - UNW_MIPS_R0];3048#if defined(__mips_hard_float) && __mips_fpr == 323049 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {3050 uint32_t *p;3051 3052 if (regNum % 2 == 0)3053 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];3054 else3055 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;3056 return *p;3057 }3058#endif3059 3060 switch (regNum) {3061 case UNW_REG_IP:3062 return _registers.__pc;3063 case UNW_REG_SP:3064 return _registers.__r[29];3065#if __mips_isa_rev < 63066 case UNW_MIPS_HI:3067 return _registers.__hi;3068 case UNW_MIPS_LO:3069 return _registers.__lo;3070#endif3071 }3072 _LIBUNWIND_ABORT("unsupported mips_o32 register");3073}3074 3075inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {3076 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {3077 _registers.__r[regNum - UNW_MIPS_R0] = value;3078 return;3079 }3080#if defined(__mips_hard_float) && __mips_fpr == 323081 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) {3082 uint32_t *p;3083 3084 if (regNum % 2 == 0)3085 p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0];3086 else3087 p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1;3088 *p = value;3089 return;3090 }3091#endif3092 3093 switch (regNum) {3094 case UNW_REG_IP:3095 _registers.__pc = value;3096 return;3097 case UNW_REG_SP:3098 _registers.__r[29] = value;3099 return;3100#if __mips_isa_rev < 63101 case UNW_MIPS_HI:3102 _registers.__hi = value;3103 return;3104 case UNW_MIPS_LO:3105 _registers.__lo = value;3106#endif3107 return;3108 }3109 _LIBUNWIND_ABORT("unsupported mips_o32 register");3110}3111 3112inline bool Registers_mips_o32::validFloatRegister(int regNum) const {3113#if defined(__mips_hard_float) && __mips_fpr == 643114 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)3115 return true;3116#else3117 (void)regNum;3118#endif3119 return false;3120}3121 3122inline double Registers_mips_o32::getFloatRegister(int regNum) const {3123#if defined(__mips_hard_float) && __mips_fpr == 643124 assert(validFloatRegister(regNum));3125 return _floats[regNum - UNW_MIPS_F0];3126#else3127 (void)regNum;3128 _LIBUNWIND_ABORT("mips_o32 float support not implemented");3129#endif3130}3131 3132inline void Registers_mips_o32::setFloatRegister(int regNum,3133 double value) {3134#if defined(__mips_hard_float) && __mips_fpr == 643135 assert(validFloatRegister(regNum));3136 _floats[regNum - UNW_MIPS_F0] = value;3137#else3138 (void)regNum;3139 (void)value;3140 _LIBUNWIND_ABORT("mips_o32 float support not implemented");3141#endif3142}3143 3144inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const {3145 return false;3146}3147 3148inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const {3149 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");3150}3151 3152inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) {3153 _LIBUNWIND_ABORT("mips_o32 vector support not implemented");3154}3155 3156inline const char *Registers_mips_o32::getRegisterName(int regNum) {3157 switch (regNum) {3158 case UNW_MIPS_R0:3159 return "$0";3160 case UNW_MIPS_R1:3161 return "$1";3162 case UNW_MIPS_R2:3163 return "$2";3164 case UNW_MIPS_R3:3165 return "$3";3166 case UNW_MIPS_R4:3167 return "$4";3168 case UNW_MIPS_R5:3169 return "$5";3170 case UNW_MIPS_R6:3171 return "$6";3172 case UNW_MIPS_R7:3173 return "$7";3174 case UNW_MIPS_R8:3175 return "$8";3176 case UNW_MIPS_R9:3177 return "$9";3178 case UNW_MIPS_R10:3179 return "$10";3180 case UNW_MIPS_R11:3181 return "$11";3182 case UNW_MIPS_R12:3183 return "$12";3184 case UNW_MIPS_R13:3185 return "$13";3186 case UNW_MIPS_R14:3187 return "$14";3188 case UNW_MIPS_R15:3189 return "$15";3190 case UNW_MIPS_R16:3191 return "$16";3192 case UNW_MIPS_R17:3193 return "$17";3194 case UNW_MIPS_R18:3195 return "$18";3196 case UNW_MIPS_R19:3197 return "$19";3198 case UNW_MIPS_R20:3199 return "$20";3200 case UNW_MIPS_R21:3201 return "$21";3202 case UNW_MIPS_R22:3203 return "$22";3204 case UNW_MIPS_R23:3205 return "$23";3206 case UNW_MIPS_R24:3207 return "$24";3208 case UNW_MIPS_R25:3209 return "$25";3210 case UNW_MIPS_R26:3211 return "$26";3212 case UNW_MIPS_R27:3213 return "$27";3214 case UNW_MIPS_R28:3215 return "$28";3216 case UNW_MIPS_R29:3217 return "$29";3218 case UNW_MIPS_R30:3219 return "$30";3220 case UNW_MIPS_R31:3221 return "$31";3222 case UNW_MIPS_F0:3223 return "$f0";3224 case UNW_MIPS_F1:3225 return "$f1";3226 case UNW_MIPS_F2:3227 return "$f2";3228 case UNW_MIPS_F3:3229 return "$f3";3230 case UNW_MIPS_F4:3231 return "$f4";3232 case UNW_MIPS_F5:3233 return "$f5";3234 case UNW_MIPS_F6:3235 return "$f6";3236 case UNW_MIPS_F7:3237 return "$f7";3238 case UNW_MIPS_F8:3239 return "$f8";3240 case UNW_MIPS_F9:3241 return "$f9";3242 case UNW_MIPS_F10:3243 return "$f10";3244 case UNW_MIPS_F11:3245 return "$f11";3246 case UNW_MIPS_F12:3247 return "$f12";3248 case UNW_MIPS_F13:3249 return "$f13";3250 case UNW_MIPS_F14:3251 return "$f14";3252 case UNW_MIPS_F15:3253 return "$f15";3254 case UNW_MIPS_F16:3255 return "$f16";3256 case UNW_MIPS_F17:3257 return "$f17";3258 case UNW_MIPS_F18:3259 return "$f18";3260 case UNW_MIPS_F19:3261 return "$f19";3262 case UNW_MIPS_F20:3263 return "$f20";3264 case UNW_MIPS_F21:3265 return "$f21";3266 case UNW_MIPS_F22:3267 return "$f22";3268 case UNW_MIPS_F23:3269 return "$f23";3270 case UNW_MIPS_F24:3271 return "$f24";3272 case UNW_MIPS_F25:3273 return "$f25";3274 case UNW_MIPS_F26:3275 return "$f26";3276 case UNW_MIPS_F27:3277 return "$f27";3278 case UNW_MIPS_F28:3279 return "$f28";3280 case UNW_MIPS_F29:3281 return "$f29";3282 case UNW_MIPS_F30:3283 return "$f30";3284 case UNW_MIPS_F31:3285 return "$f31";3286#if __mips_isa_rev < 63287 case UNW_MIPS_HI:3288 return "$hi";3289 case UNW_MIPS_LO:3290 return "$lo";3291#endif3292 default:3293 return "unknown register";3294 }3295}3296#endif // _LIBUNWIND_TARGET_MIPS_O323297 3298#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)3299/// Registers_mips_newabi holds the register state of a thread in a3300/// MIPS process using NEWABI (the N32 or N64 ABIs).3301class _LIBUNWIND_HIDDEN Registers_mips_newabi {3302public:3303 Registers_mips_newabi();3304 Registers_mips_newabi(const void *registers);3305 3306 typedef uint64_t reg_t;3307 typedef uint64_t link_reg_t;3308 3309 bool validRegister(int num) const;3310 uint64_t getRegister(int num) const;3311 void setRegister(int num, uint64_t value);3312 bool validFloatRegister(int num) const;3313 double getFloatRegister(int num) const;3314 void setFloatRegister(int num, double value);3315 bool validVectorRegister(int num) const;3316 v128 getVectorRegister(int num) const;3317 void setVectorRegister(int num, v128 value);3318 static const char *getRegisterName(int num);3319 void jumpto();3320 static constexpr int lastDwarfRegNum() {3321 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;3322 }3323 static int getArch() { return REGISTERS_MIPS_NEWABI; }3324 3325 uint64_t getSP() const { return _registers.__r[29]; }3326 void setSP(uint64_t value) { _registers.__r[29] = value; }3327 uint64_t getIP() const { return _registers.__pc; }3328 void setIP(uint64_t value) { _registers.__pc = value; }3329 3330private:3331 struct mips_newabi_thread_state_t {3332 uint64_t __r[32];3333 uint64_t __pc;3334 uint64_t __hi;3335 uint64_t __lo;3336 };3337 3338 mips_newabi_thread_state_t _registers;3339#ifdef __mips_hard_float3340 double _floats[32];3341#endif3342};3343 3344inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) {3345 static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit),3346 "mips_newabi registers do not fit into unw_context_t");3347 memcpy(&_registers, static_cast<const uint8_t *>(registers),3348 sizeof(_registers));3349}3350 3351inline Registers_mips_newabi::Registers_mips_newabi() {3352 memset(&_registers, 0, sizeof(_registers));3353}3354 3355inline bool Registers_mips_newabi::validRegister(int regNum) const {3356 if (regNum == UNW_REG_IP)3357 return true;3358 if (regNum == UNW_REG_SP)3359 return true;3360 if (regNum < 0)3361 return false;3362 if (regNum <= UNW_MIPS_R31)3363 return true;3364#if __mips_isa_rev < 63365 if (regNum == UNW_MIPS_HI)3366 return true;3367 if (regNum == UNW_MIPS_LO)3368 return true;3369#endif3370 // FIXME: Hard float, DSP accumulator registers, MSA registers3371 return false;3372}3373 3374inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {3375 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31)3376 return _registers.__r[regNum - UNW_MIPS_R0];3377 3378 switch (regNum) {3379 case UNW_REG_IP:3380 return _registers.__pc;3381 case UNW_REG_SP:3382 return _registers.__r[29];3383#if __mips_isa_rev < 63384 case UNW_MIPS_HI:3385 return _registers.__hi;3386 case UNW_MIPS_LO:3387 return _registers.__lo;3388#endif3389 }3390 _LIBUNWIND_ABORT("unsupported mips_newabi register");3391}3392 3393inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {3394 if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) {3395 _registers.__r[regNum - UNW_MIPS_R0] = value;3396 return;3397 }3398 3399 switch (regNum) {3400 case UNW_REG_IP:3401 _registers.__pc = value;3402 return;3403 case UNW_REG_SP:3404 _registers.__r[29] = value;3405 return;3406#if __mips_isa_rev < 63407 case UNW_MIPS_HI:3408 _registers.__hi = value;3409 return;3410 case UNW_MIPS_LO:3411 _registers.__lo = value;3412 return;3413#endif3414 }3415 _LIBUNWIND_ABORT("unsupported mips_newabi register");3416}3417 3418inline bool Registers_mips_newabi::validFloatRegister(int regNum) const {3419#ifdef __mips_hard_float3420 if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31)3421 return true;3422#else3423 (void)regNum;3424#endif3425 return false;3426}3427 3428inline double Registers_mips_newabi::getFloatRegister(int regNum) const {3429#ifdef __mips_hard_float3430 assert(validFloatRegister(regNum));3431 return _floats[regNum - UNW_MIPS_F0];3432#else3433 (void)regNum;3434 _LIBUNWIND_ABORT("mips_newabi float support not implemented");3435#endif3436}3437 3438inline void Registers_mips_newabi::setFloatRegister(int regNum,3439 double value) {3440#ifdef __mips_hard_float3441 assert(validFloatRegister(regNum));3442 _floats[regNum - UNW_MIPS_F0] = value;3443#else3444 (void)regNum;3445 (void)value;3446 _LIBUNWIND_ABORT("mips_newabi float support not implemented");3447#endif3448}3449 3450inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const {3451 return false;3452}3453 3454inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const {3455 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");3456}3457 3458inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) {3459 _LIBUNWIND_ABORT("mips_newabi vector support not implemented");3460}3461 3462inline const char *Registers_mips_newabi::getRegisterName(int regNum) {3463 switch (regNum) {3464 case UNW_MIPS_R0:3465 return "$0";3466 case UNW_MIPS_R1:3467 return "$1";3468 case UNW_MIPS_R2:3469 return "$2";3470 case UNW_MIPS_R3:3471 return "$3";3472 case UNW_MIPS_R4:3473 return "$4";3474 case UNW_MIPS_R5:3475 return "$5";3476 case UNW_MIPS_R6:3477 return "$6";3478 case UNW_MIPS_R7:3479 return "$7";3480 case UNW_MIPS_R8:3481 return "$8";3482 case UNW_MIPS_R9:3483 return "$9";3484 case UNW_MIPS_R10:3485 return "$10";3486 case UNW_MIPS_R11:3487 return "$11";3488 case UNW_MIPS_R12:3489 return "$12";3490 case UNW_MIPS_R13:3491 return "$13";3492 case UNW_MIPS_R14:3493 return "$14";3494 case UNW_MIPS_R15:3495 return "$15";3496 case UNW_MIPS_R16:3497 return "$16";3498 case UNW_MIPS_R17:3499 return "$17";3500 case UNW_MIPS_R18:3501 return "$18";3502 case UNW_MIPS_R19:3503 return "$19";3504 case UNW_MIPS_R20:3505 return "$20";3506 case UNW_MIPS_R21:3507 return "$21";3508 case UNW_MIPS_R22:3509 return "$22";3510 case UNW_MIPS_R23:3511 return "$23";3512 case UNW_MIPS_R24:3513 return "$24";3514 case UNW_MIPS_R25:3515 return "$25";3516 case UNW_MIPS_R26:3517 return "$26";3518 case UNW_MIPS_R27:3519 return "$27";3520 case UNW_MIPS_R28:3521 return "$28";3522 case UNW_MIPS_R29:3523 return "$29";3524 case UNW_MIPS_R30:3525 return "$30";3526 case UNW_MIPS_R31:3527 return "$31";3528 case UNW_MIPS_F0:3529 return "$f0";3530 case UNW_MIPS_F1:3531 return "$f1";3532 case UNW_MIPS_F2:3533 return "$f2";3534 case UNW_MIPS_F3:3535 return "$f3";3536 case UNW_MIPS_F4:3537 return "$f4";3538 case UNW_MIPS_F5:3539 return "$f5";3540 case UNW_MIPS_F6:3541 return "$f6";3542 case UNW_MIPS_F7:3543 return "$f7";3544 case UNW_MIPS_F8:3545 return "$f8";3546 case UNW_MIPS_F9:3547 return "$f9";3548 case UNW_MIPS_F10:3549 return "$f10";3550 case UNW_MIPS_F11:3551 return "$f11";3552 case UNW_MIPS_F12:3553 return "$f12";3554 case UNW_MIPS_F13:3555 return "$f13";3556 case UNW_MIPS_F14:3557 return "$f14";3558 case UNW_MIPS_F15:3559 return "$f15";3560 case UNW_MIPS_F16:3561 return "$f16";3562 case UNW_MIPS_F17:3563 return "$f17";3564 case UNW_MIPS_F18:3565 return "$f18";3566 case UNW_MIPS_F19:3567 return "$f19";3568 case UNW_MIPS_F20:3569 return "$f20";3570 case UNW_MIPS_F21:3571 return "$f21";3572 case UNW_MIPS_F22:3573 return "$f22";3574 case UNW_MIPS_F23:3575 return "$f23";3576 case UNW_MIPS_F24:3577 return "$f24";3578 case UNW_MIPS_F25:3579 return "$f25";3580 case UNW_MIPS_F26:3581 return "$f26";3582 case UNW_MIPS_F27:3583 return "$f27";3584 case UNW_MIPS_F28:3585 return "$f28";3586 case UNW_MIPS_F29:3587 return "$f29";3588 case UNW_MIPS_F30:3589 return "$f30";3590 case UNW_MIPS_F31:3591 return "$f31";3592#if __mips_isa_rev < 63593 case UNW_MIPS_HI:3594 return "$hi";3595 case UNW_MIPS_LO:3596 return "$lo";3597#endif3598 default:3599 return "unknown register";3600 }3601}3602#endif // _LIBUNWIND_TARGET_MIPS_NEWABI3603 3604#if defined(_LIBUNWIND_TARGET_SPARC)3605/// Registers_sparc holds the register state of a thread in a 32-bit Sparc3606/// process.3607class _LIBUNWIND_HIDDEN Registers_sparc {3608public:3609 Registers_sparc();3610 Registers_sparc(const void *registers);3611 3612 typedef uint32_t reg_t;3613 typedef uint32_t link_reg_t;3614 3615 bool validRegister(int num) const;3616 uint32_t getRegister(int num) const;3617 void setRegister(int num, uint32_t value);3618 bool validFloatRegister(int num) const;3619 double getFloatRegister(int num) const;3620 void setFloatRegister(int num, double value);3621 bool validVectorRegister(int num) const;3622 v128 getVectorRegister(int num) const;3623 void setVectorRegister(int num, v128 value);3624 static const char *getRegisterName(int num);3625 void jumpto();3626 static constexpr int lastDwarfRegNum() {3627 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;3628 }3629 static int getArch() { return REGISTERS_SPARC; }3630 3631 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }3632 void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; }3633 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }3634 void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; }3635 3636private:3637 struct sparc_thread_state_t {3638 unsigned int __regs[32];3639 };3640 3641 sparc_thread_state_t _registers;3642};3643 3644inline Registers_sparc::Registers_sparc(const void *registers) {3645 static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit),3646 "sparc registers do not fit into unw_context_t");3647 memcpy(&_registers, static_cast<const uint8_t *>(registers),3648 sizeof(_registers));3649}3650 3651inline Registers_sparc::Registers_sparc() {3652 memset(&_registers, 0, sizeof(_registers));3653}3654 3655inline bool Registers_sparc::validRegister(int regNum) const {3656 if (regNum == UNW_REG_IP)3657 return true;3658 if (regNum == UNW_REG_SP)3659 return true;3660 if (regNum < 0)3661 return false;3662 if (regNum <= UNW_SPARC_I7)3663 return true;3664 return false;3665}3666 3667inline uint32_t Registers_sparc::getRegister(int regNum) const {3668 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {3669 return _registers.__regs[regNum];3670 }3671 3672 switch (regNum) {3673 case UNW_REG_IP:3674 return _registers.__regs[UNW_SPARC_O7];3675 case UNW_REG_SP:3676 return _registers.__regs[UNW_SPARC_O6];3677 }3678 _LIBUNWIND_ABORT("unsupported sparc register");3679}3680 3681inline void Registers_sparc::setRegister(int regNum, uint32_t value) {3682 if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) {3683 _registers.__regs[regNum] = value;3684 return;3685 }3686 3687 switch (regNum) {3688 case UNW_REG_IP:3689 _registers.__regs[UNW_SPARC_O7] = value;3690 return;3691 case UNW_REG_SP:3692 _registers.__regs[UNW_SPARC_O6] = value;3693 return;3694 }3695 _LIBUNWIND_ABORT("unsupported sparc register");3696}3697 3698inline bool Registers_sparc::validFloatRegister(int) const { return false; }3699 3700inline double Registers_sparc::getFloatRegister(int) const {3701 _LIBUNWIND_ABORT("no Sparc float registers");3702}3703 3704inline void Registers_sparc::setFloatRegister(int, double) {3705 _LIBUNWIND_ABORT("no Sparc float registers");3706}3707 3708inline bool Registers_sparc::validVectorRegister(int) const { return false; }3709 3710inline v128 Registers_sparc::getVectorRegister(int) const {3711 _LIBUNWIND_ABORT("no Sparc vector registers");3712}3713 3714inline void Registers_sparc::setVectorRegister(int, v128) {3715 _LIBUNWIND_ABORT("no Sparc vector registers");3716}3717 3718inline const char *Registers_sparc::getRegisterName(int regNum) {3719 switch (regNum) {3720 case UNW_REG_IP:3721 return "pc";3722 case UNW_SPARC_G0:3723 return "g0";3724 case UNW_SPARC_G1:3725 return "g1";3726 case UNW_SPARC_G2:3727 return "g2";3728 case UNW_SPARC_G3:3729 return "g3";3730 case UNW_SPARC_G4:3731 return "g4";3732 case UNW_SPARC_G5:3733 return "g5";3734 case UNW_SPARC_G6:3735 return "g6";3736 case UNW_SPARC_G7:3737 return "g7";3738 case UNW_SPARC_O0:3739 return "o0";3740 case UNW_SPARC_O1:3741 return "o1";3742 case UNW_SPARC_O2:3743 return "o2";3744 case UNW_SPARC_O3:3745 return "o3";3746 case UNW_SPARC_O4:3747 return "o4";3748 case UNW_SPARC_O5:3749 return "o5";3750 case UNW_REG_SP:3751 case UNW_SPARC_O6:3752 return "sp";3753 case UNW_SPARC_O7:3754 return "o7";3755 case UNW_SPARC_L0:3756 return "l0";3757 case UNW_SPARC_L1:3758 return "l1";3759 case UNW_SPARC_L2:3760 return "l2";3761 case UNW_SPARC_L3:3762 return "l3";3763 case UNW_SPARC_L4:3764 return "l4";3765 case UNW_SPARC_L5:3766 return "l5";3767 case UNW_SPARC_L6:3768 return "l6";3769 case UNW_SPARC_L7:3770 return "l7";3771 case UNW_SPARC_I0:3772 return "i0";3773 case UNW_SPARC_I1:3774 return "i1";3775 case UNW_SPARC_I2:3776 return "i2";3777 case UNW_SPARC_I3:3778 return "i3";3779 case UNW_SPARC_I4:3780 return "i4";3781 case UNW_SPARC_I5:3782 return "i5";3783 case UNW_SPARC_I6:3784 return "fp";3785 case UNW_SPARC_I7:3786 return "i7";3787 default:3788 return "unknown register";3789 }3790}3791#endif // _LIBUNWIND_TARGET_SPARC3792 3793#if defined(_LIBUNWIND_TARGET_SPARC64)3794/// Registers_sparc64 holds the register state of a thread in a 64-bit3795/// sparc process.3796class _LIBUNWIND_HIDDEN Registers_sparc64 {3797public:3798 Registers_sparc64() = default;3799 Registers_sparc64(const void *registers);3800 3801 typedef uint64_t reg_t;3802 typedef uint64_t link_reg_t;3803 3804 bool validRegister(int num) const;3805 uint64_t getRegister(int num) const;3806 void setRegister(int num, uint64_t value);3807 bool validFloatRegister(int num) const;3808 double getFloatRegister(int num) const;3809 void setFloatRegister(int num, double value);3810 bool validVectorRegister(int num) const;3811 v128 getVectorRegister(int num) const;3812 void setVectorRegister(int num, v128 value);3813 const char *getRegisterName(int num);3814 void jumpto();3815 static constexpr int lastDwarfRegNum() {3816 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;3817 }3818 static int getArch() { return REGISTERS_SPARC64; }3819 3820 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; }3821 void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; }3822 uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; }3823 void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; }3824 uint64_t getWCookie() const { return _wcookie; }3825 3826private:3827 struct sparc64_thread_state_t {3828 uint64_t __regs[32];3829 };3830 3831 sparc64_thread_state_t _registers{};3832 uint64_t _wcookie = 0;3833};3834 3835inline Registers_sparc64::Registers_sparc64(const void *registers) {3836 static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit),3837 "sparc64 registers do not fit into unw_context_t");3838 memcpy(&_registers, registers, sizeof(_registers));3839 memcpy(&_wcookie,3840 static_cast<const uint8_t *>(registers) + sizeof(_registers),3841 sizeof(_wcookie));3842}3843 3844inline bool Registers_sparc64::validRegister(int regNum) const {3845 if (regNum == UNW_REG_IP)3846 return true;3847 if (regNum == UNW_REG_SP)3848 return true;3849 if (regNum < 0)3850 return false;3851 if (regNum <= UNW_SPARC_I7)3852 return true;3853 return false;3854}3855 3856inline uint64_t Registers_sparc64::getRegister(int regNum) const {3857 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7)3858 return _registers.__regs[regNum];3859 3860 switch (regNum) {3861 case UNW_REG_IP:3862 return _registers.__regs[UNW_SPARC_O7];3863 case UNW_REG_SP:3864 return _registers.__regs[UNW_SPARC_O6] + 2047;3865 }3866 _LIBUNWIND_ABORT("unsupported sparc64 register");3867}3868 3869inline void Registers_sparc64::setRegister(int regNum, uint64_t value) {3870 if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) {3871 _registers.__regs[regNum] = value;3872 return;3873 }3874 3875 switch (regNum) {3876 case UNW_REG_IP:3877 _registers.__regs[UNW_SPARC_O7] = value;3878 return;3879 case UNW_REG_SP:3880 _registers.__regs[UNW_SPARC_O6] = value - 2047;3881 return;3882 }3883 _LIBUNWIND_ABORT("unsupported sparc64 register");3884}3885 3886inline bool Registers_sparc64::validFloatRegister(int) const { return false; }3887 3888inline double Registers_sparc64::getFloatRegister(int) const {3889 _LIBUNWIND_ABORT("no sparc64 float registers");3890}3891 3892inline void Registers_sparc64::setFloatRegister(int, double) {3893 _LIBUNWIND_ABORT("no sparc64 float registers");3894}3895 3896inline bool Registers_sparc64::validVectorRegister(int) const { return false; }3897 3898inline v128 Registers_sparc64::getVectorRegister(int) const {3899 _LIBUNWIND_ABORT("no sparc64 vector registers");3900}3901 3902inline void Registers_sparc64::setVectorRegister(int, v128) {3903 _LIBUNWIND_ABORT("no sparc64 vector registers");3904}3905 3906inline const char *Registers_sparc64::getRegisterName(int regNum) {3907 switch (regNum) {3908 case UNW_REG_IP:3909 return "pc";3910 case UNW_SPARC_G0:3911 return "g0";3912 case UNW_SPARC_G1:3913 return "g1";3914 case UNW_SPARC_G2:3915 return "g2";3916 case UNW_SPARC_G3:3917 return "g3";3918 case UNW_SPARC_G4:3919 return "g4";3920 case UNW_SPARC_G5:3921 return "g5";3922 case UNW_SPARC_G6:3923 return "g6";3924 case UNW_SPARC_G7:3925 return "g7";3926 case UNW_SPARC_O0:3927 return "o0";3928 case UNW_SPARC_O1:3929 return "o1";3930 case UNW_SPARC_O2:3931 return "o2";3932 case UNW_SPARC_O3:3933 return "o3";3934 case UNW_SPARC_O4:3935 return "o4";3936 case UNW_SPARC_O5:3937 return "o5";3938 case UNW_REG_SP:3939 case UNW_SPARC_O6:3940 return "o6";3941 case UNW_SPARC_O7:3942 return "o7";3943 case UNW_SPARC_L0:3944 return "l0";3945 case UNW_SPARC_L1:3946 return "l1";3947 case UNW_SPARC_L2:3948 return "l2";3949 case UNW_SPARC_L3:3950 return "l3";3951 case UNW_SPARC_L4:3952 return "l4";3953 case UNW_SPARC_L5:3954 return "l5";3955 case UNW_SPARC_L6:3956 return "l6";3957 case UNW_SPARC_L7:3958 return "l7";3959 case UNW_SPARC_I0:3960 return "i0";3961 case UNW_SPARC_I1:3962 return "i1";3963 case UNW_SPARC_I2:3964 return "i2";3965 case UNW_SPARC_I3:3966 return "i3";3967 case UNW_SPARC_I4:3968 return "i4";3969 case UNW_SPARC_I5:3970 return "i5";3971 case UNW_SPARC_I6:3972 return "i6";3973 case UNW_SPARC_I7:3974 return "i7";3975 default:3976 return "unknown register";3977 }3978}3979#endif // _LIBUNWIND_TARGET_SPARC643980 3981#if defined(_LIBUNWIND_TARGET_HEXAGON)3982/// Registers_hexagon holds the register state of a thread in a Hexagon QDSP63983/// process.3984class _LIBUNWIND_HIDDEN Registers_hexagon {3985public:3986 Registers_hexagon();3987 Registers_hexagon(const void *registers);3988 3989 typedef uint32_t reg_t;3990 typedef uint32_t link_reg_t;3991 3992 bool validRegister(int num) const;3993 uint32_t getRegister(int num) const;3994 void setRegister(int num, uint32_t value);3995 bool validFloatRegister(int num) const;3996 double getFloatRegister(int num) const;3997 void setFloatRegister(int num, double value);3998 bool validVectorRegister(int num) const;3999 v128 getVectorRegister(int num) const;4000 void setVectorRegister(int num, v128 value);4001 const char *getRegisterName(int num);4002 void jumpto();4003 static constexpr int lastDwarfRegNum() {4004 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;4005 }4006 static int getArch() { return REGISTERS_HEXAGON; }4007 4008 uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }4009 void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; }4010 uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; }4011 void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; }4012 4013private:4014 struct hexagon_thread_state_t {4015 unsigned int __r[35];4016 };4017 4018 hexagon_thread_state_t _registers;4019};4020 4021inline Registers_hexagon::Registers_hexagon(const void *registers) {4022 static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit),4023 "hexagon registers do not fit into unw_context_t");4024 memcpy(&_registers, static_cast<const uint8_t *>(registers),4025 sizeof(_registers));4026}4027 4028inline Registers_hexagon::Registers_hexagon() {4029 memset(&_registers, 0, sizeof(_registers));4030}4031 4032inline bool Registers_hexagon::validRegister(int regNum) const {4033 if (regNum <= UNW_HEXAGON_R31)4034 return true;4035 return false;4036}4037 4038inline uint32_t Registers_hexagon::getRegister(int regNum) const {4039 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31)4040 return _registers.__r[regNum - UNW_HEXAGON_R0];4041 4042 switch (regNum) {4043 case UNW_REG_IP:4044 return _registers.__r[UNW_HEXAGON_PC];4045 case UNW_REG_SP:4046 return _registers.__r[UNW_HEXAGON_R29];4047 }4048 _LIBUNWIND_ABORT("unsupported hexagon register");4049}4050 4051inline void Registers_hexagon::setRegister(int regNum, uint32_t value) {4052 if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) {4053 _registers.__r[regNum - UNW_HEXAGON_R0] = value;4054 return;4055 }4056 4057 switch (regNum) {4058 case UNW_REG_IP:4059 _registers.__r[UNW_HEXAGON_PC] = value;4060 return;4061 case UNW_REG_SP:4062 _registers.__r[UNW_HEXAGON_R29] = value;4063 return;4064 }4065 _LIBUNWIND_ABORT("unsupported hexagon register");4066}4067 4068inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const {4069 return false;4070}4071 4072inline double Registers_hexagon::getFloatRegister(int /* regNum */) const {4073 _LIBUNWIND_ABORT("hexagon float support not implemented");4074}4075 4076inline void Registers_hexagon::setFloatRegister(int /* regNum */,4077 double /* value */) {4078 _LIBUNWIND_ABORT("hexagon float support not implemented");4079}4080 4081inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const {4082 return false;4083}4084 4085inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const {4086 _LIBUNWIND_ABORT("hexagon vector support not implemented");4087}4088 4089inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) {4090 _LIBUNWIND_ABORT("hexagon vector support not implemented");4091}4092 4093inline const char *Registers_hexagon::getRegisterName(int regNum) {4094 switch (regNum) {4095 case UNW_HEXAGON_R0:4096 return "r0";4097 case UNW_HEXAGON_R1:4098 return "r1";4099 case UNW_HEXAGON_R2:4100 return "r2";4101 case UNW_HEXAGON_R3:4102 return "r3";4103 case UNW_HEXAGON_R4:4104 return "r4";4105 case UNW_HEXAGON_R5:4106 return "r5";4107 case UNW_HEXAGON_R6:4108 return "r6";4109 case UNW_HEXAGON_R7:4110 return "r7";4111 case UNW_HEXAGON_R8:4112 return "r8";4113 case UNW_HEXAGON_R9:4114 return "r9";4115 case UNW_HEXAGON_R10:4116 return "r10";4117 case UNW_HEXAGON_R11:4118 return "r11";4119 case UNW_HEXAGON_R12:4120 return "r12";4121 case UNW_HEXAGON_R13:4122 return "r13";4123 case UNW_HEXAGON_R14:4124 return "r14";4125 case UNW_HEXAGON_R15:4126 return "r15";4127 case UNW_HEXAGON_R16:4128 return "r16";4129 case UNW_HEXAGON_R17:4130 return "r17";4131 case UNW_HEXAGON_R18:4132 return "r18";4133 case UNW_HEXAGON_R19:4134 return "r19";4135 case UNW_HEXAGON_R20:4136 return "r20";4137 case UNW_HEXAGON_R21:4138 return "r21";4139 case UNW_HEXAGON_R22:4140 return "r22";4141 case UNW_HEXAGON_R23:4142 return "r23";4143 case UNW_HEXAGON_R24:4144 return "r24";4145 case UNW_HEXAGON_R25:4146 return "r25";4147 case UNW_HEXAGON_R26:4148 return "r26";4149 case UNW_HEXAGON_R27:4150 return "r27";4151 case UNW_HEXAGON_R28:4152 return "r28";4153 case UNW_HEXAGON_R29:4154 return "r29";4155 case UNW_HEXAGON_R30:4156 return "r30";4157 case UNW_HEXAGON_R31:4158 return "r31";4159 default:4160 return "unknown register";4161 }4162 4163}4164#endif // _LIBUNWIND_TARGET_HEXAGON4165 4166 4167#if defined(_LIBUNWIND_TARGET_RISCV)4168/// Registers_riscv holds the register state of a thread in a RISC-V4169/// process.4170 4171// This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled.4172# ifdef __riscv4173# if __riscv_xlen == 324174typedef uint32_t reg_t;4175# elif __riscv_xlen == 644176typedef uint64_t reg_t;4177# else4178# error "Unsupported __riscv_xlen"4179# endif4180 4181# if defined(__riscv_flen)4182# if __riscv_flen == 644183typedef double fp_t;4184# elif __riscv_flen == 324185typedef float fp_t;4186# else4187# error "Unsupported __riscv_flen"4188# endif4189# else4190// This is just for suppressing undeclared error of fp_t.4191typedef double fp_t;4192# endif4193# else4194// Use Max possible width when cross unwinding4195typedef uint64_t reg_t;4196typedef double fp_t;4197# define __riscv_xlen 644198# define __riscv_flen 644199#endif4200 4201/// Registers_riscv holds the register state of a thread.4202class _LIBUNWIND_HIDDEN Registers_riscv {4203public:4204 Registers_riscv();4205 Registers_riscv(const void *registers);4206 4207 typedef ::libunwind::reg_t reg_t;4208 typedef ::libunwind::reg_t link_reg_t;4209 4210 bool validRegister(int num) const;4211 reg_t getRegister(int num) const;4212 void setRegister(int num, reg_t value);4213 bool validFloatRegister(int num) const;4214 fp_t getFloatRegister(int num) const;4215 void setFloatRegister(int num, fp_t value);4216 bool validVectorRegister(int num) const;4217 v128 getVectorRegister(int num) const;4218 void setVectorRegister(int num, v128 value);4219 static const char *getRegisterName(int num);4220 void jumpto();4221 static constexpr int lastDwarfRegNum() {4222 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;4223 }4224 static int getArch() { return REGISTERS_RISCV; }4225 4226 reg_t getSP() const { return _registers[2]; }4227 void setSP(reg_t value) { _registers[2] = value; }4228 reg_t getIP() const { return _registers[0]; }4229 void setIP(reg_t value) { _registers[0] = value; }4230 4231private:4232 // _registers[0] holds the pc4233 reg_t _registers[32];4234# if defined(__riscv_flen)4235 fp_t _floats[32];4236# endif4237};4238 4239inline Registers_riscv::Registers_riscv(const void *registers) {4240 static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit),4241 "riscv registers do not fit into unw_context_t");4242 memcpy(&_registers, registers, sizeof(_registers));4243# if __riscv_xlen == 324244 static_assert(sizeof(_registers) == 0x80,4245 "expected float registers to be at offset 128");4246# elif __riscv_xlen == 644247 static_assert(sizeof(_registers) == 0x100,4248 "expected float registers to be at offset 256");4249# else4250# error "Unexpected float registers."4251# endif4252 4253# if defined(__riscv_flen)4254 memcpy(_floats,4255 static_cast<const uint8_t *>(registers) + sizeof(_registers),4256 sizeof(_floats));4257# endif4258}4259 4260inline Registers_riscv::Registers_riscv() {4261 memset(&_registers, 0, sizeof(_registers));4262# if defined(__riscv_flen)4263 memset(&_floats, 0, sizeof(_floats));4264# endif4265}4266 4267inline bool Registers_riscv::validRegister(int regNum) const {4268 if (regNum == UNW_REG_IP)4269 return true;4270 if (regNum == UNW_REG_SP)4271 return true;4272 if (regNum < 0)4273 return false;4274 if (regNum == UNW_RISCV_VLENB)4275 return true;4276 if (regNum > UNW_RISCV_F31)4277 return false;4278 return true;4279}4280 4281inline reg_t Registers_riscv::getRegister(int regNum) const {4282 if (regNum == UNW_REG_IP)4283 return _registers[0];4284 if (regNum == UNW_REG_SP)4285 return _registers[2];4286 if (regNum == UNW_RISCV_X0)4287 return 0;4288 if ((regNum > 0) && (regNum < 32))4289 return _registers[regNum];4290 if (regNum == UNW_RISCV_VLENB) {4291 reg_t vlenb;4292 __asm__ volatile("csrr %0, 0xC22" : "=r"(vlenb));4293 return vlenb;4294 }4295 _LIBUNWIND_ABORT("unsupported riscv register");4296}4297 4298inline void Registers_riscv::setRegister(int regNum, reg_t value) {4299 if (regNum == UNW_REG_IP)4300 _registers[0] = value;4301 else if (regNum == UNW_REG_SP)4302 _registers[2] = value;4303 else if (regNum == UNW_RISCV_X0)4304 /* x0 is hardwired to zero */4305 return;4306 else if ((regNum > 0) && (regNum < 32))4307 _registers[regNum] = value;4308 else4309 _LIBUNWIND_ABORT("unsupported riscv register");4310}4311 4312inline const char *Registers_riscv::getRegisterName(int regNum) {4313 switch (regNum) {4314 case UNW_REG_IP:4315 return "pc";4316 case UNW_REG_SP:4317 return "sp";4318 case UNW_RISCV_X0:4319 return "zero";4320 case UNW_RISCV_X1:4321 return "ra";4322 case UNW_RISCV_X2:4323 return "sp";4324 case UNW_RISCV_X3:4325 return "gp";4326 case UNW_RISCV_X4:4327 return "tp";4328 case UNW_RISCV_X5:4329 return "t0";4330 case UNW_RISCV_X6:4331 return "t1";4332 case UNW_RISCV_X7:4333 return "t2";4334 case UNW_RISCV_X8:4335 return "s0";4336 case UNW_RISCV_X9:4337 return "s1";4338 case UNW_RISCV_X10:4339 return "a0";4340 case UNW_RISCV_X11:4341 return "a1";4342 case UNW_RISCV_X12:4343 return "a2";4344 case UNW_RISCV_X13:4345 return "a3";4346 case UNW_RISCV_X14:4347 return "a4";4348 case UNW_RISCV_X15:4349 return "a5";4350 case UNW_RISCV_X16:4351 return "a6";4352 case UNW_RISCV_X17:4353 return "a7";4354 case UNW_RISCV_X18:4355 return "s2";4356 case UNW_RISCV_X19:4357 return "s3";4358 case UNW_RISCV_X20:4359 return "s4";4360 case UNW_RISCV_X21:4361 return "s5";4362 case UNW_RISCV_X22:4363 return "s6";4364 case UNW_RISCV_X23:4365 return "s7";4366 case UNW_RISCV_X24:4367 return "s8";4368 case UNW_RISCV_X25:4369 return "s9";4370 case UNW_RISCV_X26:4371 return "s10";4372 case UNW_RISCV_X27:4373 return "s11";4374 case UNW_RISCV_X28:4375 return "t3";4376 case UNW_RISCV_X29:4377 return "t4";4378 case UNW_RISCV_X30:4379 return "t5";4380 case UNW_RISCV_X31:4381 return "t6";4382 case UNW_RISCV_F0:4383 return "ft0";4384 case UNW_RISCV_F1:4385 return "ft1";4386 case UNW_RISCV_F2:4387 return "ft2";4388 case UNW_RISCV_F3:4389 return "ft3";4390 case UNW_RISCV_F4:4391 return "ft4";4392 case UNW_RISCV_F5:4393 return "ft5";4394 case UNW_RISCV_F6:4395 return "ft6";4396 case UNW_RISCV_F7:4397 return "ft7";4398 case UNW_RISCV_F8:4399 return "fs0";4400 case UNW_RISCV_F9:4401 return "fs1";4402 case UNW_RISCV_F10:4403 return "fa0";4404 case UNW_RISCV_F11:4405 return "fa1";4406 case UNW_RISCV_F12:4407 return "fa2";4408 case UNW_RISCV_F13:4409 return "fa3";4410 case UNW_RISCV_F14:4411 return "fa4";4412 case UNW_RISCV_F15:4413 return "fa5";4414 case UNW_RISCV_F16:4415 return "fa6";4416 case UNW_RISCV_F17:4417 return "fa7";4418 case UNW_RISCV_F18:4419 return "fs2";4420 case UNW_RISCV_F19:4421 return "fs3";4422 case UNW_RISCV_F20:4423 return "fs4";4424 case UNW_RISCV_F21:4425 return "fs5";4426 case UNW_RISCV_F22:4427 return "fs6";4428 case UNW_RISCV_F23:4429 return "fs7";4430 case UNW_RISCV_F24:4431 return "fs8";4432 case UNW_RISCV_F25:4433 return "fs9";4434 case UNW_RISCV_F26:4435 return "fs10";4436 case UNW_RISCV_F27:4437 return "fs11";4438 case UNW_RISCV_F28:4439 return "ft8";4440 case UNW_RISCV_F29:4441 return "ft9";4442 case UNW_RISCV_F30:4443 return "ft10";4444 case UNW_RISCV_F31:4445 return "ft11";4446 case UNW_RISCV_VLENB:4447 return "vlenb";4448 default:4449 return "unknown register";4450 }4451}4452 4453inline bool Registers_riscv::validFloatRegister(int regNum) const {4454# if defined(__riscv_flen)4455 if (regNum < UNW_RISCV_F0)4456 return false;4457 if (regNum > UNW_RISCV_F31)4458 return false;4459 return true;4460# else4461 (void)regNum;4462 return false;4463# endif4464}4465 4466inline fp_t Registers_riscv::getFloatRegister(int regNum) const {4467# if defined(__riscv_flen)4468 assert(validFloatRegister(regNum));4469 return _floats[regNum - UNW_RISCV_F0];4470# else4471 (void)regNum;4472 _LIBUNWIND_ABORT("libunwind not built with float support");4473# endif4474}4475 4476inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) {4477# if defined(__riscv_flen)4478 assert(validFloatRegister(regNum));4479 _floats[regNum - UNW_RISCV_F0] = value;4480# else4481 (void)regNum;4482 (void)value;4483 _LIBUNWIND_ABORT("libunwind not built with float support");4484# endif4485}4486 4487inline bool Registers_riscv::validVectorRegister(int) const {4488 return false;4489}4490 4491inline v128 Registers_riscv::getVectorRegister(int) const {4492 _LIBUNWIND_ABORT("no riscv vector register support yet");4493}4494 4495inline void Registers_riscv::setVectorRegister(int, v128) {4496 _LIBUNWIND_ABORT("no riscv vector register support yet");4497}4498#endif // _LIBUNWIND_TARGET_RISCV4499 4500#if defined(_LIBUNWIND_TARGET_VE)4501/// Registers_ve holds the register state of a thread in a VE process.4502class _LIBUNWIND_HIDDEN Registers_ve {4503public:4504 Registers_ve();4505 Registers_ve(const void *registers);4506 4507 typedef uint64_t reg_t;4508 typedef uint64_t link_reg_t;4509 4510 bool validRegister(int num) const;4511 uint64_t getRegister(int num) const;4512 void setRegister(int num, uint64_t value);4513 bool validFloatRegister(int num) const;4514 double getFloatRegister(int num) const;4515 void setFloatRegister(int num, double value);4516 bool validVectorRegister(int num) const;4517 v128 getVectorRegister(int num) const;4518 void setVectorRegister(int num, v128 value);4519 static const char *getRegisterName(int num);4520 void jumpto();4521 static constexpr int lastDwarfRegNum() {4522 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;4523 }4524 static int getArch() { return REGISTERS_VE; }4525 4526 uint64_t getSP() const { return _registers.__s[11]; }4527 void setSP(uint64_t value) { _registers.__s[11] = value; }4528 uint64_t getIP() const { return _registers.__ic; }4529 void setIP(uint64_t value) { _registers.__ic = value; }4530 4531private:4532 // FIXME: Need to store not only scalar registers but also vector and vector4533 // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes4534 // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for4535 // SjLj exception support only, so Registers_ve is not implemented completely.4536 struct ve_thread_state_t {4537 uint64_t __s[64]; // s0-s644538 uint64_t __ic; // Instruction counter (IC)4539 uint64_t __vixr; // Vector Index Register4540 uint64_t __vl; // Vector Length Register4541 };4542 4543 ve_thread_state_t _registers; // total 67 registers4544 4545 // Currently no vector register is preserved.4546};4547 4548inline Registers_ve::Registers_ve(const void *registers) {4549 static_assert((check_fit<Registers_ve, unw_context_t>::does_fit),4550 "ve registers do not fit into unw_context_t");4551 memcpy(&_registers, static_cast<const uint8_t *>(registers),4552 sizeof(_registers));4553 static_assert(sizeof(_registers) == 536,4554 "expected vector register offset to be 536");4555}4556 4557inline Registers_ve::Registers_ve() {4558 memset(&_registers, 0, sizeof(_registers));4559}4560 4561inline bool Registers_ve::validRegister(int regNum) const {4562 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)4563 return true;4564 4565 switch (regNum) {4566 case UNW_REG_IP:4567 case UNW_REG_SP:4568 case UNW_VE_VIXR:4569 case UNW_VE_VL:4570 return true;4571 default:4572 return false;4573 }4574}4575 4576inline uint64_t Registers_ve::getRegister(int regNum) const {4577 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63)4578 return _registers.__s[regNum - UNW_VE_S0];4579 4580 switch (regNum) {4581 case UNW_REG_IP:4582 return _registers.__ic;4583 case UNW_REG_SP:4584 return _registers.__s[11];4585 case UNW_VE_VIXR:4586 return _registers.__vixr;4587 case UNW_VE_VL:4588 return _registers.__vl;4589 }4590 _LIBUNWIND_ABORT("unsupported ve register");4591}4592 4593inline void Registers_ve::setRegister(int regNum, uint64_t value) {4594 if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) {4595 _registers.__s[regNum - UNW_VE_S0] = value;4596 return;4597 }4598 4599 switch (regNum) {4600 case UNW_REG_IP:4601 _registers.__ic = value;4602 return;4603 case UNW_REG_SP:4604 _registers.__s[11] = value;4605 return;4606 case UNW_VE_VIXR:4607 _registers.__vixr = value;4608 return;4609 case UNW_VE_VL:4610 _registers.__vl = value;4611 return;4612 }4613 _LIBUNWIND_ABORT("unsupported ve register");4614}4615 4616inline bool Registers_ve::validFloatRegister(int /* regNum */) const {4617 return false;4618}4619 4620inline double Registers_ve::getFloatRegister(int /* regNum */) const {4621 _LIBUNWIND_ABORT("VE doesn't have float registers");4622}4623 4624inline void Registers_ve::setFloatRegister(int /* regNum */,4625 double /* value */) {4626 _LIBUNWIND_ABORT("VE doesn't have float registers");4627}4628 4629inline bool Registers_ve::validVectorRegister(int /* regNum */) const {4630 return false;4631}4632 4633inline v128 Registers_ve::getVectorRegister(int /* regNum */) const {4634 _LIBUNWIND_ABORT("VE vector support not implemented");4635}4636 4637inline void Registers_ve::setVectorRegister(int /* regNum */,4638 v128 /* value */) {4639 _LIBUNWIND_ABORT("VE vector support not implemented");4640}4641 4642inline const char *Registers_ve::getRegisterName(int regNum) {4643 switch (regNum) {4644 case UNW_REG_IP:4645 return "ip";4646 case UNW_REG_SP:4647 return "sp";4648 case UNW_VE_VIXR:4649 return "vixr";4650 case UNW_VE_VL:4651 return "vl";4652 case UNW_VE_S0:4653 return "s0";4654 case UNW_VE_S1:4655 return "s1";4656 case UNW_VE_S2:4657 return "s2";4658 case UNW_VE_S3:4659 return "s3";4660 case UNW_VE_S4:4661 return "s4";4662 case UNW_VE_S5:4663 return "s5";4664 case UNW_VE_S6:4665 return "s6";4666 case UNW_VE_S7:4667 return "s7";4668 case UNW_VE_S8:4669 return "s8";4670 case UNW_VE_S9:4671 return "s9";4672 case UNW_VE_S10:4673 return "s10";4674 case UNW_VE_S11:4675 return "s11";4676 case UNW_VE_S12:4677 return "s12";4678 case UNW_VE_S13:4679 return "s13";4680 case UNW_VE_S14:4681 return "s14";4682 case UNW_VE_S15:4683 return "s15";4684 case UNW_VE_S16:4685 return "s16";4686 case UNW_VE_S17:4687 return "s17";4688 case UNW_VE_S18:4689 return "s18";4690 case UNW_VE_S19:4691 return "s19";4692 case UNW_VE_S20:4693 return "s20";4694 case UNW_VE_S21:4695 return "s21";4696 case UNW_VE_S22:4697 return "s22";4698 case UNW_VE_S23:4699 return "s23";4700 case UNW_VE_S24:4701 return "s24";4702 case UNW_VE_S25:4703 return "s25";4704 case UNW_VE_S26:4705 return "s26";4706 case UNW_VE_S27:4707 return "s27";4708 case UNW_VE_S28:4709 return "s28";4710 case UNW_VE_S29:4711 return "s29";4712 case UNW_VE_S30:4713 return "s30";4714 case UNW_VE_S31:4715 return "s31";4716 case UNW_VE_S32:4717 return "s32";4718 case UNW_VE_S33:4719 return "s33";4720 case UNW_VE_S34:4721 return "s34";4722 case UNW_VE_S35:4723 return "s35";4724 case UNW_VE_S36:4725 return "s36";4726 case UNW_VE_S37:4727 return "s37";4728 case UNW_VE_S38:4729 return "s38";4730 case UNW_VE_S39:4731 return "s39";4732 case UNW_VE_S40:4733 return "s40";4734 case UNW_VE_S41:4735 return "s41";4736 case UNW_VE_S42:4737 return "s42";4738 case UNW_VE_S43:4739 return "s43";4740 case UNW_VE_S44:4741 return "s44";4742 case UNW_VE_S45:4743 return "s45";4744 case UNW_VE_S46:4745 return "s46";4746 case UNW_VE_S47:4747 return "s47";4748 case UNW_VE_S48:4749 return "s48";4750 case UNW_VE_S49:4751 return "s49";4752 case UNW_VE_S50:4753 return "s50";4754 case UNW_VE_S51:4755 return "s51";4756 case UNW_VE_S52:4757 return "s52";4758 case UNW_VE_S53:4759 return "s53";4760 case UNW_VE_S54:4761 return "s54";4762 case UNW_VE_S55:4763 return "s55";4764 case UNW_VE_S56:4765 return "s56";4766 case UNW_VE_S57:4767 return "s57";4768 case UNW_VE_S58:4769 return "s58";4770 case UNW_VE_S59:4771 return "s59";4772 case UNW_VE_S60:4773 return "s60";4774 case UNW_VE_S61:4775 return "s61";4776 case UNW_VE_S62:4777 return "s62";4778 case UNW_VE_S63:4779 return "s63";4780 case UNW_VE_V0:4781 return "v0";4782 case UNW_VE_V1:4783 return "v1";4784 case UNW_VE_V2:4785 return "v2";4786 case UNW_VE_V3:4787 return "v3";4788 case UNW_VE_V4:4789 return "v4";4790 case UNW_VE_V5:4791 return "v5";4792 case UNW_VE_V6:4793 return "v6";4794 case UNW_VE_V7:4795 return "v7";4796 case UNW_VE_V8:4797 return "v8";4798 case UNW_VE_V9:4799 return "v9";4800 case UNW_VE_V10:4801 return "v10";4802 case UNW_VE_V11:4803 return "v11";4804 case UNW_VE_V12:4805 return "v12";4806 case UNW_VE_V13:4807 return "v13";4808 case UNW_VE_V14:4809 return "v14";4810 case UNW_VE_V15:4811 return "v15";4812 case UNW_VE_V16:4813 return "v16";4814 case UNW_VE_V17:4815 return "v17";4816 case UNW_VE_V18:4817 return "v18";4818 case UNW_VE_V19:4819 return "v19";4820 case UNW_VE_V20:4821 return "v20";4822 case UNW_VE_V21:4823 return "v21";4824 case UNW_VE_V22:4825 return "v22";4826 case UNW_VE_V23:4827 return "v23";4828 case UNW_VE_V24:4829 return "v24";4830 case UNW_VE_V25:4831 return "v25";4832 case UNW_VE_V26:4833 return "v26";4834 case UNW_VE_V27:4835 return "v27";4836 case UNW_VE_V28:4837 return "v28";4838 case UNW_VE_V29:4839 return "v29";4840 case UNW_VE_V30:4841 return "v30";4842 case UNW_VE_V31:4843 return "v31";4844 case UNW_VE_V32:4845 return "v32";4846 case UNW_VE_V33:4847 return "v33";4848 case UNW_VE_V34:4849 return "v34";4850 case UNW_VE_V35:4851 return "v35";4852 case UNW_VE_V36:4853 return "v36";4854 case UNW_VE_V37:4855 return "v37";4856 case UNW_VE_V38:4857 return "v38";4858 case UNW_VE_V39:4859 return "v39";4860 case UNW_VE_V40:4861 return "v40";4862 case UNW_VE_V41:4863 return "v41";4864 case UNW_VE_V42:4865 return "v42";4866 case UNW_VE_V43:4867 return "v43";4868 case UNW_VE_V44:4869 return "v44";4870 case UNW_VE_V45:4871 return "v45";4872 case UNW_VE_V46:4873 return "v46";4874 case UNW_VE_V47:4875 return "v47";4876 case UNW_VE_V48:4877 return "v48";4878 case UNW_VE_V49:4879 return "v49";4880 case UNW_VE_V50:4881 return "v50";4882 case UNW_VE_V51:4883 return "v51";4884 case UNW_VE_V52:4885 return "v52";4886 case UNW_VE_V53:4887 return "v53";4888 case UNW_VE_V54:4889 return "v54";4890 case UNW_VE_V55:4891 return "v55";4892 case UNW_VE_V56:4893 return "v56";4894 case UNW_VE_V57:4895 return "v57";4896 case UNW_VE_V58:4897 return "v58";4898 case UNW_VE_V59:4899 return "v59";4900 case UNW_VE_V60:4901 return "v60";4902 case UNW_VE_V61:4903 return "v61";4904 case UNW_VE_V62:4905 return "v62";4906 case UNW_VE_V63:4907 return "v63";4908 case UNW_VE_VM0:4909 return "vm0";4910 case UNW_VE_VM1:4911 return "vm1";4912 case UNW_VE_VM2:4913 return "vm2";4914 case UNW_VE_VM3:4915 return "vm3";4916 case UNW_VE_VM4:4917 return "vm4";4918 case UNW_VE_VM5:4919 return "vm5";4920 case UNW_VE_VM6:4921 return "vm6";4922 case UNW_VE_VM7:4923 return "vm7";4924 case UNW_VE_VM8:4925 return "vm8";4926 case UNW_VE_VM9:4927 return "vm9";4928 case UNW_VE_VM10:4929 return "vm10";4930 case UNW_VE_VM11:4931 return "vm11";4932 case UNW_VE_VM12:4933 return "vm12";4934 case UNW_VE_VM13:4935 return "vm13";4936 case UNW_VE_VM14:4937 return "vm14";4938 case UNW_VE_VM15:4939 return "vm15";4940 }4941 return "unknown register";4942}4943#endif // _LIBUNWIND_TARGET_VE4944 4945#if defined(_LIBUNWIND_TARGET_S390X)4946/// Registers_s390x holds the register state of a thread in a4947/// 64-bit Linux on IBM zSystems process.4948class _LIBUNWIND_HIDDEN Registers_s390x {4949public:4950 Registers_s390x();4951 Registers_s390x(const void *registers);4952 4953 typedef uint64_t reg_t;4954 typedef uint64_t link_reg_t;4955 4956 bool validRegister(int num) const;4957 uint64_t getRegister(int num) const;4958 void setRegister(int num, uint64_t value);4959 bool validFloatRegister(int num) const;4960 double getFloatRegister(int num) const;4961 void setFloatRegister(int num, double value);4962 bool validVectorRegister(int num) const;4963 v128 getVectorRegister(int num) const;4964 void setVectorRegister(int num, v128 value);4965 static const char *getRegisterName(int num);4966 void jumpto();4967 static constexpr int lastDwarfRegNum() {4968 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;4969 }4970 static int getArch() { return REGISTERS_S390X; }4971 4972 uint64_t getSP() const { return _registers.__gpr[15]; }4973 void setSP(uint64_t value) { _registers.__gpr[15] = value; }4974 uint64_t getIP() const { return _registers.__pswa; }4975 void setIP(uint64_t value) { _registers.__pswa = value; }4976 4977private:4978 struct s390x_thread_state_t {4979 uint64_t __pswm; // Problem Status Word: Mask4980 uint64_t __pswa; // Problem Status Word: Address (PC)4981 uint64_t __gpr[16]; // General Purpose Registers4982 double __fpr[16]; // Floating-Point Registers4983 };4984 4985 s390x_thread_state_t _registers;4986};4987 4988inline Registers_s390x::Registers_s390x(const void *registers) {4989 static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),4990 "s390x registers do not fit into unw_context_t");4991 memcpy(&_registers, static_cast<const uint8_t *>(registers),4992 sizeof(_registers));4993}4994 4995inline Registers_s390x::Registers_s390x() {4996 memset(&_registers, 0, sizeof(_registers));4997}4998 4999inline bool Registers_s390x::validRegister(int regNum) const {5000 switch (regNum) {5001 case UNW_S390X_PSWM:5002 case UNW_S390X_PSWA:5003 case UNW_REG_IP:5004 case UNW_REG_SP:5005 return true;5006 }5007 5008 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)5009 return true;5010 5011 return false;5012}5013 5014inline uint64_t Registers_s390x::getRegister(int regNum) const {5015 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)5016 return _registers.__gpr[regNum - UNW_S390X_R0];5017 5018 switch (regNum) {5019 case UNW_S390X_PSWM:5020 return _registers.__pswm;5021 case UNW_S390X_PSWA:5022 case UNW_REG_IP:5023 return _registers.__pswa;5024 case UNW_REG_SP:5025 return _registers.__gpr[15];5026 }5027 _LIBUNWIND_ABORT("unsupported s390x register");5028}5029 5030inline void Registers_s390x::setRegister(int regNum, uint64_t value) {5031 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {5032 _registers.__gpr[regNum - UNW_S390X_R0] = value;5033 return;5034 }5035 5036 switch (regNum) {5037 case UNW_S390X_PSWM:5038 _registers.__pswm = value;5039 return;5040 case UNW_S390X_PSWA:5041 case UNW_REG_IP:5042 _registers.__pswa = value;5043 return;5044 case UNW_REG_SP:5045 _registers.__gpr[15] = value;5046 return;5047 }5048 _LIBUNWIND_ABORT("unsupported s390x register");5049}5050 5051inline bool Registers_s390x::validFloatRegister(int regNum) const {5052 return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;5053}5054 5055inline double Registers_s390x::getFloatRegister(int regNum) const {5056 // NOTE: FPR DWARF register numbers are not consecutive.5057 switch (regNum) {5058 case UNW_S390X_F0:5059 return _registers.__fpr[0];5060 case UNW_S390X_F1:5061 return _registers.__fpr[1];5062 case UNW_S390X_F2:5063 return _registers.__fpr[2];5064 case UNW_S390X_F3:5065 return _registers.__fpr[3];5066 case UNW_S390X_F4:5067 return _registers.__fpr[4];5068 case UNW_S390X_F5:5069 return _registers.__fpr[5];5070 case UNW_S390X_F6:5071 return _registers.__fpr[6];5072 case UNW_S390X_F7:5073 return _registers.__fpr[7];5074 case UNW_S390X_F8:5075 return _registers.__fpr[8];5076 case UNW_S390X_F9:5077 return _registers.__fpr[9];5078 case UNW_S390X_F10:5079 return _registers.__fpr[10];5080 case UNW_S390X_F11:5081 return _registers.__fpr[11];5082 case UNW_S390X_F12:5083 return _registers.__fpr[12];5084 case UNW_S390X_F13:5085 return _registers.__fpr[13];5086 case UNW_S390X_F14:5087 return _registers.__fpr[14];5088 case UNW_S390X_F15:5089 return _registers.__fpr[15];5090 }5091 _LIBUNWIND_ABORT("unsupported s390x register");5092}5093 5094inline void Registers_s390x::setFloatRegister(int regNum, double value) {5095 // NOTE: FPR DWARF register numbers are not consecutive.5096 switch (regNum) {5097 case UNW_S390X_F0:5098 _registers.__fpr[0] = value;5099 return;5100 case UNW_S390X_F1:5101 _registers.__fpr[1] = value;5102 return;5103 case UNW_S390X_F2:5104 _registers.__fpr[2] = value;5105 return;5106 case UNW_S390X_F3:5107 _registers.__fpr[3] = value;5108 return;5109 case UNW_S390X_F4:5110 _registers.__fpr[4] = value;5111 return;5112 case UNW_S390X_F5:5113 _registers.__fpr[5] = value;5114 return;5115 case UNW_S390X_F6:5116 _registers.__fpr[6] = value;5117 return;5118 case UNW_S390X_F7:5119 _registers.__fpr[7] = value;5120 return;5121 case UNW_S390X_F8:5122 _registers.__fpr[8] = value;5123 return;5124 case UNW_S390X_F9:5125 _registers.__fpr[9] = value;5126 return;5127 case UNW_S390X_F10:5128 _registers.__fpr[10] = value;5129 return;5130 case UNW_S390X_F11:5131 _registers.__fpr[11] = value;5132 return;5133 case UNW_S390X_F12:5134 _registers.__fpr[12] = value;5135 return;5136 case UNW_S390X_F13:5137 _registers.__fpr[13] = value;5138 return;5139 case UNW_S390X_F14:5140 _registers.__fpr[14] = value;5141 return;5142 case UNW_S390X_F15:5143 _registers.__fpr[15] = value;5144 return;5145 }5146 _LIBUNWIND_ABORT("unsupported s390x register");5147}5148 5149inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {5150 return false;5151}5152 5153inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {5154 _LIBUNWIND_ABORT("s390x vector support not implemented");5155}5156 5157inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {5158 _LIBUNWIND_ABORT("s390x vector support not implemented");5159}5160 5161inline const char *Registers_s390x::getRegisterName(int regNum) {5162 switch (regNum) {5163 case UNW_REG_IP:5164 return "ip";5165 case UNW_REG_SP:5166 return "sp";5167 case UNW_S390X_R0:5168 return "r0";5169 case UNW_S390X_R1:5170 return "r1";5171 case UNW_S390X_R2:5172 return "r2";5173 case UNW_S390X_R3:5174 return "r3";5175 case UNW_S390X_R4:5176 return "r4";5177 case UNW_S390X_R5:5178 return "r5";5179 case UNW_S390X_R6:5180 return "r6";5181 case UNW_S390X_R7:5182 return "r7";5183 case UNW_S390X_R8:5184 return "r8";5185 case UNW_S390X_R9:5186 return "r9";5187 case UNW_S390X_R10:5188 return "r10";5189 case UNW_S390X_R11:5190 return "r11";5191 case UNW_S390X_R12:5192 return "r12";5193 case UNW_S390X_R13:5194 return "r13";5195 case UNW_S390X_R14:5196 return "r14";5197 case UNW_S390X_R15:5198 return "r15";5199 case UNW_S390X_F0:5200 return "f0";5201 case UNW_S390X_F1:5202 return "f1";5203 case UNW_S390X_F2:5204 return "f2";5205 case UNW_S390X_F3:5206 return "f3";5207 case UNW_S390X_F4:5208 return "f4";5209 case UNW_S390X_F5:5210 return "f5";5211 case UNW_S390X_F6:5212 return "f6";5213 case UNW_S390X_F7:5214 return "f7";5215 case UNW_S390X_F8:5216 return "f8";5217 case UNW_S390X_F9:5218 return "f9";5219 case UNW_S390X_F10:5220 return "f10";5221 case UNW_S390X_F11:5222 return "f11";5223 case UNW_S390X_F12:5224 return "f12";5225 case UNW_S390X_F13:5226 return "f13";5227 case UNW_S390X_F14:5228 return "f14";5229 case UNW_S390X_F15:5230 return "f15";5231 }5232 return "unknown register";5233}5234#endif // _LIBUNWIND_TARGET_S390X5235 5236#if defined(_LIBUNWIND_TARGET_LOONGARCH)5237/// Registers_loongarch holds the register state of a thread in a 64-bit5238/// LoongArch process.5239class _LIBUNWIND_HIDDEN Registers_loongarch {5240public:5241 Registers_loongarch();5242 Registers_loongarch(const void *registers);5243 5244 typedef uint64_t reg_t;5245 typedef uint64_t link_reg_t;5246 5247 bool validRegister(int num) const;5248 uint64_t getRegister(int num) const;5249 void setRegister(int num, uint64_t value);5250 bool validFloatRegister(int num) const;5251 double getFloatRegister(int num) const;5252 void setFloatRegister(int num, double value);5253 bool validVectorRegister(int num) const;5254 v128 getVectorRegister(int num) const;5255 void setVectorRegister(int num, v128 value);5256 static const char *getRegisterName(int num);5257 void jumpto();5258 static constexpr int lastDwarfRegNum() {5259 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;5260 }5261 static int getArch() { return REGISTERS_LOONGARCH; }5262 5263 uint64_t getSP() const { return _registers.__r[3]; }5264 void setSP(uint64_t value) { _registers.__r[3] = value; }5265 uint64_t getIP() const { return _registers.__pc; }5266 void setIP(uint64_t value) { _registers.__pc = value; }5267 5268private:5269 struct loongarch_thread_state_t {5270 uint64_t __r[32];5271 uint64_t __pc;5272 };5273 5274 loongarch_thread_state_t _registers;5275#if __loongarch_frlen == 645276 double _floats[32];5277#endif5278};5279 5280inline Registers_loongarch::Registers_loongarch(const void *registers) {5281 static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),5282 "loongarch registers do not fit into unw_context_t");5283 memcpy(&_registers, registers, sizeof(_registers));5284 static_assert(sizeof(_registers) == 0x108,5285 "expected float registers to be at offset 264");5286#if __loongarch_frlen == 645287 memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),5288 sizeof(_floats));5289#endif5290}5291 5292inline Registers_loongarch::Registers_loongarch() {5293 memset(&_registers, 0, sizeof(_registers));5294#if __loongarch_frlen == 645295 memset(&_floats, 0, sizeof(_floats));5296#endif5297}5298 5299inline bool Registers_loongarch::validRegister(int regNum) const {5300 if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)5301 return true;5302 if (regNum < 0 || regNum > UNW_LOONGARCH_F31)5303 return false;5304 return true;5305}5306 5307inline uint64_t Registers_loongarch::getRegister(int regNum) const {5308 if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)5309 return _registers.__r[regNum - UNW_LOONGARCH_R0];5310 5311 if (regNum == UNW_REG_IP)5312 return _registers.__pc;5313 if (regNum == UNW_REG_SP)5314 return _registers.__r[3];5315 _LIBUNWIND_ABORT("unsupported loongarch register");5316}5317 5318inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {5319 if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)5320 _registers.__r[regNum - UNW_LOONGARCH_R0] = value;5321 else if (regNum == UNW_REG_IP)5322 _registers.__pc = value;5323 else if (regNum == UNW_REG_SP)5324 _registers.__r[3] = value;5325 else5326 _LIBUNWIND_ABORT("unsupported loongarch register");5327}5328 5329inline const char *Registers_loongarch::getRegisterName(int regNum) {5330 switch (regNum) {5331 case UNW_REG_IP:5332 return "$pc";5333 case UNW_REG_SP:5334 return "$sp";5335 case UNW_LOONGARCH_R0:5336 return "$r0";5337 case UNW_LOONGARCH_R1:5338 return "$r1";5339 case UNW_LOONGARCH_R2:5340 return "$r2";5341 case UNW_LOONGARCH_R3:5342 return "$r3";5343 case UNW_LOONGARCH_R4:5344 return "$r4";5345 case UNW_LOONGARCH_R5:5346 return "$r5";5347 case UNW_LOONGARCH_R6:5348 return "$r6";5349 case UNW_LOONGARCH_R7:5350 return "$r7";5351 case UNW_LOONGARCH_R8:5352 return "$r8";5353 case UNW_LOONGARCH_R9:5354 return "$r9";5355 case UNW_LOONGARCH_R10:5356 return "$r10";5357 case UNW_LOONGARCH_R11:5358 return "$r11";5359 case UNW_LOONGARCH_R12:5360 return "$r12";5361 case UNW_LOONGARCH_R13:5362 return "$r13";5363 case UNW_LOONGARCH_R14:5364 return "$r14";5365 case UNW_LOONGARCH_R15:5366 return "$r15";5367 case UNW_LOONGARCH_R16:5368 return "$r16";5369 case UNW_LOONGARCH_R17:5370 return "$r17";5371 case UNW_LOONGARCH_R18:5372 return "$r18";5373 case UNW_LOONGARCH_R19:5374 return "$r19";5375 case UNW_LOONGARCH_R20:5376 return "$r20";5377 case UNW_LOONGARCH_R21:5378 return "$r21";5379 case UNW_LOONGARCH_R22:5380 return "$r22";5381 case UNW_LOONGARCH_R23:5382 return "$r23";5383 case UNW_LOONGARCH_R24:5384 return "$r24";5385 case UNW_LOONGARCH_R25:5386 return "$r25";5387 case UNW_LOONGARCH_R26:5388 return "$r26";5389 case UNW_LOONGARCH_R27:5390 return "$r27";5391 case UNW_LOONGARCH_R28:5392 return "$r28";5393 case UNW_LOONGARCH_R29:5394 return "$r29";5395 case UNW_LOONGARCH_R30:5396 return "$r30";5397 case UNW_LOONGARCH_R31:5398 return "$r31";5399 case UNW_LOONGARCH_F0:5400 return "$f0";5401 case UNW_LOONGARCH_F1:5402 return "$f1";5403 case UNW_LOONGARCH_F2:5404 return "$f2";5405 case UNW_LOONGARCH_F3:5406 return "$f3";5407 case UNW_LOONGARCH_F4:5408 return "$f4";5409 case UNW_LOONGARCH_F5:5410 return "$f5";5411 case UNW_LOONGARCH_F6:5412 return "$f6";5413 case UNW_LOONGARCH_F7:5414 return "$f7";5415 case UNW_LOONGARCH_F8:5416 return "$f8";5417 case UNW_LOONGARCH_F9:5418 return "$f9";5419 case UNW_LOONGARCH_F10:5420 return "$f10";5421 case UNW_LOONGARCH_F11:5422 return "$f11";5423 case UNW_LOONGARCH_F12:5424 return "$f12";5425 case UNW_LOONGARCH_F13:5426 return "$f13";5427 case UNW_LOONGARCH_F14:5428 return "$f14";5429 case UNW_LOONGARCH_F15:5430 return "$f15";5431 case UNW_LOONGARCH_F16:5432 return "$f16";5433 case UNW_LOONGARCH_F17:5434 return "$f17";5435 case UNW_LOONGARCH_F18:5436 return "$f18";5437 case UNW_LOONGARCH_F19:5438 return "$f19";5439 case UNW_LOONGARCH_F20:5440 return "$f20";5441 case UNW_LOONGARCH_F21:5442 return "$f21";5443 case UNW_LOONGARCH_F22:5444 return "$f22";5445 case UNW_LOONGARCH_F23:5446 return "$f23";5447 case UNW_LOONGARCH_F24:5448 return "$f24";5449 case UNW_LOONGARCH_F25:5450 return "$f25";5451 case UNW_LOONGARCH_F26:5452 return "$f26";5453 case UNW_LOONGARCH_F27:5454 return "$f27";5455 case UNW_LOONGARCH_F28:5456 return "$f28";5457 case UNW_LOONGARCH_F29:5458 return "$f29";5459 case UNW_LOONGARCH_F30:5460 return "$f30";5461 case UNW_LOONGARCH_F31:5462 return "$f31";5463 default:5464 return "unknown register";5465 }5466}5467 5468inline bool Registers_loongarch::validFloatRegister(int regNum) const {5469 if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)5470 return false;5471 return true;5472}5473 5474inline double Registers_loongarch::getFloatRegister(int regNum) const {5475#if __loongarch_frlen == 645476 assert(validFloatRegister(regNum));5477 return _floats[regNum - UNW_LOONGARCH_F0];5478#else5479 _LIBUNWIND_ABORT("libunwind not built with float support");5480#endif5481}5482 5483inline void Registers_loongarch::setFloatRegister(int regNum, double value) {5484#if __loongarch_frlen == 645485 assert(validFloatRegister(regNum));5486 _floats[regNum - UNW_LOONGARCH_F0] = value;5487#else5488 _LIBUNWIND_ABORT("libunwind not built with float support");5489#endif5490}5491 5492inline bool Registers_loongarch::validVectorRegister(int) const {5493 return false;5494}5495 5496inline v128 Registers_loongarch::getVectorRegister(int) const {5497 _LIBUNWIND_ABORT("loongarch vector support not implemented");5498}5499 5500inline void Registers_loongarch::setVectorRegister(int, v128) {5501 _LIBUNWIND_ABORT("loongarch vector support not implemented");5502}5503#endif //_LIBUNWIND_TARGET_LOONGARCH5504 5505} // namespace libunwind5506 5507#endif // __REGISTERS_HPP__5508