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