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