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