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(&_registers, registers, sizeof(_registers)); |
351 | } |
352 | |
353 | inline Registers_x86_64::Registers_x86_64() { |
354 | memset(&_registers, 0, 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 | class _LIBUNWIND_HIDDEN Registers_arm64 { |
1819 | public: |
1820 | Registers_arm64(); |
1821 | Registers_arm64(const void *registers); |
1822 | |
1823 | bool validRegister(int num) const; |
1824 | uint64_t getRegister(int num) const; |
1825 | void setRegister(int num, uint64_t value); |
1826 | bool validFloatRegister(int num) const; |
1827 | double getFloatRegister(int num) const; |
1828 | void setFloatRegister(int num, double value); |
1829 | bool validVectorRegister(int num) const; |
1830 | v128 getVectorRegister(int num) const; |
1831 | void setVectorRegister(int num, v128 value); |
1832 | static const char *getRegisterName(int num); |
1833 | void jumpto() { __libunwind_Registers_arm64_jumpto(this); } |
1834 | static constexpr int lastDwarfRegNum() { |
1835 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; |
1836 | } |
1837 | static int getArch() { return REGISTERS_ARM64; } |
1838 | |
1839 | uint64_t getSP() const { return _registers.__sp; } |
1840 | void setSP(uint64_t value) { _registers.__sp = value; } |
1841 | uint64_t getIP() const { return _registers.__pc; } |
1842 | void setIP(uint64_t value) { _registers.__pc = value; } |
1843 | uint64_t getFP() const { return _registers.__fp; } |
1844 | void setFP(uint64_t value) { _registers.__fp = value; } |
1845 | |
1846 | private: |
1847 | struct GPRs { |
1848 | uint64_t __x[29]; // x0-x28 |
1849 | uint64_t __fp; // Frame pointer x29 |
1850 | uint64_t __lr; // Link register x30 |
1851 | uint64_t __sp; // Stack pointer x31 |
1852 | uint64_t __pc; // Program counter |
1853 | uint64_t __ra_sign_state; // RA sign state register |
1854 | }; |
1855 | |
1856 | GPRs _registers; |
1857 | double _vectorHalfRegisters[32]; |
1858 | // Currently only the lower double in 128-bit vectore registers |
1859 | // is perserved during unwinding. We could define new register |
1860 | // numbers (> 96) which mean whole vector registers, then this |
1861 | // struct would need to change to contain whole vector registers. |
1862 | }; |
1863 | |
1864 | inline Registers_arm64::Registers_arm64(const void *registers) { |
1865 | static_assert((check_fit<Registers_arm64, unw_context_t>::does_fit), |
1866 | "arm64 registers do not fit into unw_context_t" ); |
1867 | memcpy(&_registers, registers, sizeof(_registers)); |
1868 | static_assert(sizeof(GPRs) == 0x110, |
1869 | "expected VFP registers to be at offset 272" ); |
1870 | memcpy(_vectorHalfRegisters, |
1871 | static_cast<const uint8_t *>(registers) + sizeof(GPRs), |
1872 | sizeof(_vectorHalfRegisters)); |
1873 | } |
1874 | |
1875 | inline Registers_arm64::Registers_arm64() { |
1876 | memset(&_registers, 0, sizeof(_registers)); |
1877 | memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); |
1878 | } |
1879 | |
1880 | inline bool Registers_arm64::validRegister(int regNum) const { |
1881 | if (regNum == UNW_REG_IP) |
1882 | return true; |
1883 | if (regNum == UNW_REG_SP) |
1884 | return true; |
1885 | if (regNum < 0) |
1886 | return false; |
1887 | if (regNum > 95) |
1888 | return false; |
1889 | if (regNum == UNW_AARCH64_RA_SIGN_STATE) |
1890 | return true; |
1891 | if ((regNum > 32) && (regNum < 64)) |
1892 | return false; |
1893 | return true; |
1894 | } |
1895 | |
1896 | inline uint64_t Registers_arm64::getRegister(int regNum) const { |
1897 | if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) |
1898 | return _registers.__pc; |
1899 | if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) |
1900 | return _registers.__sp; |
1901 | if (regNum == UNW_AARCH64_RA_SIGN_STATE) |
1902 | return _registers.__ra_sign_state; |
1903 | if (regNum == UNW_AARCH64_FP) |
1904 | return _registers.__fp; |
1905 | if (regNum == UNW_AARCH64_LR) |
1906 | return _registers.__lr; |
1907 | if ((regNum >= 0) && (regNum < 29)) |
1908 | return _registers.__x[regNum]; |
1909 | _LIBUNWIND_ABORT("unsupported arm64 register" ); |
1910 | } |
1911 | |
1912 | inline void Registers_arm64::setRegister(int regNum, uint64_t value) { |
1913 | if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) |
1914 | _registers.__pc = value; |
1915 | else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) |
1916 | _registers.__sp = value; |
1917 | else if (regNum == UNW_AARCH64_RA_SIGN_STATE) |
1918 | _registers.__ra_sign_state = value; |
1919 | else if (regNum == UNW_AARCH64_FP) |
1920 | _registers.__fp = value; |
1921 | else if (regNum == UNW_AARCH64_LR) |
1922 | _registers.__lr = value; |
1923 | else if ((regNum >= 0) && (regNum < 29)) |
1924 | _registers.__x[regNum] = value; |
1925 | else |
1926 | _LIBUNWIND_ABORT("unsupported arm64 register" ); |
1927 | } |
1928 | |
1929 | inline const char *Registers_arm64::getRegisterName(int regNum) { |
1930 | switch (regNum) { |
1931 | case UNW_REG_IP: |
1932 | return "pc" ; |
1933 | case UNW_REG_SP: |
1934 | return "sp" ; |
1935 | case UNW_AARCH64_X0: |
1936 | return "x0" ; |
1937 | case UNW_AARCH64_X1: |
1938 | return "x1" ; |
1939 | case UNW_AARCH64_X2: |
1940 | return "x2" ; |
1941 | case UNW_AARCH64_X3: |
1942 | return "x3" ; |
1943 | case UNW_AARCH64_X4: |
1944 | return "x4" ; |
1945 | case UNW_AARCH64_X5: |
1946 | return "x5" ; |
1947 | case UNW_AARCH64_X6: |
1948 | return "x6" ; |
1949 | case UNW_AARCH64_X7: |
1950 | return "x7" ; |
1951 | case UNW_AARCH64_X8: |
1952 | return "x8" ; |
1953 | case UNW_AARCH64_X9: |
1954 | return "x9" ; |
1955 | case UNW_AARCH64_X10: |
1956 | return "x10" ; |
1957 | case UNW_AARCH64_X11: |
1958 | return "x11" ; |
1959 | case UNW_AARCH64_X12: |
1960 | return "x12" ; |
1961 | case UNW_AARCH64_X13: |
1962 | return "x13" ; |
1963 | case UNW_AARCH64_X14: |
1964 | return "x14" ; |
1965 | case UNW_AARCH64_X15: |
1966 | return "x15" ; |
1967 | case UNW_AARCH64_X16: |
1968 | return "x16" ; |
1969 | case UNW_AARCH64_X17: |
1970 | return "x17" ; |
1971 | case UNW_AARCH64_X18: |
1972 | return "x18" ; |
1973 | case UNW_AARCH64_X19: |
1974 | return "x19" ; |
1975 | case UNW_AARCH64_X20: |
1976 | return "x20" ; |
1977 | case UNW_AARCH64_X21: |
1978 | return "x21" ; |
1979 | case UNW_AARCH64_X22: |
1980 | return "x22" ; |
1981 | case UNW_AARCH64_X23: |
1982 | return "x23" ; |
1983 | case UNW_AARCH64_X24: |
1984 | return "x24" ; |
1985 | case UNW_AARCH64_X25: |
1986 | return "x25" ; |
1987 | case UNW_AARCH64_X26: |
1988 | return "x26" ; |
1989 | case UNW_AARCH64_X27: |
1990 | return "x27" ; |
1991 | case UNW_AARCH64_X28: |
1992 | return "x28" ; |
1993 | case UNW_AARCH64_FP: |
1994 | return "fp" ; |
1995 | case UNW_AARCH64_LR: |
1996 | return "lr" ; |
1997 | case UNW_AARCH64_SP: |
1998 | return "sp" ; |
1999 | case UNW_AARCH64_PC: |
2000 | return "pc" ; |
2001 | case UNW_AARCH64_V0: |
2002 | return "d0" ; |
2003 | case UNW_AARCH64_V1: |
2004 | return "d1" ; |
2005 | case UNW_AARCH64_V2: |
2006 | return "d2" ; |
2007 | case UNW_AARCH64_V3: |
2008 | return "d3" ; |
2009 | case UNW_AARCH64_V4: |
2010 | return "d4" ; |
2011 | case UNW_AARCH64_V5: |
2012 | return "d5" ; |
2013 | case UNW_AARCH64_V6: |
2014 | return "d6" ; |
2015 | case UNW_AARCH64_V7: |
2016 | return "d7" ; |
2017 | case UNW_AARCH64_V8: |
2018 | return "d8" ; |
2019 | case UNW_AARCH64_V9: |
2020 | return "d9" ; |
2021 | case UNW_AARCH64_V10: |
2022 | return "d10" ; |
2023 | case UNW_AARCH64_V11: |
2024 | return "d11" ; |
2025 | case UNW_AARCH64_V12: |
2026 | return "d12" ; |
2027 | case UNW_AARCH64_V13: |
2028 | return "d13" ; |
2029 | case UNW_AARCH64_V14: |
2030 | return "d14" ; |
2031 | case UNW_AARCH64_V15: |
2032 | return "d15" ; |
2033 | case UNW_AARCH64_V16: |
2034 | return "d16" ; |
2035 | case UNW_AARCH64_V17: |
2036 | return "d17" ; |
2037 | case UNW_AARCH64_V18: |
2038 | return "d18" ; |
2039 | case UNW_AARCH64_V19: |
2040 | return "d19" ; |
2041 | case UNW_AARCH64_V20: |
2042 | return "d20" ; |
2043 | case UNW_AARCH64_V21: |
2044 | return "d21" ; |
2045 | case UNW_AARCH64_V22: |
2046 | return "d22" ; |
2047 | case UNW_AARCH64_V23: |
2048 | return "d23" ; |
2049 | case UNW_AARCH64_V24: |
2050 | return "d24" ; |
2051 | case UNW_AARCH64_V25: |
2052 | return "d25" ; |
2053 | case UNW_AARCH64_V26: |
2054 | return "d26" ; |
2055 | case UNW_AARCH64_V27: |
2056 | return "d27" ; |
2057 | case UNW_AARCH64_V28: |
2058 | return "d28" ; |
2059 | case UNW_AARCH64_V29: |
2060 | return "d29" ; |
2061 | case UNW_AARCH64_V30: |
2062 | return "d30" ; |
2063 | case UNW_AARCH64_V31: |
2064 | return "d31" ; |
2065 | default: |
2066 | return "unknown register" ; |
2067 | } |
2068 | } |
2069 | |
2070 | inline bool Registers_arm64::validFloatRegister(int regNum) const { |
2071 | if (regNum < UNW_AARCH64_V0) |
2072 | return false; |
2073 | if (regNum > UNW_AARCH64_V31) |
2074 | return false; |
2075 | return true; |
2076 | } |
2077 | |
2078 | inline double Registers_arm64::getFloatRegister(int regNum) const { |
2079 | assert(validFloatRegister(regNum)); |
2080 | return _vectorHalfRegisters[regNum - UNW_AARCH64_V0]; |
2081 | } |
2082 | |
2083 | inline void Registers_arm64::setFloatRegister(int regNum, double value) { |
2084 | assert(validFloatRegister(regNum)); |
2085 | _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value; |
2086 | } |
2087 | |
2088 | inline bool Registers_arm64::validVectorRegister(int) const { |
2089 | return false; |
2090 | } |
2091 | |
2092 | inline v128 Registers_arm64::getVectorRegister(int) const { |
2093 | _LIBUNWIND_ABORT("no arm64 vector register support yet" ); |
2094 | } |
2095 | |
2096 | inline void Registers_arm64::setVectorRegister(int, v128) { |
2097 | _LIBUNWIND_ABORT("no arm64 vector register support yet" ); |
2098 | } |
2099 | #endif // _LIBUNWIND_TARGET_AARCH64 |
2100 | |
2101 | #if defined(_LIBUNWIND_TARGET_ARM) |
2102 | /// Registers_arm holds the register state of a thread in a 32-bit arm |
2103 | /// process. |
2104 | /// |
2105 | /// NOTE: Assumes VFPv3. On ARM processors without a floating point unit, |
2106 | /// this uses more memory than required. |
2107 | class _LIBUNWIND_HIDDEN Registers_arm { |
2108 | public: |
2109 | Registers_arm(); |
2110 | Registers_arm(const void *registers); |
2111 | |
2112 | bool validRegister(int num) const; |
2113 | uint32_t getRegister(int num) const; |
2114 | void setRegister(int num, uint32_t value); |
2115 | bool validFloatRegister(int num) const; |
2116 | unw_fpreg_t getFloatRegister(int num); |
2117 | void setFloatRegister(int num, unw_fpreg_t value); |
2118 | bool validVectorRegister(int num) const; |
2119 | v128 getVectorRegister(int num) const; |
2120 | void setVectorRegister(int num, v128 value); |
2121 | static const char *getRegisterName(int num); |
2122 | void jumpto() { |
2123 | restoreSavedFloatRegisters(); |
2124 | restoreCoreAndJumpTo(); |
2125 | } |
2126 | static constexpr int lastDwarfRegNum() { |
2127 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; |
2128 | } |
2129 | static int getArch() { return REGISTERS_ARM; } |
2130 | |
2131 | uint32_t getSP() const { return _registers.__sp; } |
2132 | void setSP(uint32_t value) { _registers.__sp = value; } |
2133 | uint32_t getIP() const { return _registers.__pc; } |
2134 | void setIP(uint32_t value) { _registers.__pc = value; } |
2135 | |
2136 | void saveVFPAsX() { |
2137 | assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); |
2138 | _use_X_for_vfp_save = true; |
2139 | } |
2140 | |
2141 | void restoreSavedFloatRegisters() { |
2142 | if (_saved_vfp_d0_d15) { |
2143 | if (_use_X_for_vfp_save) |
2144 | restoreVFPWithFLDMX(_vfp_d0_d15_pad); |
2145 | else |
2146 | restoreVFPWithFLDMD(_vfp_d0_d15_pad); |
2147 | } |
2148 | if (_saved_vfp_d16_d31) |
2149 | restoreVFPv3(_vfp_d16_d31); |
2150 | #if defined(__ARM_WMMX) |
2151 | if (_saved_iwmmx) |
2152 | restoreiWMMX(_iwmmx); |
2153 | if (_saved_iwmmx_control) |
2154 | restoreiWMMXControl(_iwmmx_control); |
2155 | #endif |
2156 | } |
2157 | |
2158 | private: |
2159 | struct GPRs { |
2160 | uint32_t __r[13]; // r0-r12 |
2161 | uint32_t __sp; // Stack pointer r13 |
2162 | uint32_t __lr; // Link register r14 |
2163 | uint32_t __pc; // Program counter r15 |
2164 | }; |
2165 | |
2166 | struct PseudoRegisters { |
2167 | uint32_t __pac; // Return Authentication Code (PAC) |
2168 | }; |
2169 | |
2170 | static void saveVFPWithFSTMD(void*); |
2171 | static void saveVFPWithFSTMX(void*); |
2172 | static void saveVFPv3(void*); |
2173 | static void restoreVFPWithFLDMD(void*); |
2174 | static void restoreVFPWithFLDMX(void*); |
2175 | static void restoreVFPv3(void*); |
2176 | #if defined(__ARM_WMMX) |
2177 | static void saveiWMMX(void*); |
2178 | static void saveiWMMXControl(uint32_t*); |
2179 | static void restoreiWMMX(void*); |
2180 | static void restoreiWMMXControl(uint32_t*); |
2181 | #endif |
2182 | void restoreCoreAndJumpTo(); |
2183 | |
2184 | // ARM registers |
2185 | GPRs _registers; |
2186 | PseudoRegisters _pseudo_registers; |
2187 | |
2188 | // We save floating point registers lazily because we can't know ahead of |
2189 | // time which ones are used. See EHABI #4.7. |
2190 | |
2191 | // Whether D0-D15 are saved in the FTSMX instead of FSTMD format. |
2192 | // |
2193 | // See EHABI #7.5 that explains how matching instruction sequences for load |
2194 | // and store need to be used to correctly restore the exact register bits. |
2195 | bool _use_X_for_vfp_save; |
2196 | // Whether VFP D0-D15 are saved. |
2197 | bool _saved_vfp_d0_d15; |
2198 | // Whether VFPv3 D16-D31 are saved. |
2199 | bool _saved_vfp_d16_d31; |
2200 | // VFP registers D0-D15, + padding if saved using FSTMX |
2201 | unw_fpreg_t _vfp_d0_d15_pad[17]; |
2202 | // VFPv3 registers D16-D31, always saved using FSTMD |
2203 | unw_fpreg_t _vfp_d16_d31[16]; |
2204 | #if defined(__ARM_WMMX) |
2205 | // Whether iWMMX data registers are saved. |
2206 | bool _saved_iwmmx; |
2207 | // Whether iWMMX control registers are saved. |
2208 | mutable bool _saved_iwmmx_control; |
2209 | // iWMMX registers |
2210 | unw_fpreg_t _iwmmx[16]; |
2211 | // iWMMX control registers |
2212 | mutable uint32_t _iwmmx_control[4]; |
2213 | #endif |
2214 | }; |
2215 | |
2216 | inline Registers_arm::Registers_arm(const void *registers) |
2217 | : _use_X_for_vfp_save(false), |
2218 | _saved_vfp_d0_d15(false), |
2219 | _saved_vfp_d16_d31(false) { |
2220 | static_assert((check_fit<Registers_arm, unw_context_t>::does_fit), |
2221 | "arm registers do not fit into unw_context_t" ); |
2222 | // See __unw_getcontext() note about data. |
2223 | memcpy(&_registers, registers, sizeof(_registers)); |
2224 | memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); |
2225 | memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); |
2226 | memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); |
2227 | #if defined(__ARM_WMMX) |
2228 | _saved_iwmmx = false; |
2229 | _saved_iwmmx_control = false; |
2230 | memset(&_iwmmx, 0, sizeof(_iwmmx)); |
2231 | memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); |
2232 | #endif |
2233 | } |
2234 | |
2235 | inline Registers_arm::Registers_arm() |
2236 | : _use_X_for_vfp_save(false), |
2237 | _saved_vfp_d0_d15(false), |
2238 | _saved_vfp_d16_d31(false) { |
2239 | memset(&_registers, 0, sizeof(_registers)); |
2240 | memset(&_pseudo_registers, 0, sizeof(_pseudo_registers)); |
2241 | memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); |
2242 | memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); |
2243 | #if defined(__ARM_WMMX) |
2244 | _saved_iwmmx = false; |
2245 | _saved_iwmmx_control = false; |
2246 | memset(&_iwmmx, 0, sizeof(_iwmmx)); |
2247 | memset(&_iwmmx_control, 0, sizeof(_iwmmx_control)); |
2248 | #endif |
2249 | } |
2250 | |
2251 | inline bool Registers_arm::validRegister(int regNum) const { |
2252 | // Returns true for all non-VFP registers supported by the EHABI |
2253 | // virtual register set (VRS). |
2254 | if (regNum == UNW_REG_IP) |
2255 | return true; |
2256 | |
2257 | if (regNum == UNW_REG_SP) |
2258 | return true; |
2259 | |
2260 | if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) |
2261 | return true; |
2262 | |
2263 | #if defined(__ARM_WMMX) |
2264 | if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) |
2265 | return true; |
2266 | #endif |
2267 | |
2268 | #ifdef __ARM_FEATURE_PAUTH |
2269 | if (regNum == UNW_ARM_RA_AUTH_CODE) |
2270 | return true; |
2271 | #endif |
2272 | |
2273 | return false; |
2274 | } |
2275 | |
2276 | inline uint32_t Registers_arm::getRegister(int regNum) const { |
2277 | if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) |
2278 | return _registers.__sp; |
2279 | |
2280 | if (regNum == UNW_ARM_LR) |
2281 | return _registers.__lr; |
2282 | |
2283 | if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) |
2284 | return _registers.__pc; |
2285 | |
2286 | if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) |
2287 | return _registers.__r[regNum]; |
2288 | |
2289 | #if defined(__ARM_WMMX) |
2290 | if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { |
2291 | if (!_saved_iwmmx_control) { |
2292 | _saved_iwmmx_control = true; |
2293 | saveiWMMXControl(_iwmmx_control); |
2294 | } |
2295 | return _iwmmx_control[regNum - UNW_ARM_WC0]; |
2296 | } |
2297 | #endif |
2298 | |
2299 | #ifdef __ARM_FEATURE_PAUTH |
2300 | if (regNum == UNW_ARM_RA_AUTH_CODE) |
2301 | return _pseudo_registers.__pac; |
2302 | #endif |
2303 | |
2304 | _LIBUNWIND_ABORT("unsupported arm register" ); |
2305 | } |
2306 | |
2307 | inline void Registers_arm::setRegister(int regNum, uint32_t value) { |
2308 | if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) { |
2309 | _registers.__sp = value; |
2310 | return; |
2311 | } |
2312 | |
2313 | if (regNum == UNW_ARM_LR) { |
2314 | _registers.__lr = value; |
2315 | return; |
2316 | } |
2317 | |
2318 | if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) { |
2319 | _registers.__pc = value; |
2320 | return; |
2321 | } |
2322 | |
2323 | if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) { |
2324 | _registers.__r[regNum] = value; |
2325 | return; |
2326 | } |
2327 | |
2328 | #if defined(__ARM_WMMX) |
2329 | if (regNum >= UNW_ARM_WC0 && regNum <= UNW_ARM_WC3) { |
2330 | if (!_saved_iwmmx_control) { |
2331 | _saved_iwmmx_control = true; |
2332 | saveiWMMXControl(_iwmmx_control); |
2333 | } |
2334 | _iwmmx_control[regNum - UNW_ARM_WC0] = value; |
2335 | return; |
2336 | } |
2337 | #endif |
2338 | |
2339 | if (regNum == UNW_ARM_RA_AUTH_CODE) { |
2340 | _pseudo_registers.__pac = value; |
2341 | return; |
2342 | } |
2343 | |
2344 | _LIBUNWIND_ABORT("unsupported arm register" ); |
2345 | } |
2346 | |
2347 | inline const char *Registers_arm::getRegisterName(int regNum) { |
2348 | switch (regNum) { |
2349 | case UNW_REG_IP: |
2350 | case UNW_ARM_IP: // UNW_ARM_R15 is alias |
2351 | return "pc" ; |
2352 | case UNW_ARM_LR: // UNW_ARM_R14 is alias |
2353 | return "lr" ; |
2354 | case UNW_REG_SP: |
2355 | case UNW_ARM_SP: // UNW_ARM_R13 is alias |
2356 | return "sp" ; |
2357 | case UNW_ARM_R0: |
2358 | return "r0" ; |
2359 | case UNW_ARM_R1: |
2360 | return "r1" ; |
2361 | case UNW_ARM_R2: |
2362 | return "r2" ; |
2363 | case UNW_ARM_R3: |
2364 | return "r3" ; |
2365 | case UNW_ARM_R4: |
2366 | return "r4" ; |
2367 | case UNW_ARM_R5: |
2368 | return "r5" ; |
2369 | case UNW_ARM_R6: |
2370 | return "r6" ; |
2371 | case UNW_ARM_R7: |
2372 | return "r7" ; |
2373 | case UNW_ARM_R8: |
2374 | return "r8" ; |
2375 | case UNW_ARM_R9: |
2376 | return "r9" ; |
2377 | case UNW_ARM_R10: |
2378 | return "r10" ; |
2379 | case UNW_ARM_R11: |
2380 | return "r11" ; |
2381 | case UNW_ARM_R12: |
2382 | return "r12" ; |
2383 | case UNW_ARM_S0: |
2384 | return "s0" ; |
2385 | case UNW_ARM_S1: |
2386 | return "s1" ; |
2387 | case UNW_ARM_S2: |
2388 | return "s2" ; |
2389 | case UNW_ARM_S3: |
2390 | return "s3" ; |
2391 | case UNW_ARM_S4: |
2392 | return "s4" ; |
2393 | case UNW_ARM_S5: |
2394 | return "s5" ; |
2395 | case UNW_ARM_S6: |
2396 | return "s6" ; |
2397 | case UNW_ARM_S7: |
2398 | return "s7" ; |
2399 | case UNW_ARM_S8: |
2400 | return "s8" ; |
2401 | case UNW_ARM_S9: |
2402 | return "s9" ; |
2403 | case UNW_ARM_S10: |
2404 | return "s10" ; |
2405 | case UNW_ARM_S11: |
2406 | return "s11" ; |
2407 | case UNW_ARM_S12: |
2408 | return "s12" ; |
2409 | case UNW_ARM_S13: |
2410 | return "s13" ; |
2411 | case UNW_ARM_S14: |
2412 | return "s14" ; |
2413 | case UNW_ARM_S15: |
2414 | return "s15" ; |
2415 | case UNW_ARM_S16: |
2416 | return "s16" ; |
2417 | case UNW_ARM_S17: |
2418 | return "s17" ; |
2419 | case UNW_ARM_S18: |
2420 | return "s18" ; |
2421 | case UNW_ARM_S19: |
2422 | return "s19" ; |
2423 | case UNW_ARM_S20: |
2424 | return "s20" ; |
2425 | case UNW_ARM_S21: |
2426 | return "s21" ; |
2427 | case UNW_ARM_S22: |
2428 | return "s22" ; |
2429 | case UNW_ARM_S23: |
2430 | return "s23" ; |
2431 | case UNW_ARM_S24: |
2432 | return "s24" ; |
2433 | case UNW_ARM_S25: |
2434 | return "s25" ; |
2435 | case UNW_ARM_S26: |
2436 | return "s26" ; |
2437 | case UNW_ARM_S27: |
2438 | return "s27" ; |
2439 | case UNW_ARM_S28: |
2440 | return "s28" ; |
2441 | case UNW_ARM_S29: |
2442 | return "s29" ; |
2443 | case UNW_ARM_S30: |
2444 | return "s30" ; |
2445 | case UNW_ARM_S31: |
2446 | return "s31" ; |
2447 | case UNW_ARM_D0: |
2448 | return "d0" ; |
2449 | case UNW_ARM_D1: |
2450 | return "d1" ; |
2451 | case UNW_ARM_D2: |
2452 | return "d2" ; |
2453 | case UNW_ARM_D3: |
2454 | return "d3" ; |
2455 | case UNW_ARM_D4: |
2456 | return "d4" ; |
2457 | case UNW_ARM_D5: |
2458 | return "d5" ; |
2459 | case UNW_ARM_D6: |
2460 | return "d6" ; |
2461 | case UNW_ARM_D7: |
2462 | return "d7" ; |
2463 | case UNW_ARM_D8: |
2464 | return "d8" ; |
2465 | case UNW_ARM_D9: |
2466 | return "d9" ; |
2467 | case UNW_ARM_D10: |
2468 | return "d10" ; |
2469 | case UNW_ARM_D11: |
2470 | return "d11" ; |
2471 | case UNW_ARM_D12: |
2472 | return "d12" ; |
2473 | case UNW_ARM_D13: |
2474 | return "d13" ; |
2475 | case UNW_ARM_D14: |
2476 | return "d14" ; |
2477 | case UNW_ARM_D15: |
2478 | return "d15" ; |
2479 | case UNW_ARM_D16: |
2480 | return "d16" ; |
2481 | case UNW_ARM_D17: |
2482 | return "d17" ; |
2483 | case UNW_ARM_D18: |
2484 | return "d18" ; |
2485 | case UNW_ARM_D19: |
2486 | return "d19" ; |
2487 | case UNW_ARM_D20: |
2488 | return "d20" ; |
2489 | case UNW_ARM_D21: |
2490 | return "d21" ; |
2491 | case UNW_ARM_D22: |
2492 | return "d22" ; |
2493 | case UNW_ARM_D23: |
2494 | return "d23" ; |
2495 | case UNW_ARM_D24: |
2496 | return "d24" ; |
2497 | case UNW_ARM_D25: |
2498 | return "d25" ; |
2499 | case UNW_ARM_D26: |
2500 | return "d26" ; |
2501 | case UNW_ARM_D27: |
2502 | return "d27" ; |
2503 | case UNW_ARM_D28: |
2504 | return "d28" ; |
2505 | case UNW_ARM_D29: |
2506 | return "d29" ; |
2507 | case UNW_ARM_D30: |
2508 | return "d30" ; |
2509 | case UNW_ARM_D31: |
2510 | return "d31" ; |
2511 | default: |
2512 | return "unknown register" ; |
2513 | } |
2514 | } |
2515 | |
2516 | inline bool Registers_arm::validFloatRegister(int regNum) const { |
2517 | // NOTE: Consider the intel MMX registers floating points so the |
2518 | // __unw_get_fpreg can be used to transmit the 64-bit data back. |
2519 | return ((regNum >= UNW_ARM_D0) && (regNum <= UNW_ARM_D31)) |
2520 | #if defined(__ARM_WMMX) |
2521 | || ((regNum >= UNW_ARM_WR0) && (regNum <= UNW_ARM_WR15)) |
2522 | #endif |
2523 | ; |
2524 | } |
2525 | |
2526 | inline unw_fpreg_t Registers_arm::getFloatRegister(int regNum) { |
2527 | if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { |
2528 | if (!_saved_vfp_d0_d15) { |
2529 | _saved_vfp_d0_d15 = true; |
2530 | if (_use_X_for_vfp_save) |
2531 | saveVFPWithFSTMX(_vfp_d0_d15_pad); |
2532 | else |
2533 | saveVFPWithFSTMD(_vfp_d0_d15_pad); |
2534 | } |
2535 | return _vfp_d0_d15_pad[regNum - UNW_ARM_D0]; |
2536 | } |
2537 | |
2538 | if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { |
2539 | if (!_saved_vfp_d16_d31) { |
2540 | _saved_vfp_d16_d31 = true; |
2541 | saveVFPv3(_vfp_d16_d31); |
2542 | } |
2543 | return _vfp_d16_d31[regNum - UNW_ARM_D16]; |
2544 | } |
2545 | |
2546 | #if defined(__ARM_WMMX) |
2547 | if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { |
2548 | if (!_saved_iwmmx) { |
2549 | _saved_iwmmx = true; |
2550 | saveiWMMX(_iwmmx); |
2551 | } |
2552 | return _iwmmx[regNum - UNW_ARM_WR0]; |
2553 | } |
2554 | #endif |
2555 | |
2556 | _LIBUNWIND_ABORT("Unknown ARM float register" ); |
2557 | } |
2558 | |
2559 | inline void Registers_arm::setFloatRegister(int regNum, unw_fpreg_t value) { |
2560 | if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D15) { |
2561 | if (!_saved_vfp_d0_d15) { |
2562 | _saved_vfp_d0_d15 = true; |
2563 | if (_use_X_for_vfp_save) |
2564 | saveVFPWithFSTMX(_vfp_d0_d15_pad); |
2565 | else |
2566 | saveVFPWithFSTMD(_vfp_d0_d15_pad); |
2567 | } |
2568 | _vfp_d0_d15_pad[regNum - UNW_ARM_D0] = value; |
2569 | return; |
2570 | } |
2571 | |
2572 | if (regNum >= UNW_ARM_D16 && regNum <= UNW_ARM_D31) { |
2573 | if (!_saved_vfp_d16_d31) { |
2574 | _saved_vfp_d16_d31 = true; |
2575 | saveVFPv3(_vfp_d16_d31); |
2576 | } |
2577 | _vfp_d16_d31[regNum - UNW_ARM_D16] = value; |
2578 | return; |
2579 | } |
2580 | |
2581 | #if defined(__ARM_WMMX) |
2582 | if (regNum >= UNW_ARM_WR0 && regNum <= UNW_ARM_WR15) { |
2583 | if (!_saved_iwmmx) { |
2584 | _saved_iwmmx = true; |
2585 | saveiWMMX(_iwmmx); |
2586 | } |
2587 | _iwmmx[regNum - UNW_ARM_WR0] = value; |
2588 | return; |
2589 | } |
2590 | #endif |
2591 | |
2592 | _LIBUNWIND_ABORT("Unknown ARM float register" ); |
2593 | } |
2594 | |
2595 | inline bool Registers_arm::validVectorRegister(int) const { |
2596 | return false; |
2597 | } |
2598 | |
2599 | inline v128 Registers_arm::getVectorRegister(int) const { |
2600 | _LIBUNWIND_ABORT("ARM vector support not implemented" ); |
2601 | } |
2602 | |
2603 | inline void Registers_arm::setVectorRegister(int, v128) { |
2604 | _LIBUNWIND_ABORT("ARM vector support not implemented" ); |
2605 | } |
2606 | #endif // _LIBUNWIND_TARGET_ARM |
2607 | |
2608 | |
2609 | #if defined(_LIBUNWIND_TARGET_OR1K) |
2610 | /// Registers_or1k holds the register state of a thread in an OpenRISC1000 |
2611 | /// process. |
2612 | class _LIBUNWIND_HIDDEN Registers_or1k { |
2613 | public: |
2614 | Registers_or1k(); |
2615 | Registers_or1k(const void *registers); |
2616 | |
2617 | bool validRegister(int num) const; |
2618 | uint32_t getRegister(int num) const; |
2619 | void setRegister(int num, uint32_t value); |
2620 | bool validFloatRegister(int num) const; |
2621 | double getFloatRegister(int num) const; |
2622 | void setFloatRegister(int num, double value); |
2623 | bool validVectorRegister(int num) const; |
2624 | v128 getVectorRegister(int num) const; |
2625 | void setVectorRegister(int num, v128 value); |
2626 | static const char *getRegisterName(int num); |
2627 | void jumpto(); |
2628 | static constexpr int lastDwarfRegNum() { |
2629 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; |
2630 | } |
2631 | static int getArch() { return REGISTERS_OR1K; } |
2632 | |
2633 | uint64_t getSP() const { return _registers.__r[1]; } |
2634 | void setSP(uint32_t value) { _registers.__r[1] = value; } |
2635 | uint64_t getIP() const { return _registers.__pc; } |
2636 | void setIP(uint32_t value) { _registers.__pc = value; } |
2637 | |
2638 | private: |
2639 | struct or1k_thread_state_t { |
2640 | unsigned int __r[32]; // r0-r31 |
2641 | unsigned int __pc; // Program counter |
2642 | unsigned int __epcr; // Program counter at exception |
2643 | }; |
2644 | |
2645 | or1k_thread_state_t _registers; |
2646 | }; |
2647 | |
2648 | inline Registers_or1k::Registers_or1k(const void *registers) { |
2649 | static_assert((check_fit<Registers_or1k, unw_context_t>::does_fit), |
2650 | "or1k registers do not fit into unw_context_t" ); |
2651 | memcpy(&_registers, static_cast<const uint8_t *>(registers), |
2652 | sizeof(_registers)); |
2653 | } |
2654 | |
2655 | inline Registers_or1k::Registers_or1k() { |
2656 | memset(&_registers, 0, sizeof(_registers)); |
2657 | } |
2658 | |
2659 | inline bool Registers_or1k::validRegister(int regNum) const { |
2660 | if (regNum == UNW_REG_IP) |
2661 | return true; |
2662 | if (regNum == UNW_REG_SP) |
2663 | return true; |
2664 | if (regNum < 0) |
2665 | return false; |
2666 | if (regNum <= UNW_OR1K_R31) |
2667 | return true; |
2668 | if (regNum == UNW_OR1K_EPCR) |
2669 | return true; |
2670 | return false; |
2671 | } |
2672 | |
2673 | inline uint32_t Registers_or1k::getRegister(int regNum) const { |
2674 | if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) |
2675 | return _registers.__r[regNum - UNW_OR1K_R0]; |
2676 | |
2677 | switch (regNum) { |
2678 | case UNW_REG_IP: |
2679 | return _registers.__pc; |
2680 | case UNW_REG_SP: |
2681 | return _registers.__r[1]; |
2682 | case UNW_OR1K_EPCR: |
2683 | return _registers.__epcr; |
2684 | } |
2685 | _LIBUNWIND_ABORT("unsupported or1k register" ); |
2686 | } |
2687 | |
2688 | inline void Registers_or1k::setRegister(int regNum, uint32_t value) { |
2689 | if (regNum >= UNW_OR1K_R0 && regNum <= UNW_OR1K_R31) { |
2690 | _registers.__r[regNum - UNW_OR1K_R0] = value; |
2691 | return; |
2692 | } |
2693 | |
2694 | switch (regNum) { |
2695 | case UNW_REG_IP: |
2696 | _registers.__pc = value; |
2697 | return; |
2698 | case UNW_REG_SP: |
2699 | _registers.__r[1] = value; |
2700 | return; |
2701 | case UNW_OR1K_EPCR: |
2702 | _registers.__epcr = value; |
2703 | return; |
2704 | } |
2705 | _LIBUNWIND_ABORT("unsupported or1k register" ); |
2706 | } |
2707 | |
2708 | inline bool Registers_or1k::validFloatRegister(int /* regNum */) const { |
2709 | return false; |
2710 | } |
2711 | |
2712 | inline double Registers_or1k::getFloatRegister(int /* regNum */) const { |
2713 | _LIBUNWIND_ABORT("or1k float support not implemented" ); |
2714 | } |
2715 | |
2716 | inline void Registers_or1k::setFloatRegister(int /* regNum */, |
2717 | double /* value */) { |
2718 | _LIBUNWIND_ABORT("or1k float support not implemented" ); |
2719 | } |
2720 | |
2721 | inline bool Registers_or1k::validVectorRegister(int /* regNum */) const { |
2722 | return false; |
2723 | } |
2724 | |
2725 | inline v128 Registers_or1k::getVectorRegister(int /* regNum */) const { |
2726 | _LIBUNWIND_ABORT("or1k vector support not implemented" ); |
2727 | } |
2728 | |
2729 | inline void Registers_or1k::setVectorRegister(int /* regNum */, v128 /* value */) { |
2730 | _LIBUNWIND_ABORT("or1k vector support not implemented" ); |
2731 | } |
2732 | |
2733 | inline const char *Registers_or1k::getRegisterName(int regNum) { |
2734 | switch (regNum) { |
2735 | case UNW_OR1K_R0: |
2736 | return "r0" ; |
2737 | case UNW_OR1K_R1: |
2738 | return "r1" ; |
2739 | case UNW_OR1K_R2: |
2740 | return "r2" ; |
2741 | case UNW_OR1K_R3: |
2742 | return "r3" ; |
2743 | case UNW_OR1K_R4: |
2744 | return "r4" ; |
2745 | case UNW_OR1K_R5: |
2746 | return "r5" ; |
2747 | case UNW_OR1K_R6: |
2748 | return "r6" ; |
2749 | case UNW_OR1K_R7: |
2750 | return "r7" ; |
2751 | case UNW_OR1K_R8: |
2752 | return "r8" ; |
2753 | case UNW_OR1K_R9: |
2754 | return "r9" ; |
2755 | case UNW_OR1K_R10: |
2756 | return "r10" ; |
2757 | case UNW_OR1K_R11: |
2758 | return "r11" ; |
2759 | case UNW_OR1K_R12: |
2760 | return "r12" ; |
2761 | case UNW_OR1K_R13: |
2762 | return "r13" ; |
2763 | case UNW_OR1K_R14: |
2764 | return "r14" ; |
2765 | case UNW_OR1K_R15: |
2766 | return "r15" ; |
2767 | case UNW_OR1K_R16: |
2768 | return "r16" ; |
2769 | case UNW_OR1K_R17: |
2770 | return "r17" ; |
2771 | case UNW_OR1K_R18: |
2772 | return "r18" ; |
2773 | case UNW_OR1K_R19: |
2774 | return "r19" ; |
2775 | case UNW_OR1K_R20: |
2776 | return "r20" ; |
2777 | case UNW_OR1K_R21: |
2778 | return "r21" ; |
2779 | case UNW_OR1K_R22: |
2780 | return "r22" ; |
2781 | case UNW_OR1K_R23: |
2782 | return "r23" ; |
2783 | case UNW_OR1K_R24: |
2784 | return "r24" ; |
2785 | case UNW_OR1K_R25: |
2786 | return "r25" ; |
2787 | case UNW_OR1K_R26: |
2788 | return "r26" ; |
2789 | case UNW_OR1K_R27: |
2790 | return "r27" ; |
2791 | case UNW_OR1K_R28: |
2792 | return "r28" ; |
2793 | case UNW_OR1K_R29: |
2794 | return "r29" ; |
2795 | case UNW_OR1K_R30: |
2796 | return "r30" ; |
2797 | case UNW_OR1K_R31: |
2798 | return "r31" ; |
2799 | case UNW_OR1K_EPCR: |
2800 | return "EPCR" ; |
2801 | default: |
2802 | return "unknown register" ; |
2803 | } |
2804 | |
2805 | } |
2806 | #endif // _LIBUNWIND_TARGET_OR1K |
2807 | |
2808 | #if defined(_LIBUNWIND_TARGET_MIPS_O32) |
2809 | /// Registers_mips_o32 holds the register state of a thread in a 32-bit MIPS |
2810 | /// process. |
2811 | class _LIBUNWIND_HIDDEN Registers_mips_o32 { |
2812 | public: |
2813 | Registers_mips_o32(); |
2814 | Registers_mips_o32(const void *registers); |
2815 | |
2816 | bool validRegister(int num) const; |
2817 | uint32_t getRegister(int num) const; |
2818 | void setRegister(int num, uint32_t value); |
2819 | bool validFloatRegister(int num) const; |
2820 | double getFloatRegister(int num) const; |
2821 | void setFloatRegister(int num, double value); |
2822 | bool validVectorRegister(int num) const; |
2823 | v128 getVectorRegister(int num) const; |
2824 | void setVectorRegister(int num, v128 value); |
2825 | static const char *getRegisterName(int num); |
2826 | void jumpto(); |
2827 | static constexpr int lastDwarfRegNum() { |
2828 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; |
2829 | } |
2830 | static int getArch() { return REGISTERS_MIPS_O32; } |
2831 | |
2832 | uint32_t getSP() const { return _registers.__r[29]; } |
2833 | void setSP(uint32_t value) { _registers.__r[29] = value; } |
2834 | uint32_t getIP() const { return _registers.__pc; } |
2835 | void setIP(uint32_t value) { _registers.__pc = value; } |
2836 | |
2837 | private: |
2838 | struct mips_o32_thread_state_t { |
2839 | uint32_t __r[32]; |
2840 | uint32_t __pc; |
2841 | uint32_t __hi; |
2842 | uint32_t __lo; |
2843 | }; |
2844 | |
2845 | mips_o32_thread_state_t _registers; |
2846 | #ifdef __mips_hard_float |
2847 | /// O32 with 32-bit floating point registers only uses half of this |
2848 | /// space. However, using the same layout for 32-bit vs 64-bit |
2849 | /// floating point registers results in a single context size for |
2850 | /// O32 with hard float. |
2851 | uint32_t _padding; |
2852 | double _floats[32]; |
2853 | #endif |
2854 | }; |
2855 | |
2856 | inline Registers_mips_o32::Registers_mips_o32(const void *registers) { |
2857 | static_assert((check_fit<Registers_mips_o32, unw_context_t>::does_fit), |
2858 | "mips_o32 registers do not fit into unw_context_t" ); |
2859 | memcpy(&_registers, static_cast<const uint8_t *>(registers), |
2860 | sizeof(_registers)); |
2861 | } |
2862 | |
2863 | inline Registers_mips_o32::Registers_mips_o32() { |
2864 | memset(&_registers, 0, sizeof(_registers)); |
2865 | } |
2866 | |
2867 | inline bool Registers_mips_o32::validRegister(int regNum) const { |
2868 | if (regNum == UNW_REG_IP) |
2869 | return true; |
2870 | if (regNum == UNW_REG_SP) |
2871 | return true; |
2872 | if (regNum < 0) |
2873 | return false; |
2874 | if (regNum <= UNW_MIPS_R31) |
2875 | return true; |
2876 | #if __mips_isa_rev < 6 |
2877 | if (regNum == UNW_MIPS_HI) |
2878 | return true; |
2879 | if (regNum == UNW_MIPS_LO) |
2880 | return true; |
2881 | #endif |
2882 | #if defined(__mips_hard_float) && __mips_fpr == 32 |
2883 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) |
2884 | return true; |
2885 | #endif |
2886 | // FIXME: DSP accumulator registers, MSA registers |
2887 | return false; |
2888 | } |
2889 | |
2890 | inline uint32_t Registers_mips_o32::getRegister(int regNum) const { |
2891 | if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) |
2892 | return _registers.__r[regNum - UNW_MIPS_R0]; |
2893 | #if defined(__mips_hard_float) && __mips_fpr == 32 |
2894 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { |
2895 | uint32_t *p; |
2896 | |
2897 | if (regNum % 2 == 0) |
2898 | p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; |
2899 | else |
2900 | p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; |
2901 | return *p; |
2902 | } |
2903 | #endif |
2904 | |
2905 | switch (regNum) { |
2906 | case UNW_REG_IP: |
2907 | return _registers.__pc; |
2908 | case UNW_REG_SP: |
2909 | return _registers.__r[29]; |
2910 | #if __mips_isa_rev < 6 |
2911 | case UNW_MIPS_HI: |
2912 | return _registers.__hi; |
2913 | case UNW_MIPS_LO: |
2914 | return _registers.__lo; |
2915 | #endif |
2916 | } |
2917 | _LIBUNWIND_ABORT("unsupported mips_o32 register" ); |
2918 | } |
2919 | |
2920 | inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) { |
2921 | if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { |
2922 | _registers.__r[regNum - UNW_MIPS_R0] = value; |
2923 | return; |
2924 | } |
2925 | #if defined(__mips_hard_float) && __mips_fpr == 32 |
2926 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) { |
2927 | uint32_t *p; |
2928 | |
2929 | if (regNum % 2 == 0) |
2930 | p = (uint32_t *)&_floats[regNum - UNW_MIPS_F0]; |
2931 | else |
2932 | p = (uint32_t *)&_floats[(regNum - 1) - UNW_MIPS_F0] + 1; |
2933 | *p = value; |
2934 | return; |
2935 | } |
2936 | #endif |
2937 | |
2938 | switch (regNum) { |
2939 | case UNW_REG_IP: |
2940 | _registers.__pc = value; |
2941 | return; |
2942 | case UNW_REG_SP: |
2943 | _registers.__r[29] = value; |
2944 | return; |
2945 | #if __mips_isa_rev < 6 |
2946 | case UNW_MIPS_HI: |
2947 | _registers.__hi = value; |
2948 | return; |
2949 | case UNW_MIPS_LO: |
2950 | _registers.__lo = value; |
2951 | #endif |
2952 | return; |
2953 | } |
2954 | _LIBUNWIND_ABORT("unsupported mips_o32 register" ); |
2955 | } |
2956 | |
2957 | inline bool Registers_mips_o32::validFloatRegister(int regNum) const { |
2958 | #if defined(__mips_hard_float) && __mips_fpr == 64 |
2959 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) |
2960 | return true; |
2961 | #else |
2962 | (void)regNum; |
2963 | #endif |
2964 | return false; |
2965 | } |
2966 | |
2967 | inline double Registers_mips_o32::getFloatRegister(int regNum) const { |
2968 | #if defined(__mips_hard_float) && __mips_fpr == 64 |
2969 | assert(validFloatRegister(regNum)); |
2970 | return _floats[regNum - UNW_MIPS_F0]; |
2971 | #else |
2972 | (void)regNum; |
2973 | _LIBUNWIND_ABORT("mips_o32 float support not implemented" ); |
2974 | #endif |
2975 | } |
2976 | |
2977 | inline void Registers_mips_o32::setFloatRegister(int regNum, |
2978 | double value) { |
2979 | #if defined(__mips_hard_float) && __mips_fpr == 64 |
2980 | assert(validFloatRegister(regNum)); |
2981 | _floats[regNum - UNW_MIPS_F0] = value; |
2982 | #else |
2983 | (void)regNum; |
2984 | (void)value; |
2985 | _LIBUNWIND_ABORT("mips_o32 float support not implemented" ); |
2986 | #endif |
2987 | } |
2988 | |
2989 | inline bool Registers_mips_o32::validVectorRegister(int /* regNum */) const { |
2990 | return false; |
2991 | } |
2992 | |
2993 | inline v128 Registers_mips_o32::getVectorRegister(int /* regNum */) const { |
2994 | _LIBUNWIND_ABORT("mips_o32 vector support not implemented" ); |
2995 | } |
2996 | |
2997 | inline void Registers_mips_o32::setVectorRegister(int /* regNum */, v128 /* value */) { |
2998 | _LIBUNWIND_ABORT("mips_o32 vector support not implemented" ); |
2999 | } |
3000 | |
3001 | inline const char *Registers_mips_o32::getRegisterName(int regNum) { |
3002 | switch (regNum) { |
3003 | case UNW_MIPS_R0: |
3004 | return "$0" ; |
3005 | case UNW_MIPS_R1: |
3006 | return "$1" ; |
3007 | case UNW_MIPS_R2: |
3008 | return "$2" ; |
3009 | case UNW_MIPS_R3: |
3010 | return "$3" ; |
3011 | case UNW_MIPS_R4: |
3012 | return "$4" ; |
3013 | case UNW_MIPS_R5: |
3014 | return "$5" ; |
3015 | case UNW_MIPS_R6: |
3016 | return "$6" ; |
3017 | case UNW_MIPS_R7: |
3018 | return "$7" ; |
3019 | case UNW_MIPS_R8: |
3020 | return "$8" ; |
3021 | case UNW_MIPS_R9: |
3022 | return "$9" ; |
3023 | case UNW_MIPS_R10: |
3024 | return "$10" ; |
3025 | case UNW_MIPS_R11: |
3026 | return "$11" ; |
3027 | case UNW_MIPS_R12: |
3028 | return "$12" ; |
3029 | case UNW_MIPS_R13: |
3030 | return "$13" ; |
3031 | case UNW_MIPS_R14: |
3032 | return "$14" ; |
3033 | case UNW_MIPS_R15: |
3034 | return "$15" ; |
3035 | case UNW_MIPS_R16: |
3036 | return "$16" ; |
3037 | case UNW_MIPS_R17: |
3038 | return "$17" ; |
3039 | case UNW_MIPS_R18: |
3040 | return "$18" ; |
3041 | case UNW_MIPS_R19: |
3042 | return "$19" ; |
3043 | case UNW_MIPS_R20: |
3044 | return "$20" ; |
3045 | case UNW_MIPS_R21: |
3046 | return "$21" ; |
3047 | case UNW_MIPS_R22: |
3048 | return "$22" ; |
3049 | case UNW_MIPS_R23: |
3050 | return "$23" ; |
3051 | case UNW_MIPS_R24: |
3052 | return "$24" ; |
3053 | case UNW_MIPS_R25: |
3054 | return "$25" ; |
3055 | case UNW_MIPS_R26: |
3056 | return "$26" ; |
3057 | case UNW_MIPS_R27: |
3058 | return "$27" ; |
3059 | case UNW_MIPS_R28: |
3060 | return "$28" ; |
3061 | case UNW_MIPS_R29: |
3062 | return "$29" ; |
3063 | case UNW_MIPS_R30: |
3064 | return "$30" ; |
3065 | case UNW_MIPS_R31: |
3066 | return "$31" ; |
3067 | case UNW_MIPS_F0: |
3068 | return "$f0" ; |
3069 | case UNW_MIPS_F1: |
3070 | return "$f1" ; |
3071 | case UNW_MIPS_F2: |
3072 | return "$f2" ; |
3073 | case UNW_MIPS_F3: |
3074 | return "$f3" ; |
3075 | case UNW_MIPS_F4: |
3076 | return "$f4" ; |
3077 | case UNW_MIPS_F5: |
3078 | return "$f5" ; |
3079 | case UNW_MIPS_F6: |
3080 | return "$f6" ; |
3081 | case UNW_MIPS_F7: |
3082 | return "$f7" ; |
3083 | case UNW_MIPS_F8: |
3084 | return "$f8" ; |
3085 | case UNW_MIPS_F9: |
3086 | return "$f9" ; |
3087 | case UNW_MIPS_F10: |
3088 | return "$f10" ; |
3089 | case UNW_MIPS_F11: |
3090 | return "$f11" ; |
3091 | case UNW_MIPS_F12: |
3092 | return "$f12" ; |
3093 | case UNW_MIPS_F13: |
3094 | return "$f13" ; |
3095 | case UNW_MIPS_F14: |
3096 | return "$f14" ; |
3097 | case UNW_MIPS_F15: |
3098 | return "$f15" ; |
3099 | case UNW_MIPS_F16: |
3100 | return "$f16" ; |
3101 | case UNW_MIPS_F17: |
3102 | return "$f17" ; |
3103 | case UNW_MIPS_F18: |
3104 | return "$f18" ; |
3105 | case UNW_MIPS_F19: |
3106 | return "$f19" ; |
3107 | case UNW_MIPS_F20: |
3108 | return "$f20" ; |
3109 | case UNW_MIPS_F21: |
3110 | return "$f21" ; |
3111 | case UNW_MIPS_F22: |
3112 | return "$f22" ; |
3113 | case UNW_MIPS_F23: |
3114 | return "$f23" ; |
3115 | case UNW_MIPS_F24: |
3116 | return "$f24" ; |
3117 | case UNW_MIPS_F25: |
3118 | return "$f25" ; |
3119 | case UNW_MIPS_F26: |
3120 | return "$f26" ; |
3121 | case UNW_MIPS_F27: |
3122 | return "$f27" ; |
3123 | case UNW_MIPS_F28: |
3124 | return "$f28" ; |
3125 | case UNW_MIPS_F29: |
3126 | return "$f29" ; |
3127 | case UNW_MIPS_F30: |
3128 | return "$f30" ; |
3129 | case UNW_MIPS_F31: |
3130 | return "$f31" ; |
3131 | #if __mips_isa_rev < 6 |
3132 | case UNW_MIPS_HI: |
3133 | return "$hi" ; |
3134 | case UNW_MIPS_LO: |
3135 | return "$lo" ; |
3136 | #endif |
3137 | default: |
3138 | return "unknown register" ; |
3139 | } |
3140 | } |
3141 | #endif // _LIBUNWIND_TARGET_MIPS_O32 |
3142 | |
3143 | #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) |
3144 | /// Registers_mips_newabi holds the register state of a thread in a |
3145 | /// MIPS process using NEWABI (the N32 or N64 ABIs). |
3146 | class _LIBUNWIND_HIDDEN Registers_mips_newabi { |
3147 | public: |
3148 | Registers_mips_newabi(); |
3149 | Registers_mips_newabi(const void *registers); |
3150 | |
3151 | bool validRegister(int num) const; |
3152 | uint64_t getRegister(int num) const; |
3153 | void setRegister(int num, uint64_t value); |
3154 | bool validFloatRegister(int num) const; |
3155 | double getFloatRegister(int num) const; |
3156 | void setFloatRegister(int num, double value); |
3157 | bool validVectorRegister(int num) const; |
3158 | v128 getVectorRegister(int num) const; |
3159 | void setVectorRegister(int num, v128 value); |
3160 | static const char *getRegisterName(int num); |
3161 | void jumpto(); |
3162 | static constexpr int lastDwarfRegNum() { |
3163 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; |
3164 | } |
3165 | static int getArch() { return REGISTERS_MIPS_NEWABI; } |
3166 | |
3167 | uint64_t getSP() const { return _registers.__r[29]; } |
3168 | void setSP(uint64_t value) { _registers.__r[29] = value; } |
3169 | uint64_t getIP() const { return _registers.__pc; } |
3170 | void setIP(uint64_t value) { _registers.__pc = value; } |
3171 | |
3172 | private: |
3173 | struct mips_newabi_thread_state_t { |
3174 | uint64_t __r[32]; |
3175 | uint64_t __pc; |
3176 | uint64_t __hi; |
3177 | uint64_t __lo; |
3178 | }; |
3179 | |
3180 | mips_newabi_thread_state_t _registers; |
3181 | #ifdef __mips_hard_float |
3182 | double _floats[32]; |
3183 | #endif |
3184 | }; |
3185 | |
3186 | inline Registers_mips_newabi::Registers_mips_newabi(const void *registers) { |
3187 | static_assert((check_fit<Registers_mips_newabi, unw_context_t>::does_fit), |
3188 | "mips_newabi registers do not fit into unw_context_t" ); |
3189 | memcpy(&_registers, static_cast<const uint8_t *>(registers), |
3190 | sizeof(_registers)); |
3191 | } |
3192 | |
3193 | inline Registers_mips_newabi::Registers_mips_newabi() { |
3194 | memset(&_registers, 0, sizeof(_registers)); |
3195 | } |
3196 | |
3197 | inline bool Registers_mips_newabi::validRegister(int regNum) const { |
3198 | if (regNum == UNW_REG_IP) |
3199 | return true; |
3200 | if (regNum == UNW_REG_SP) |
3201 | return true; |
3202 | if (regNum < 0) |
3203 | return false; |
3204 | if (regNum <= UNW_MIPS_R31) |
3205 | return true; |
3206 | #if __mips_isa_rev < 6 |
3207 | if (regNum == UNW_MIPS_HI) |
3208 | return true; |
3209 | if (regNum == UNW_MIPS_LO) |
3210 | return true; |
3211 | #endif |
3212 | // FIXME: Hard float, DSP accumulator registers, MSA registers |
3213 | return false; |
3214 | } |
3215 | |
3216 | inline uint64_t Registers_mips_newabi::getRegister(int regNum) const { |
3217 | if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) |
3218 | return _registers.__r[regNum - UNW_MIPS_R0]; |
3219 | |
3220 | switch (regNum) { |
3221 | case UNW_REG_IP: |
3222 | return _registers.__pc; |
3223 | case UNW_REG_SP: |
3224 | return _registers.__r[29]; |
3225 | #if __mips_isa_rev < 6 |
3226 | case UNW_MIPS_HI: |
3227 | return _registers.__hi; |
3228 | case UNW_MIPS_LO: |
3229 | return _registers.__lo; |
3230 | #endif |
3231 | } |
3232 | _LIBUNWIND_ABORT("unsupported mips_newabi register" ); |
3233 | } |
3234 | |
3235 | inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) { |
3236 | if (regNum >= UNW_MIPS_R0 && regNum <= UNW_MIPS_R31) { |
3237 | _registers.__r[regNum - UNW_MIPS_R0] = value; |
3238 | return; |
3239 | } |
3240 | |
3241 | switch (regNum) { |
3242 | case UNW_REG_IP: |
3243 | _registers.__pc = value; |
3244 | return; |
3245 | case UNW_REG_SP: |
3246 | _registers.__r[29] = value; |
3247 | return; |
3248 | #if __mips_isa_rev < 6 |
3249 | case UNW_MIPS_HI: |
3250 | _registers.__hi = value; |
3251 | return; |
3252 | case UNW_MIPS_LO: |
3253 | _registers.__lo = value; |
3254 | return; |
3255 | #endif |
3256 | } |
3257 | _LIBUNWIND_ABORT("unsupported mips_newabi register" ); |
3258 | } |
3259 | |
3260 | inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { |
3261 | #ifdef __mips_hard_float |
3262 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) |
3263 | return true; |
3264 | #else |
3265 | (void)regNum; |
3266 | #endif |
3267 | return false; |
3268 | } |
3269 | |
3270 | inline double Registers_mips_newabi::getFloatRegister(int regNum) const { |
3271 | #ifdef __mips_hard_float |
3272 | assert(validFloatRegister(regNum)); |
3273 | return _floats[regNum - UNW_MIPS_F0]; |
3274 | #else |
3275 | (void)regNum; |
3276 | _LIBUNWIND_ABORT("mips_newabi float support not implemented" ); |
3277 | #endif |
3278 | } |
3279 | |
3280 | inline void Registers_mips_newabi::setFloatRegister(int regNum, |
3281 | double value) { |
3282 | #ifdef __mips_hard_float |
3283 | assert(validFloatRegister(regNum)); |
3284 | _floats[regNum - UNW_MIPS_F0] = value; |
3285 | #else |
3286 | (void)regNum; |
3287 | (void)value; |
3288 | _LIBUNWIND_ABORT("mips_newabi float support not implemented" ); |
3289 | #endif |
3290 | } |
3291 | |
3292 | inline bool Registers_mips_newabi::validVectorRegister(int /* regNum */) const { |
3293 | return false; |
3294 | } |
3295 | |
3296 | inline v128 Registers_mips_newabi::getVectorRegister(int /* regNum */) const { |
3297 | _LIBUNWIND_ABORT("mips_newabi vector support not implemented" ); |
3298 | } |
3299 | |
3300 | inline void Registers_mips_newabi::setVectorRegister(int /* regNum */, v128 /* value */) { |
3301 | _LIBUNWIND_ABORT("mips_newabi vector support not implemented" ); |
3302 | } |
3303 | |
3304 | inline const char *Registers_mips_newabi::getRegisterName(int regNum) { |
3305 | switch (regNum) { |
3306 | case UNW_MIPS_R0: |
3307 | return "$0" ; |
3308 | case UNW_MIPS_R1: |
3309 | return "$1" ; |
3310 | case UNW_MIPS_R2: |
3311 | return "$2" ; |
3312 | case UNW_MIPS_R3: |
3313 | return "$3" ; |
3314 | case UNW_MIPS_R4: |
3315 | return "$4" ; |
3316 | case UNW_MIPS_R5: |
3317 | return "$5" ; |
3318 | case UNW_MIPS_R6: |
3319 | return "$6" ; |
3320 | case UNW_MIPS_R7: |
3321 | return "$7" ; |
3322 | case UNW_MIPS_R8: |
3323 | return "$8" ; |
3324 | case UNW_MIPS_R9: |
3325 | return "$9" ; |
3326 | case UNW_MIPS_R10: |
3327 | return "$10" ; |
3328 | case UNW_MIPS_R11: |
3329 | return "$11" ; |
3330 | case UNW_MIPS_R12: |
3331 | return "$12" ; |
3332 | case UNW_MIPS_R13: |
3333 | return "$13" ; |
3334 | case UNW_MIPS_R14: |
3335 | return "$14" ; |
3336 | case UNW_MIPS_R15: |
3337 | return "$15" ; |
3338 | case UNW_MIPS_R16: |
3339 | return "$16" ; |
3340 | case UNW_MIPS_R17: |
3341 | return "$17" ; |
3342 | case UNW_MIPS_R18: |
3343 | return "$18" ; |
3344 | case UNW_MIPS_R19: |
3345 | return "$19" ; |
3346 | case UNW_MIPS_R20: |
3347 | return "$20" ; |
3348 | case UNW_MIPS_R21: |
3349 | return "$21" ; |
3350 | case UNW_MIPS_R22: |
3351 | return "$22" ; |
3352 | case UNW_MIPS_R23: |
3353 | return "$23" ; |
3354 | case UNW_MIPS_R24: |
3355 | return "$24" ; |
3356 | case UNW_MIPS_R25: |
3357 | return "$25" ; |
3358 | case UNW_MIPS_R26: |
3359 | return "$26" ; |
3360 | case UNW_MIPS_R27: |
3361 | return "$27" ; |
3362 | case UNW_MIPS_R28: |
3363 | return "$28" ; |
3364 | case UNW_MIPS_R29: |
3365 | return "$29" ; |
3366 | case UNW_MIPS_R30: |
3367 | return "$30" ; |
3368 | case UNW_MIPS_R31: |
3369 | return "$31" ; |
3370 | case UNW_MIPS_F0: |
3371 | return "$f0" ; |
3372 | case UNW_MIPS_F1: |
3373 | return "$f1" ; |
3374 | case UNW_MIPS_F2: |
3375 | return "$f2" ; |
3376 | case UNW_MIPS_F3: |
3377 | return "$f3" ; |
3378 | case UNW_MIPS_F4: |
3379 | return "$f4" ; |
3380 | case UNW_MIPS_F5: |
3381 | return "$f5" ; |
3382 | case UNW_MIPS_F6: |
3383 | return "$f6" ; |
3384 | case UNW_MIPS_F7: |
3385 | return "$f7" ; |
3386 | case UNW_MIPS_F8: |
3387 | return "$f8" ; |
3388 | case UNW_MIPS_F9: |
3389 | return "$f9" ; |
3390 | case UNW_MIPS_F10: |
3391 | return "$f10" ; |
3392 | case UNW_MIPS_F11: |
3393 | return "$f11" ; |
3394 | case UNW_MIPS_F12: |
3395 | return "$f12" ; |
3396 | case UNW_MIPS_F13: |
3397 | return "$f13" ; |
3398 | case UNW_MIPS_F14: |
3399 | return "$f14" ; |
3400 | case UNW_MIPS_F15: |
3401 | return "$f15" ; |
3402 | case UNW_MIPS_F16: |
3403 | return "$f16" ; |
3404 | case UNW_MIPS_F17: |
3405 | return "$f17" ; |
3406 | case UNW_MIPS_F18: |
3407 | return "$f18" ; |
3408 | case UNW_MIPS_F19: |
3409 | return "$f19" ; |
3410 | case UNW_MIPS_F20: |
3411 | return "$f20" ; |
3412 | case UNW_MIPS_F21: |
3413 | return "$f21" ; |
3414 | case UNW_MIPS_F22: |
3415 | return "$f22" ; |
3416 | case UNW_MIPS_F23: |
3417 | return "$f23" ; |
3418 | case UNW_MIPS_F24: |
3419 | return "$f24" ; |
3420 | case UNW_MIPS_F25: |
3421 | return "$f25" ; |
3422 | case UNW_MIPS_F26: |
3423 | return "$f26" ; |
3424 | case UNW_MIPS_F27: |
3425 | return "$f27" ; |
3426 | case UNW_MIPS_F28: |
3427 | return "$f28" ; |
3428 | case UNW_MIPS_F29: |
3429 | return "$f29" ; |
3430 | case UNW_MIPS_F30: |
3431 | return "$f30" ; |
3432 | case UNW_MIPS_F31: |
3433 | return "$f31" ; |
3434 | #if __mips_isa_rev < 6 |
3435 | case UNW_MIPS_HI: |
3436 | return "$hi" ; |
3437 | case UNW_MIPS_LO: |
3438 | return "$lo" ; |
3439 | #endif |
3440 | default: |
3441 | return "unknown register" ; |
3442 | } |
3443 | } |
3444 | #endif // _LIBUNWIND_TARGET_MIPS_NEWABI |
3445 | |
3446 | #if defined(_LIBUNWIND_TARGET_SPARC) |
3447 | /// Registers_sparc holds the register state of a thread in a 32-bit Sparc |
3448 | /// process. |
3449 | class _LIBUNWIND_HIDDEN Registers_sparc { |
3450 | public: |
3451 | Registers_sparc(); |
3452 | Registers_sparc(const void *registers); |
3453 | |
3454 | bool validRegister(int num) const; |
3455 | uint32_t getRegister(int num) const; |
3456 | void setRegister(int num, uint32_t value); |
3457 | bool validFloatRegister(int num) const; |
3458 | double getFloatRegister(int num) const; |
3459 | void setFloatRegister(int num, double value); |
3460 | bool validVectorRegister(int num) const; |
3461 | v128 getVectorRegister(int num) const; |
3462 | void setVectorRegister(int num, v128 value); |
3463 | static const char *getRegisterName(int num); |
3464 | void jumpto(); |
3465 | static constexpr int lastDwarfRegNum() { |
3466 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; |
3467 | } |
3468 | static int getArch() { return REGISTERS_SPARC; } |
3469 | |
3470 | uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; } |
3471 | void setSP(uint32_t value) { _registers.__regs[UNW_SPARC_O6] = value; } |
3472 | uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; } |
3473 | void setIP(uint32_t value) { _registers.__regs[UNW_SPARC_O7] = value; } |
3474 | |
3475 | private: |
3476 | struct sparc_thread_state_t { |
3477 | unsigned int __regs[32]; |
3478 | }; |
3479 | |
3480 | sparc_thread_state_t _registers; |
3481 | }; |
3482 | |
3483 | inline Registers_sparc::Registers_sparc(const void *registers) { |
3484 | static_assert((check_fit<Registers_sparc, unw_context_t>::does_fit), |
3485 | "sparc registers do not fit into unw_context_t" ); |
3486 | memcpy(&_registers, static_cast<const uint8_t *>(registers), |
3487 | sizeof(_registers)); |
3488 | } |
3489 | |
3490 | inline Registers_sparc::Registers_sparc() { |
3491 | memset(&_registers, 0, sizeof(_registers)); |
3492 | } |
3493 | |
3494 | inline bool Registers_sparc::validRegister(int regNum) const { |
3495 | if (regNum == UNW_REG_IP) |
3496 | return true; |
3497 | if (regNum == UNW_REG_SP) |
3498 | return true; |
3499 | if (regNum < 0) |
3500 | return false; |
3501 | if (regNum <= UNW_SPARC_I7) |
3502 | return true; |
3503 | return false; |
3504 | } |
3505 | |
3506 | inline uint32_t Registers_sparc::getRegister(int regNum) const { |
3507 | if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { |
3508 | return _registers.__regs[regNum]; |
3509 | } |
3510 | |
3511 | switch (regNum) { |
3512 | case UNW_REG_IP: |
3513 | return _registers.__regs[UNW_SPARC_O7]; |
3514 | case UNW_REG_SP: |
3515 | return _registers.__regs[UNW_SPARC_O6]; |
3516 | } |
3517 | _LIBUNWIND_ABORT("unsupported sparc register" ); |
3518 | } |
3519 | |
3520 | inline void Registers_sparc::setRegister(int regNum, uint32_t value) { |
3521 | if ((UNW_SPARC_G0 <= regNum) && (regNum <= UNW_SPARC_I7)) { |
3522 | _registers.__regs[regNum] = value; |
3523 | return; |
3524 | } |
3525 | |
3526 | switch (regNum) { |
3527 | case UNW_REG_IP: |
3528 | _registers.__regs[UNW_SPARC_O7] = value; |
3529 | return; |
3530 | case UNW_REG_SP: |
3531 | _registers.__regs[UNW_SPARC_O6] = value; |
3532 | return; |
3533 | } |
3534 | _LIBUNWIND_ABORT("unsupported sparc register" ); |
3535 | } |
3536 | |
3537 | inline bool Registers_sparc::validFloatRegister(int) const { return false; } |
3538 | |
3539 | inline double Registers_sparc::getFloatRegister(int) const { |
3540 | _LIBUNWIND_ABORT("no Sparc float registers" ); |
3541 | } |
3542 | |
3543 | inline void Registers_sparc::setFloatRegister(int, double) { |
3544 | _LIBUNWIND_ABORT("no Sparc float registers" ); |
3545 | } |
3546 | |
3547 | inline bool Registers_sparc::validVectorRegister(int) const { return false; } |
3548 | |
3549 | inline v128 Registers_sparc::getVectorRegister(int) const { |
3550 | _LIBUNWIND_ABORT("no Sparc vector registers" ); |
3551 | } |
3552 | |
3553 | inline void Registers_sparc::setVectorRegister(int, v128) { |
3554 | _LIBUNWIND_ABORT("no Sparc vector registers" ); |
3555 | } |
3556 | |
3557 | inline const char *Registers_sparc::getRegisterName(int regNum) { |
3558 | switch (regNum) { |
3559 | case UNW_REG_IP: |
3560 | return "pc" ; |
3561 | case UNW_SPARC_G0: |
3562 | return "g0" ; |
3563 | case UNW_SPARC_G1: |
3564 | return "g1" ; |
3565 | case UNW_SPARC_G2: |
3566 | return "g2" ; |
3567 | case UNW_SPARC_G3: |
3568 | return "g3" ; |
3569 | case UNW_SPARC_G4: |
3570 | return "g4" ; |
3571 | case UNW_SPARC_G5: |
3572 | return "g5" ; |
3573 | case UNW_SPARC_G6: |
3574 | return "g6" ; |
3575 | case UNW_SPARC_G7: |
3576 | return "g7" ; |
3577 | case UNW_SPARC_O0: |
3578 | return "o0" ; |
3579 | case UNW_SPARC_O1: |
3580 | return "o1" ; |
3581 | case UNW_SPARC_O2: |
3582 | return "o2" ; |
3583 | case UNW_SPARC_O3: |
3584 | return "o3" ; |
3585 | case UNW_SPARC_O4: |
3586 | return "o4" ; |
3587 | case UNW_SPARC_O5: |
3588 | return "o5" ; |
3589 | case UNW_REG_SP: |
3590 | case UNW_SPARC_O6: |
3591 | return "sp" ; |
3592 | case UNW_SPARC_O7: |
3593 | return "o7" ; |
3594 | case UNW_SPARC_L0: |
3595 | return "l0" ; |
3596 | case UNW_SPARC_L1: |
3597 | return "l1" ; |
3598 | case UNW_SPARC_L2: |
3599 | return "l2" ; |
3600 | case UNW_SPARC_L3: |
3601 | return "l3" ; |
3602 | case UNW_SPARC_L4: |
3603 | return "l4" ; |
3604 | case UNW_SPARC_L5: |
3605 | return "l5" ; |
3606 | case UNW_SPARC_L6: |
3607 | return "l6" ; |
3608 | case UNW_SPARC_L7: |
3609 | return "l7" ; |
3610 | case UNW_SPARC_I0: |
3611 | return "i0" ; |
3612 | case UNW_SPARC_I1: |
3613 | return "i1" ; |
3614 | case UNW_SPARC_I2: |
3615 | return "i2" ; |
3616 | case UNW_SPARC_I3: |
3617 | return "i3" ; |
3618 | case UNW_SPARC_I4: |
3619 | return "i4" ; |
3620 | case UNW_SPARC_I5: |
3621 | return "i5" ; |
3622 | case UNW_SPARC_I6: |
3623 | return "fp" ; |
3624 | case UNW_SPARC_I7: |
3625 | return "i7" ; |
3626 | default: |
3627 | return "unknown register" ; |
3628 | } |
3629 | } |
3630 | #endif // _LIBUNWIND_TARGET_SPARC |
3631 | |
3632 | #if defined(_LIBUNWIND_TARGET_SPARC64) |
3633 | /// Registers_sparc64 holds the register state of a thread in a 64-bit |
3634 | /// sparc process. |
3635 | class _LIBUNWIND_HIDDEN Registers_sparc64 { |
3636 | public: |
3637 | Registers_sparc64() = default; |
3638 | Registers_sparc64(const void *registers); |
3639 | |
3640 | bool validRegister(int num) const; |
3641 | uint64_t getRegister(int num) const; |
3642 | void setRegister(int num, uint64_t value); |
3643 | bool validFloatRegister(int num) const; |
3644 | double getFloatRegister(int num) const; |
3645 | void setFloatRegister(int num, double value); |
3646 | bool validVectorRegister(int num) const; |
3647 | v128 getVectorRegister(int num) const; |
3648 | void setVectorRegister(int num, v128 value); |
3649 | const char *getRegisterName(int num); |
3650 | void jumpto(); |
3651 | static constexpr int lastDwarfRegNum() { |
3652 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64; |
3653 | } |
3654 | static int getArch() { return REGISTERS_SPARC64; } |
3655 | |
3656 | uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6] + 2047; } |
3657 | void setSP(uint64_t value) { _registers.__regs[UNW_SPARC_O6] = value - 2047; } |
3658 | uint64_t getIP() const { return _registers.__regs[UNW_SPARC_O7]; } |
3659 | void setIP(uint64_t value) { _registers.__regs[UNW_SPARC_O7] = value; } |
3660 | uint64_t getWCookie() const { return _wcookie; } |
3661 | |
3662 | private: |
3663 | struct sparc64_thread_state_t { |
3664 | uint64_t __regs[32]; |
3665 | }; |
3666 | |
3667 | sparc64_thread_state_t _registers{}; |
3668 | uint64_t _wcookie = 0; |
3669 | }; |
3670 | |
3671 | inline Registers_sparc64::Registers_sparc64(const void *registers) { |
3672 | static_assert((check_fit<Registers_sparc64, unw_context_t>::does_fit), |
3673 | "sparc64 registers do not fit into unw_context_t" ); |
3674 | memcpy(&_registers, registers, sizeof(_registers)); |
3675 | memcpy(&_wcookie, |
3676 | static_cast<const uint8_t *>(registers) + sizeof(_registers), |
3677 | sizeof(_wcookie)); |
3678 | } |
3679 | |
3680 | inline bool Registers_sparc64::validRegister(int regNum) const { |
3681 | if (regNum == UNW_REG_IP) |
3682 | return true; |
3683 | if (regNum == UNW_REG_SP) |
3684 | return true; |
3685 | if (regNum < 0) |
3686 | return false; |
3687 | if (regNum <= UNW_SPARC_I7) |
3688 | return true; |
3689 | return false; |
3690 | } |
3691 | |
3692 | inline uint64_t Registers_sparc64::getRegister(int regNum) const { |
3693 | if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) |
3694 | return _registers.__regs[regNum]; |
3695 | |
3696 | switch (regNum) { |
3697 | case UNW_REG_IP: |
3698 | return _registers.__regs[UNW_SPARC_O7]; |
3699 | case UNW_REG_SP: |
3700 | return _registers.__regs[UNW_SPARC_O6] + 2047; |
3701 | } |
3702 | _LIBUNWIND_ABORT("unsupported sparc64 register" ); |
3703 | } |
3704 | |
3705 | inline void Registers_sparc64::setRegister(int regNum, uint64_t value) { |
3706 | if (regNum >= UNW_SPARC_G0 && regNum <= UNW_SPARC_I7) { |
3707 | _registers.__regs[regNum] = value; |
3708 | return; |
3709 | } |
3710 | |
3711 | switch (regNum) { |
3712 | case UNW_REG_IP: |
3713 | _registers.__regs[UNW_SPARC_O7] = value; |
3714 | return; |
3715 | case UNW_REG_SP: |
3716 | _registers.__regs[UNW_SPARC_O6] = value - 2047; |
3717 | return; |
3718 | } |
3719 | _LIBUNWIND_ABORT("unsupported sparc64 register" ); |
3720 | } |
3721 | |
3722 | inline bool Registers_sparc64::validFloatRegister(int) const { return false; } |
3723 | |
3724 | inline double Registers_sparc64::getFloatRegister(int) const { |
3725 | _LIBUNWIND_ABORT("no sparc64 float registers" ); |
3726 | } |
3727 | |
3728 | inline void Registers_sparc64::setFloatRegister(int, double) { |
3729 | _LIBUNWIND_ABORT("no sparc64 float registers" ); |
3730 | } |
3731 | |
3732 | inline bool Registers_sparc64::validVectorRegister(int) const { return false; } |
3733 | |
3734 | inline v128 Registers_sparc64::getVectorRegister(int) const { |
3735 | _LIBUNWIND_ABORT("no sparc64 vector registers" ); |
3736 | } |
3737 | |
3738 | inline void Registers_sparc64::setVectorRegister(int, v128) { |
3739 | _LIBUNWIND_ABORT("no sparc64 vector registers" ); |
3740 | } |
3741 | |
3742 | inline const char *Registers_sparc64::getRegisterName(int regNum) { |
3743 | switch (regNum) { |
3744 | case UNW_REG_IP: |
3745 | return "pc" ; |
3746 | case UNW_SPARC_G0: |
3747 | return "g0" ; |
3748 | case UNW_SPARC_G1: |
3749 | return "g1" ; |
3750 | case UNW_SPARC_G2: |
3751 | return "g2" ; |
3752 | case UNW_SPARC_G3: |
3753 | return "g3" ; |
3754 | case UNW_SPARC_G4: |
3755 | return "g4" ; |
3756 | case UNW_SPARC_G5: |
3757 | return "g5" ; |
3758 | case UNW_SPARC_G6: |
3759 | return "g6" ; |
3760 | case UNW_SPARC_G7: |
3761 | return "g7" ; |
3762 | case UNW_SPARC_O0: |
3763 | return "o0" ; |
3764 | case UNW_SPARC_O1: |
3765 | return "o1" ; |
3766 | case UNW_SPARC_O2: |
3767 | return "o2" ; |
3768 | case UNW_SPARC_O3: |
3769 | return "o3" ; |
3770 | case UNW_SPARC_O4: |
3771 | return "o4" ; |
3772 | case UNW_SPARC_O5: |
3773 | return "o5" ; |
3774 | case UNW_REG_SP: |
3775 | case UNW_SPARC_O6: |
3776 | return "o6" ; |
3777 | case UNW_SPARC_O7: |
3778 | return "o7" ; |
3779 | case UNW_SPARC_L0: |
3780 | return "l0" ; |
3781 | case UNW_SPARC_L1: |
3782 | return "l1" ; |
3783 | case UNW_SPARC_L2: |
3784 | return "l2" ; |
3785 | case UNW_SPARC_L3: |
3786 | return "l3" ; |
3787 | case UNW_SPARC_L4: |
3788 | return "l4" ; |
3789 | case UNW_SPARC_L5: |
3790 | return "l5" ; |
3791 | case UNW_SPARC_L6: |
3792 | return "l6" ; |
3793 | case UNW_SPARC_L7: |
3794 | return "l7" ; |
3795 | case UNW_SPARC_I0: |
3796 | return "i0" ; |
3797 | case UNW_SPARC_I1: |
3798 | return "i1" ; |
3799 | case UNW_SPARC_I2: |
3800 | return "i2" ; |
3801 | case UNW_SPARC_I3: |
3802 | return "i3" ; |
3803 | case UNW_SPARC_I4: |
3804 | return "i4" ; |
3805 | case UNW_SPARC_I5: |
3806 | return "i5" ; |
3807 | case UNW_SPARC_I6: |
3808 | return "i6" ; |
3809 | case UNW_SPARC_I7: |
3810 | return "i7" ; |
3811 | default: |
3812 | return "unknown register" ; |
3813 | } |
3814 | } |
3815 | #endif // _LIBUNWIND_TARGET_SPARC64 |
3816 | |
3817 | #if defined(_LIBUNWIND_TARGET_HEXAGON) |
3818 | /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6 |
3819 | /// process. |
3820 | class _LIBUNWIND_HIDDEN Registers_hexagon { |
3821 | public: |
3822 | Registers_hexagon(); |
3823 | Registers_hexagon(const void *registers); |
3824 | |
3825 | bool validRegister(int num) const; |
3826 | uint32_t getRegister(int num) const; |
3827 | void setRegister(int num, uint32_t value); |
3828 | bool validFloatRegister(int num) const; |
3829 | double getFloatRegister(int num) const; |
3830 | void setFloatRegister(int num, double value); |
3831 | bool validVectorRegister(int num) const; |
3832 | v128 getVectorRegister(int num) const; |
3833 | void setVectorRegister(int num, v128 value); |
3834 | const char *getRegisterName(int num); |
3835 | void jumpto(); |
3836 | static constexpr int lastDwarfRegNum() { |
3837 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON; |
3838 | } |
3839 | static int getArch() { return REGISTERS_HEXAGON; } |
3840 | |
3841 | uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; } |
3842 | void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; } |
3843 | uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; } |
3844 | void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; } |
3845 | |
3846 | private: |
3847 | struct hexagon_thread_state_t { |
3848 | unsigned int __r[35]; |
3849 | }; |
3850 | |
3851 | hexagon_thread_state_t _registers; |
3852 | }; |
3853 | |
3854 | inline Registers_hexagon::Registers_hexagon(const void *registers) { |
3855 | static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit), |
3856 | "hexagon registers do not fit into unw_context_t" ); |
3857 | memcpy(&_registers, static_cast<const uint8_t *>(registers), |
3858 | sizeof(_registers)); |
3859 | } |
3860 | |
3861 | inline Registers_hexagon::Registers_hexagon() { |
3862 | memset(&_registers, 0, sizeof(_registers)); |
3863 | } |
3864 | |
3865 | inline bool Registers_hexagon::validRegister(int regNum) const { |
3866 | if (regNum <= UNW_HEXAGON_R31) |
3867 | return true; |
3868 | return false; |
3869 | } |
3870 | |
3871 | inline uint32_t Registers_hexagon::getRegister(int regNum) const { |
3872 | if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) |
3873 | return _registers.__r[regNum - UNW_HEXAGON_R0]; |
3874 | |
3875 | switch (regNum) { |
3876 | case UNW_REG_IP: |
3877 | return _registers.__r[UNW_HEXAGON_PC]; |
3878 | case UNW_REG_SP: |
3879 | return _registers.__r[UNW_HEXAGON_R29]; |
3880 | } |
3881 | _LIBUNWIND_ABORT("unsupported hexagon register" ); |
3882 | } |
3883 | |
3884 | inline void Registers_hexagon::setRegister(int regNum, uint32_t value) { |
3885 | if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) { |
3886 | _registers.__r[regNum - UNW_HEXAGON_R0] = value; |
3887 | return; |
3888 | } |
3889 | |
3890 | switch (regNum) { |
3891 | case UNW_REG_IP: |
3892 | _registers.__r[UNW_HEXAGON_PC] = value; |
3893 | return; |
3894 | case UNW_REG_SP: |
3895 | _registers.__r[UNW_HEXAGON_R29] = value; |
3896 | return; |
3897 | } |
3898 | _LIBUNWIND_ABORT("unsupported hexagon register" ); |
3899 | } |
3900 | |
3901 | inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const { |
3902 | return false; |
3903 | } |
3904 | |
3905 | inline double Registers_hexagon::getFloatRegister(int /* regNum */) const { |
3906 | _LIBUNWIND_ABORT("hexagon float support not implemented" ); |
3907 | } |
3908 | |
3909 | inline void Registers_hexagon::setFloatRegister(int /* regNum */, |
3910 | double /* value */) { |
3911 | _LIBUNWIND_ABORT("hexagon float support not implemented" ); |
3912 | } |
3913 | |
3914 | inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const { |
3915 | return false; |
3916 | } |
3917 | |
3918 | inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const { |
3919 | _LIBUNWIND_ABORT("hexagon vector support not implemented" ); |
3920 | } |
3921 | |
3922 | inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) { |
3923 | _LIBUNWIND_ABORT("hexagon vector support not implemented" ); |
3924 | } |
3925 | |
3926 | inline const char *Registers_hexagon::getRegisterName(int regNum) { |
3927 | switch (regNum) { |
3928 | case UNW_HEXAGON_R0: |
3929 | return "r0" ; |
3930 | case UNW_HEXAGON_R1: |
3931 | return "r1" ; |
3932 | case UNW_HEXAGON_R2: |
3933 | return "r2" ; |
3934 | case UNW_HEXAGON_R3: |
3935 | return "r3" ; |
3936 | case UNW_HEXAGON_R4: |
3937 | return "r4" ; |
3938 | case UNW_HEXAGON_R5: |
3939 | return "r5" ; |
3940 | case UNW_HEXAGON_R6: |
3941 | return "r6" ; |
3942 | case UNW_HEXAGON_R7: |
3943 | return "r7" ; |
3944 | case UNW_HEXAGON_R8: |
3945 | return "r8" ; |
3946 | case UNW_HEXAGON_R9: |
3947 | return "r9" ; |
3948 | case UNW_HEXAGON_R10: |
3949 | return "r10" ; |
3950 | case UNW_HEXAGON_R11: |
3951 | return "r11" ; |
3952 | case UNW_HEXAGON_R12: |
3953 | return "r12" ; |
3954 | case UNW_HEXAGON_R13: |
3955 | return "r13" ; |
3956 | case UNW_HEXAGON_R14: |
3957 | return "r14" ; |
3958 | case UNW_HEXAGON_R15: |
3959 | return "r15" ; |
3960 | case UNW_HEXAGON_R16: |
3961 | return "r16" ; |
3962 | case UNW_HEXAGON_R17: |
3963 | return "r17" ; |
3964 | case UNW_HEXAGON_R18: |
3965 | return "r18" ; |
3966 | case UNW_HEXAGON_R19: |
3967 | return "r19" ; |
3968 | case UNW_HEXAGON_R20: |
3969 | return "r20" ; |
3970 | case UNW_HEXAGON_R21: |
3971 | return "r21" ; |
3972 | case UNW_HEXAGON_R22: |
3973 | return "r22" ; |
3974 | case UNW_HEXAGON_R23: |
3975 | return "r23" ; |
3976 | case UNW_HEXAGON_R24: |
3977 | return "r24" ; |
3978 | case UNW_HEXAGON_R25: |
3979 | return "r25" ; |
3980 | case UNW_HEXAGON_R26: |
3981 | return "r26" ; |
3982 | case UNW_HEXAGON_R27: |
3983 | return "r27" ; |
3984 | case UNW_HEXAGON_R28: |
3985 | return "r28" ; |
3986 | case UNW_HEXAGON_R29: |
3987 | return "r29" ; |
3988 | case UNW_HEXAGON_R30: |
3989 | return "r30" ; |
3990 | case UNW_HEXAGON_R31: |
3991 | return "r31" ; |
3992 | default: |
3993 | return "unknown register" ; |
3994 | } |
3995 | |
3996 | } |
3997 | #endif // _LIBUNWIND_TARGET_HEXAGON |
3998 | |
3999 | |
4000 | #if defined(_LIBUNWIND_TARGET_RISCV) |
4001 | /// Registers_riscv holds the register state of a thread in a RISC-V |
4002 | /// process. |
4003 | |
4004 | // This check makes it safe when LIBUNWIND_ENABLE_CROSS_UNWINDING enabled. |
4005 | # ifdef __riscv |
4006 | # if __riscv_xlen == 32 |
4007 | typedef uint32_t reg_t; |
4008 | # elif __riscv_xlen == 64 |
4009 | typedef uint64_t reg_t; |
4010 | # else |
4011 | # error "Unsupported __riscv_xlen" |
4012 | # endif |
4013 | |
4014 | # if defined(__riscv_flen) |
4015 | # if __riscv_flen == 64 |
4016 | typedef double fp_t; |
4017 | # elif __riscv_flen == 32 |
4018 | typedef float fp_t; |
4019 | # else |
4020 | # error "Unsupported __riscv_flen" |
4021 | # endif |
4022 | # else |
4023 | // This is just for suppressing undeclared error of fp_t. |
4024 | typedef double fp_t; |
4025 | # endif |
4026 | # else |
4027 | // Use Max possible width when cross unwinding |
4028 | typedef uint64_t reg_t; |
4029 | typedef double fp_t; |
4030 | # define __riscv_xlen 64 |
4031 | # define __riscv_flen 64 |
4032 | #endif |
4033 | |
4034 | /// Registers_riscv holds the register state of a thread. |
4035 | class _LIBUNWIND_HIDDEN Registers_riscv { |
4036 | public: |
4037 | Registers_riscv(); |
4038 | Registers_riscv(const void *registers); |
4039 | |
4040 | bool validRegister(int num) const; |
4041 | reg_t getRegister(int num) const; |
4042 | void setRegister(int num, reg_t value); |
4043 | bool validFloatRegister(int num) const; |
4044 | fp_t getFloatRegister(int num) const; |
4045 | void setFloatRegister(int num, fp_t value); |
4046 | bool validVectorRegister(int num) const; |
4047 | v128 getVectorRegister(int num) const; |
4048 | void setVectorRegister(int num, v128 value); |
4049 | static const char *getRegisterName(int num); |
4050 | void jumpto(); |
4051 | static constexpr int lastDwarfRegNum() { |
4052 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; |
4053 | } |
4054 | static int getArch() { return REGISTERS_RISCV; } |
4055 | |
4056 | reg_t getSP() const { return _registers[2]; } |
4057 | void setSP(reg_t value) { _registers[2] = value; } |
4058 | reg_t getIP() const { return _registers[0]; } |
4059 | void setIP(reg_t value) { _registers[0] = value; } |
4060 | |
4061 | private: |
4062 | // _registers[0] holds the pc |
4063 | reg_t _registers[32]; |
4064 | # if defined(__riscv_flen) |
4065 | fp_t _floats[32]; |
4066 | # endif |
4067 | }; |
4068 | |
4069 | inline Registers_riscv::Registers_riscv(const void *registers) { |
4070 | static_assert((check_fit<Registers_riscv, unw_context_t>::does_fit), |
4071 | "riscv registers do not fit into unw_context_t" ); |
4072 | memcpy(&_registers, registers, sizeof(_registers)); |
4073 | # if __riscv_xlen == 32 |
4074 | static_assert(sizeof(_registers) == 0x80, |
4075 | "expected float registers to be at offset 128" ); |
4076 | # elif __riscv_xlen == 64 |
4077 | static_assert(sizeof(_registers) == 0x100, |
4078 | "expected float registers to be at offset 256" ); |
4079 | # else |
4080 | # error "Unexpected float registers." |
4081 | # endif |
4082 | |
4083 | # if defined(__riscv_flen) |
4084 | memcpy(_floats, |
4085 | static_cast<const uint8_t *>(registers) + sizeof(_registers), |
4086 | sizeof(_floats)); |
4087 | # endif |
4088 | } |
4089 | |
4090 | inline Registers_riscv::Registers_riscv() { |
4091 | memset(&_registers, 0, sizeof(_registers)); |
4092 | # if defined(__riscv_flen) |
4093 | memset(&_floats, 0, sizeof(_floats)); |
4094 | # endif |
4095 | } |
4096 | |
4097 | inline bool Registers_riscv::validRegister(int regNum) const { |
4098 | if (regNum == UNW_REG_IP) |
4099 | return true; |
4100 | if (regNum == UNW_REG_SP) |
4101 | return true; |
4102 | if (regNum < 0) |
4103 | return false; |
4104 | if (regNum == UNW_RISCV_VLENB) |
4105 | return true; |
4106 | if (regNum > UNW_RISCV_F31) |
4107 | return false; |
4108 | return true; |
4109 | } |
4110 | |
4111 | inline reg_t Registers_riscv::getRegister(int regNum) const { |
4112 | if (regNum == UNW_REG_IP) |
4113 | return _registers[0]; |
4114 | if (regNum == UNW_REG_SP) |
4115 | return _registers[2]; |
4116 | if (regNum == UNW_RISCV_X0) |
4117 | return 0; |
4118 | if ((regNum > 0) && (regNum < 32)) |
4119 | return _registers[regNum]; |
4120 | if (regNum == UNW_RISCV_VLENB) { |
4121 | reg_t vlenb; |
4122 | __asm__("csrr %0, 0xC22" : "=r" (vlenb)); |
4123 | return vlenb; |
4124 | } |
4125 | _LIBUNWIND_ABORT("unsupported riscv register" ); |
4126 | } |
4127 | |
4128 | inline void Registers_riscv::setRegister(int regNum, reg_t value) { |
4129 | if (regNum == UNW_REG_IP) |
4130 | _registers[0] = value; |
4131 | else if (regNum == UNW_REG_SP) |
4132 | _registers[2] = value; |
4133 | else if (regNum == UNW_RISCV_X0) |
4134 | /* x0 is hardwired to zero */ |
4135 | return; |
4136 | else if ((regNum > 0) && (regNum < 32)) |
4137 | _registers[regNum] = value; |
4138 | else |
4139 | _LIBUNWIND_ABORT("unsupported riscv register" ); |
4140 | } |
4141 | |
4142 | inline const char *Registers_riscv::getRegisterName(int regNum) { |
4143 | switch (regNum) { |
4144 | case UNW_REG_IP: |
4145 | return "pc" ; |
4146 | case UNW_REG_SP: |
4147 | return "sp" ; |
4148 | case UNW_RISCV_X0: |
4149 | return "zero" ; |
4150 | case UNW_RISCV_X1: |
4151 | return "ra" ; |
4152 | case UNW_RISCV_X2: |
4153 | return "sp" ; |
4154 | case UNW_RISCV_X3: |
4155 | return "gp" ; |
4156 | case UNW_RISCV_X4: |
4157 | return "tp" ; |
4158 | case UNW_RISCV_X5: |
4159 | return "t0" ; |
4160 | case UNW_RISCV_X6: |
4161 | return "t1" ; |
4162 | case UNW_RISCV_X7: |
4163 | return "t2" ; |
4164 | case UNW_RISCV_X8: |
4165 | return "s0" ; |
4166 | case UNW_RISCV_X9: |
4167 | return "s1" ; |
4168 | case UNW_RISCV_X10: |
4169 | return "a0" ; |
4170 | case UNW_RISCV_X11: |
4171 | return "a1" ; |
4172 | case UNW_RISCV_X12: |
4173 | return "a2" ; |
4174 | case UNW_RISCV_X13: |
4175 | return "a3" ; |
4176 | case UNW_RISCV_X14: |
4177 | return "a4" ; |
4178 | case UNW_RISCV_X15: |
4179 | return "a5" ; |
4180 | case UNW_RISCV_X16: |
4181 | return "a6" ; |
4182 | case UNW_RISCV_X17: |
4183 | return "a7" ; |
4184 | case UNW_RISCV_X18: |
4185 | return "s2" ; |
4186 | case UNW_RISCV_X19: |
4187 | return "s3" ; |
4188 | case UNW_RISCV_X20: |
4189 | return "s4" ; |
4190 | case UNW_RISCV_X21: |
4191 | return "s5" ; |
4192 | case UNW_RISCV_X22: |
4193 | return "s6" ; |
4194 | case UNW_RISCV_X23: |
4195 | return "s7" ; |
4196 | case UNW_RISCV_X24: |
4197 | return "s8" ; |
4198 | case UNW_RISCV_X25: |
4199 | return "s9" ; |
4200 | case UNW_RISCV_X26: |
4201 | return "s10" ; |
4202 | case UNW_RISCV_X27: |
4203 | return "s11" ; |
4204 | case UNW_RISCV_X28: |
4205 | return "t3" ; |
4206 | case UNW_RISCV_X29: |
4207 | return "t4" ; |
4208 | case UNW_RISCV_X30: |
4209 | return "t5" ; |
4210 | case UNW_RISCV_X31: |
4211 | return "t6" ; |
4212 | case UNW_RISCV_F0: |
4213 | return "ft0" ; |
4214 | case UNW_RISCV_F1: |
4215 | return "ft1" ; |
4216 | case UNW_RISCV_F2: |
4217 | return "ft2" ; |
4218 | case UNW_RISCV_F3: |
4219 | return "ft3" ; |
4220 | case UNW_RISCV_F4: |
4221 | return "ft4" ; |
4222 | case UNW_RISCV_F5: |
4223 | return "ft5" ; |
4224 | case UNW_RISCV_F6: |
4225 | return "ft6" ; |
4226 | case UNW_RISCV_F7: |
4227 | return "ft7" ; |
4228 | case UNW_RISCV_F8: |
4229 | return "fs0" ; |
4230 | case UNW_RISCV_F9: |
4231 | return "fs1" ; |
4232 | case UNW_RISCV_F10: |
4233 | return "fa0" ; |
4234 | case UNW_RISCV_F11: |
4235 | return "fa1" ; |
4236 | case UNW_RISCV_F12: |
4237 | return "fa2" ; |
4238 | case UNW_RISCV_F13: |
4239 | return "fa3" ; |
4240 | case UNW_RISCV_F14: |
4241 | return "fa4" ; |
4242 | case UNW_RISCV_F15: |
4243 | return "fa5" ; |
4244 | case UNW_RISCV_F16: |
4245 | return "fa6" ; |
4246 | case UNW_RISCV_F17: |
4247 | return "fa7" ; |
4248 | case UNW_RISCV_F18: |
4249 | return "fs2" ; |
4250 | case UNW_RISCV_F19: |
4251 | return "fs3" ; |
4252 | case UNW_RISCV_F20: |
4253 | return "fs4" ; |
4254 | case UNW_RISCV_F21: |
4255 | return "fs5" ; |
4256 | case UNW_RISCV_F22: |
4257 | return "fs6" ; |
4258 | case UNW_RISCV_F23: |
4259 | return "fs7" ; |
4260 | case UNW_RISCV_F24: |
4261 | return "fs8" ; |
4262 | case UNW_RISCV_F25: |
4263 | return "fs9" ; |
4264 | case UNW_RISCV_F26: |
4265 | return "fs10" ; |
4266 | case UNW_RISCV_F27: |
4267 | return "fs11" ; |
4268 | case UNW_RISCV_F28: |
4269 | return "ft8" ; |
4270 | case UNW_RISCV_F29: |
4271 | return "ft9" ; |
4272 | case UNW_RISCV_F30: |
4273 | return "ft10" ; |
4274 | case UNW_RISCV_F31: |
4275 | return "ft11" ; |
4276 | case UNW_RISCV_VLENB: |
4277 | return "vlenb" ; |
4278 | default: |
4279 | return "unknown register" ; |
4280 | } |
4281 | } |
4282 | |
4283 | inline bool Registers_riscv::validFloatRegister(int regNum) const { |
4284 | # if defined(__riscv_flen) |
4285 | if (regNum < UNW_RISCV_F0) |
4286 | return false; |
4287 | if (regNum > UNW_RISCV_F31) |
4288 | return false; |
4289 | return true; |
4290 | # else |
4291 | (void)regNum; |
4292 | return false; |
4293 | # endif |
4294 | } |
4295 | |
4296 | inline fp_t Registers_riscv::getFloatRegister(int regNum) const { |
4297 | # if defined(__riscv_flen) |
4298 | assert(validFloatRegister(regNum)); |
4299 | return _floats[regNum - UNW_RISCV_F0]; |
4300 | # else |
4301 | (void)regNum; |
4302 | _LIBUNWIND_ABORT("libunwind not built with float support" ); |
4303 | # endif |
4304 | } |
4305 | |
4306 | inline void Registers_riscv::setFloatRegister(int regNum, fp_t value) { |
4307 | # if defined(__riscv_flen) |
4308 | assert(validFloatRegister(regNum)); |
4309 | _floats[regNum - UNW_RISCV_F0] = value; |
4310 | # else |
4311 | (void)regNum; |
4312 | (void)value; |
4313 | _LIBUNWIND_ABORT("libunwind not built with float support" ); |
4314 | # endif |
4315 | } |
4316 | |
4317 | inline bool Registers_riscv::validVectorRegister(int) const { |
4318 | return false; |
4319 | } |
4320 | |
4321 | inline v128 Registers_riscv::getVectorRegister(int) const { |
4322 | _LIBUNWIND_ABORT("no riscv vector register support yet" ); |
4323 | } |
4324 | |
4325 | inline void Registers_riscv::setVectorRegister(int, v128) { |
4326 | _LIBUNWIND_ABORT("no riscv vector register support yet" ); |
4327 | } |
4328 | #endif // _LIBUNWIND_TARGET_RISCV |
4329 | |
4330 | #if defined(_LIBUNWIND_TARGET_VE) |
4331 | /// Registers_ve holds the register state of a thread in a VE process. |
4332 | class _LIBUNWIND_HIDDEN Registers_ve { |
4333 | public: |
4334 | Registers_ve(); |
4335 | Registers_ve(const void *registers); |
4336 | |
4337 | bool validRegister(int num) const; |
4338 | uint64_t getRegister(int num) const; |
4339 | void setRegister(int num, uint64_t value); |
4340 | bool validFloatRegister(int num) const; |
4341 | double getFloatRegister(int num) const; |
4342 | void setFloatRegister(int num, double value); |
4343 | bool validVectorRegister(int num) const; |
4344 | v128 getVectorRegister(int num) const; |
4345 | void setVectorRegister(int num, v128 value); |
4346 | static const char *getRegisterName(int num); |
4347 | void jumpto(); |
4348 | static constexpr int lastDwarfRegNum() { |
4349 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE; |
4350 | } |
4351 | static int getArch() { return REGISTERS_VE; } |
4352 | |
4353 | uint64_t getSP() const { return _registers.__s[11]; } |
4354 | void setSP(uint64_t value) { _registers.__s[11] = value; } |
4355 | uint64_t getIP() const { return _registers.__ic; } |
4356 | void setIP(uint64_t value) { _registers.__ic = value; } |
4357 | |
4358 | private: |
4359 | // FIXME: Need to store not only scalar registers but also vector and vector |
4360 | // mask registers. VEOS uses mcontext_t defined in ucontext.h. It takes |
4361 | // 524288 bytes (65536*8 bytes), though. Currently, we use libunwind for |
4362 | // SjLj exception support only, so Registers_ve is not implemented completely. |
4363 | struct ve_thread_state_t { |
4364 | uint64_t __s[64]; // s0-s64 |
4365 | uint64_t __ic; // Instruction counter (IC) |
4366 | uint64_t __vixr; // Vector Index Register |
4367 | uint64_t __vl; // Vector Length Register |
4368 | }; |
4369 | |
4370 | ve_thread_state_t _registers; // total 67 registers |
4371 | |
4372 | // Currently no vector register is preserved. |
4373 | }; |
4374 | |
4375 | inline Registers_ve::Registers_ve(const void *registers) { |
4376 | static_assert((check_fit<Registers_ve, unw_context_t>::does_fit), |
4377 | "ve registers do not fit into unw_context_t" ); |
4378 | memcpy(&_registers, static_cast<const uint8_t *>(registers), |
4379 | sizeof(_registers)); |
4380 | static_assert(sizeof(_registers) == 536, |
4381 | "expected vector register offset to be 536" ); |
4382 | } |
4383 | |
4384 | inline Registers_ve::Registers_ve() { |
4385 | memset(&_registers, 0, sizeof(_registers)); |
4386 | } |
4387 | |
4388 | inline bool Registers_ve::validRegister(int regNum) const { |
4389 | if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) |
4390 | return true; |
4391 | |
4392 | switch (regNum) { |
4393 | case UNW_REG_IP: |
4394 | case UNW_REG_SP: |
4395 | case UNW_VE_VIXR: |
4396 | case UNW_VE_VL: |
4397 | return true; |
4398 | default: |
4399 | return false; |
4400 | } |
4401 | } |
4402 | |
4403 | inline uint64_t Registers_ve::getRegister(int regNum) const { |
4404 | if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) |
4405 | return _registers.__s[regNum - UNW_VE_S0]; |
4406 | |
4407 | switch (regNum) { |
4408 | case UNW_REG_IP: |
4409 | return _registers.__ic; |
4410 | case UNW_REG_SP: |
4411 | return _registers.__s[11]; |
4412 | case UNW_VE_VIXR: |
4413 | return _registers.__vixr; |
4414 | case UNW_VE_VL: |
4415 | return _registers.__vl; |
4416 | } |
4417 | _LIBUNWIND_ABORT("unsupported ve register" ); |
4418 | } |
4419 | |
4420 | inline void Registers_ve::setRegister(int regNum, uint64_t value) { |
4421 | if (regNum >= UNW_VE_S0 && regNum <= UNW_VE_S63) { |
4422 | _registers.__s[regNum - UNW_VE_S0] = value; |
4423 | return; |
4424 | } |
4425 | |
4426 | switch (regNum) { |
4427 | case UNW_REG_IP: |
4428 | _registers.__ic = value; |
4429 | return; |
4430 | case UNW_REG_SP: |
4431 | _registers.__s[11] = value; |
4432 | return; |
4433 | case UNW_VE_VIXR: |
4434 | _registers.__vixr = value; |
4435 | return; |
4436 | case UNW_VE_VL: |
4437 | _registers.__vl = value; |
4438 | return; |
4439 | } |
4440 | _LIBUNWIND_ABORT("unsupported ve register" ); |
4441 | } |
4442 | |
4443 | inline bool Registers_ve::validFloatRegister(int /* regNum */) const { |
4444 | return false; |
4445 | } |
4446 | |
4447 | inline double Registers_ve::getFloatRegister(int /* regNum */) const { |
4448 | _LIBUNWIND_ABORT("VE doesn't have float registers" ); |
4449 | } |
4450 | |
4451 | inline void Registers_ve::setFloatRegister(int /* regNum */, |
4452 | double /* value */) { |
4453 | _LIBUNWIND_ABORT("VE doesn't have float registers" ); |
4454 | } |
4455 | |
4456 | inline bool Registers_ve::validVectorRegister(int /* regNum */) const { |
4457 | return false; |
4458 | } |
4459 | |
4460 | inline v128 Registers_ve::getVectorRegister(int /* regNum */) const { |
4461 | _LIBUNWIND_ABORT("VE vector support not implemented" ); |
4462 | } |
4463 | |
4464 | inline void Registers_ve::setVectorRegister(int /* regNum */, |
4465 | v128 /* value */) { |
4466 | _LIBUNWIND_ABORT("VE vector support not implemented" ); |
4467 | } |
4468 | |
4469 | inline const char *Registers_ve::getRegisterName(int regNum) { |
4470 | switch (regNum) { |
4471 | case UNW_REG_IP: |
4472 | return "ip" ; |
4473 | case UNW_REG_SP: |
4474 | return "sp" ; |
4475 | case UNW_VE_VIXR: |
4476 | return "vixr" ; |
4477 | case UNW_VE_VL: |
4478 | return "vl" ; |
4479 | case UNW_VE_S0: |
4480 | return "s0" ; |
4481 | case UNW_VE_S1: |
4482 | return "s1" ; |
4483 | case UNW_VE_S2: |
4484 | return "s2" ; |
4485 | case UNW_VE_S3: |
4486 | return "s3" ; |
4487 | case UNW_VE_S4: |
4488 | return "s4" ; |
4489 | case UNW_VE_S5: |
4490 | return "s5" ; |
4491 | case UNW_VE_S6: |
4492 | return "s6" ; |
4493 | case UNW_VE_S7: |
4494 | return "s7" ; |
4495 | case UNW_VE_S8: |
4496 | return "s8" ; |
4497 | case UNW_VE_S9: |
4498 | return "s9" ; |
4499 | case UNW_VE_S10: |
4500 | return "s10" ; |
4501 | case UNW_VE_S11: |
4502 | return "s11" ; |
4503 | case UNW_VE_S12: |
4504 | return "s12" ; |
4505 | case UNW_VE_S13: |
4506 | return "s13" ; |
4507 | case UNW_VE_S14: |
4508 | return "s14" ; |
4509 | case UNW_VE_S15: |
4510 | return "s15" ; |
4511 | case UNW_VE_S16: |
4512 | return "s16" ; |
4513 | case UNW_VE_S17: |
4514 | return "s17" ; |
4515 | case UNW_VE_S18: |
4516 | return "s18" ; |
4517 | case UNW_VE_S19: |
4518 | return "s19" ; |
4519 | case UNW_VE_S20: |
4520 | return "s20" ; |
4521 | case UNW_VE_S21: |
4522 | return "s21" ; |
4523 | case UNW_VE_S22: |
4524 | return "s22" ; |
4525 | case UNW_VE_S23: |
4526 | return "s23" ; |
4527 | case UNW_VE_S24: |
4528 | return "s24" ; |
4529 | case UNW_VE_S25: |
4530 | return "s25" ; |
4531 | case UNW_VE_S26: |
4532 | return "s26" ; |
4533 | case UNW_VE_S27: |
4534 | return "s27" ; |
4535 | case UNW_VE_S28: |
4536 | return "s28" ; |
4537 | case UNW_VE_S29: |
4538 | return "s29" ; |
4539 | case UNW_VE_S30: |
4540 | return "s30" ; |
4541 | case UNW_VE_S31: |
4542 | return "s31" ; |
4543 | case UNW_VE_S32: |
4544 | return "s32" ; |
4545 | case UNW_VE_S33: |
4546 | return "s33" ; |
4547 | case UNW_VE_S34: |
4548 | return "s34" ; |
4549 | case UNW_VE_S35: |
4550 | return "s35" ; |
4551 | case UNW_VE_S36: |
4552 | return "s36" ; |
4553 | case UNW_VE_S37: |
4554 | return "s37" ; |
4555 | case UNW_VE_S38: |
4556 | return "s38" ; |
4557 | case UNW_VE_S39: |
4558 | return "s39" ; |
4559 | case UNW_VE_S40: |
4560 | return "s40" ; |
4561 | case UNW_VE_S41: |
4562 | return "s41" ; |
4563 | case UNW_VE_S42: |
4564 | return "s42" ; |
4565 | case UNW_VE_S43: |
4566 | return "s43" ; |
4567 | case UNW_VE_S44: |
4568 | return "s44" ; |
4569 | case UNW_VE_S45: |
4570 | return "s45" ; |
4571 | case UNW_VE_S46: |
4572 | return "s46" ; |
4573 | case UNW_VE_S47: |
4574 | return "s47" ; |
4575 | case UNW_VE_S48: |
4576 | return "s48" ; |
4577 | case UNW_VE_S49: |
4578 | return "s49" ; |
4579 | case UNW_VE_S50: |
4580 | return "s50" ; |
4581 | case UNW_VE_S51: |
4582 | return "s51" ; |
4583 | case UNW_VE_S52: |
4584 | return "s52" ; |
4585 | case UNW_VE_S53: |
4586 | return "s53" ; |
4587 | case UNW_VE_S54: |
4588 | return "s54" ; |
4589 | case UNW_VE_S55: |
4590 | return "s55" ; |
4591 | case UNW_VE_S56: |
4592 | return "s56" ; |
4593 | case UNW_VE_S57: |
4594 | return "s57" ; |
4595 | case UNW_VE_S58: |
4596 | return "s58" ; |
4597 | case UNW_VE_S59: |
4598 | return "s59" ; |
4599 | case UNW_VE_S60: |
4600 | return "s60" ; |
4601 | case UNW_VE_S61: |
4602 | return "s61" ; |
4603 | case UNW_VE_S62: |
4604 | return "s62" ; |
4605 | case UNW_VE_S63: |
4606 | return "s63" ; |
4607 | case UNW_VE_V0: |
4608 | return "v0" ; |
4609 | case UNW_VE_V1: |
4610 | return "v1" ; |
4611 | case UNW_VE_V2: |
4612 | return "v2" ; |
4613 | case UNW_VE_V3: |
4614 | return "v3" ; |
4615 | case UNW_VE_V4: |
4616 | return "v4" ; |
4617 | case UNW_VE_V5: |
4618 | return "v5" ; |
4619 | case UNW_VE_V6: |
4620 | return "v6" ; |
4621 | case UNW_VE_V7: |
4622 | return "v7" ; |
4623 | case UNW_VE_V8: |
4624 | return "v8" ; |
4625 | case UNW_VE_V9: |
4626 | return "v9" ; |
4627 | case UNW_VE_V10: |
4628 | return "v10" ; |
4629 | case UNW_VE_V11: |
4630 | return "v11" ; |
4631 | case UNW_VE_V12: |
4632 | return "v12" ; |
4633 | case UNW_VE_V13: |
4634 | return "v13" ; |
4635 | case UNW_VE_V14: |
4636 | return "v14" ; |
4637 | case UNW_VE_V15: |
4638 | return "v15" ; |
4639 | case UNW_VE_V16: |
4640 | return "v16" ; |
4641 | case UNW_VE_V17: |
4642 | return "v17" ; |
4643 | case UNW_VE_V18: |
4644 | return "v18" ; |
4645 | case UNW_VE_V19: |
4646 | return "v19" ; |
4647 | case UNW_VE_V20: |
4648 | return "v20" ; |
4649 | case UNW_VE_V21: |
4650 | return "v21" ; |
4651 | case UNW_VE_V22: |
4652 | return "v22" ; |
4653 | case UNW_VE_V23: |
4654 | return "v23" ; |
4655 | case UNW_VE_V24: |
4656 | return "v24" ; |
4657 | case UNW_VE_V25: |
4658 | return "v25" ; |
4659 | case UNW_VE_V26: |
4660 | return "v26" ; |
4661 | case UNW_VE_V27: |
4662 | return "v27" ; |
4663 | case UNW_VE_V28: |
4664 | return "v28" ; |
4665 | case UNW_VE_V29: |
4666 | return "v29" ; |
4667 | case UNW_VE_V30: |
4668 | return "v30" ; |
4669 | case UNW_VE_V31: |
4670 | return "v31" ; |
4671 | case UNW_VE_V32: |
4672 | return "v32" ; |
4673 | case UNW_VE_V33: |
4674 | return "v33" ; |
4675 | case UNW_VE_V34: |
4676 | return "v34" ; |
4677 | case UNW_VE_V35: |
4678 | return "v35" ; |
4679 | case UNW_VE_V36: |
4680 | return "v36" ; |
4681 | case UNW_VE_V37: |
4682 | return "v37" ; |
4683 | case UNW_VE_V38: |
4684 | return "v38" ; |
4685 | case UNW_VE_V39: |
4686 | return "v39" ; |
4687 | case UNW_VE_V40: |
4688 | return "v40" ; |
4689 | case UNW_VE_V41: |
4690 | return "v41" ; |
4691 | case UNW_VE_V42: |
4692 | return "v42" ; |
4693 | case UNW_VE_V43: |
4694 | return "v43" ; |
4695 | case UNW_VE_V44: |
4696 | return "v44" ; |
4697 | case UNW_VE_V45: |
4698 | return "v45" ; |
4699 | case UNW_VE_V46: |
4700 | return "v46" ; |
4701 | case UNW_VE_V47: |
4702 | return "v47" ; |
4703 | case UNW_VE_V48: |
4704 | return "v48" ; |
4705 | case UNW_VE_V49: |
4706 | return "v49" ; |
4707 | case UNW_VE_V50: |
4708 | return "v50" ; |
4709 | case UNW_VE_V51: |
4710 | return "v51" ; |
4711 | case UNW_VE_V52: |
4712 | return "v52" ; |
4713 | case UNW_VE_V53: |
4714 | return "v53" ; |
4715 | case UNW_VE_V54: |
4716 | return "v54" ; |
4717 | case UNW_VE_V55: |
4718 | return "v55" ; |
4719 | case UNW_VE_V56: |
4720 | return "v56" ; |
4721 | case UNW_VE_V57: |
4722 | return "v57" ; |
4723 | case UNW_VE_V58: |
4724 | return "v58" ; |
4725 | case UNW_VE_V59: |
4726 | return "v59" ; |
4727 | case UNW_VE_V60: |
4728 | return "v60" ; |
4729 | case UNW_VE_V61: |
4730 | return "v61" ; |
4731 | case UNW_VE_V62: |
4732 | return "v62" ; |
4733 | case UNW_VE_V63: |
4734 | return "v63" ; |
4735 | case UNW_VE_VM0: |
4736 | return "vm0" ; |
4737 | case UNW_VE_VM1: |
4738 | return "vm1" ; |
4739 | case UNW_VE_VM2: |
4740 | return "vm2" ; |
4741 | case UNW_VE_VM3: |
4742 | return "vm3" ; |
4743 | case UNW_VE_VM4: |
4744 | return "vm4" ; |
4745 | case UNW_VE_VM5: |
4746 | return "vm5" ; |
4747 | case UNW_VE_VM6: |
4748 | return "vm6" ; |
4749 | case UNW_VE_VM7: |
4750 | return "vm7" ; |
4751 | case UNW_VE_VM8: |
4752 | return "vm8" ; |
4753 | case UNW_VE_VM9: |
4754 | return "vm9" ; |
4755 | case UNW_VE_VM10: |
4756 | return "vm10" ; |
4757 | case UNW_VE_VM11: |
4758 | return "vm11" ; |
4759 | case UNW_VE_VM12: |
4760 | return "vm12" ; |
4761 | case UNW_VE_VM13: |
4762 | return "vm13" ; |
4763 | case UNW_VE_VM14: |
4764 | return "vm14" ; |
4765 | case UNW_VE_VM15: |
4766 | return "vm15" ; |
4767 | } |
4768 | return "unknown register" ; |
4769 | } |
4770 | #endif // _LIBUNWIND_TARGET_VE |
4771 | |
4772 | #if defined(_LIBUNWIND_TARGET_S390X) |
4773 | /// Registers_s390x holds the register state of a thread in a |
4774 | /// 64-bit Linux on IBM zSystems process. |
4775 | class _LIBUNWIND_HIDDEN Registers_s390x { |
4776 | public: |
4777 | Registers_s390x(); |
4778 | Registers_s390x(const void *registers); |
4779 | |
4780 | bool validRegister(int num) const; |
4781 | uint64_t getRegister(int num) const; |
4782 | void setRegister(int num, uint64_t value); |
4783 | bool validFloatRegister(int num) const; |
4784 | double getFloatRegister(int num) const; |
4785 | void setFloatRegister(int num, double value); |
4786 | bool validVectorRegister(int num) const; |
4787 | v128 getVectorRegister(int num) const; |
4788 | void setVectorRegister(int num, v128 value); |
4789 | static const char *getRegisterName(int num); |
4790 | void jumpto(); |
4791 | static constexpr int lastDwarfRegNum() { |
4792 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X; |
4793 | } |
4794 | static int getArch() { return REGISTERS_S390X; } |
4795 | |
4796 | uint64_t getSP() const { return _registers.__gpr[15]; } |
4797 | void setSP(uint64_t value) { _registers.__gpr[15] = value; } |
4798 | uint64_t getIP() const { return _registers.__pswa; } |
4799 | void setIP(uint64_t value) { _registers.__pswa = value; } |
4800 | |
4801 | private: |
4802 | struct s390x_thread_state_t { |
4803 | uint64_t __pswm; // Problem Status Word: Mask |
4804 | uint64_t __pswa; // Problem Status Word: Address (PC) |
4805 | uint64_t __gpr[16]; // General Purpose Registers |
4806 | double __fpr[16]; // Floating-Point Registers |
4807 | }; |
4808 | |
4809 | s390x_thread_state_t _registers; |
4810 | }; |
4811 | |
4812 | inline Registers_s390x::Registers_s390x(const void *registers) { |
4813 | static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit), |
4814 | "s390x registers do not fit into unw_context_t" ); |
4815 | memcpy(&_registers, static_cast<const uint8_t *>(registers), |
4816 | sizeof(_registers)); |
4817 | } |
4818 | |
4819 | inline Registers_s390x::Registers_s390x() { |
4820 | memset(&_registers, 0, sizeof(_registers)); |
4821 | } |
4822 | |
4823 | inline bool Registers_s390x::validRegister(int regNum) const { |
4824 | switch (regNum) { |
4825 | case UNW_S390X_PSWM: |
4826 | case UNW_S390X_PSWA: |
4827 | case UNW_REG_IP: |
4828 | case UNW_REG_SP: |
4829 | return true; |
4830 | } |
4831 | |
4832 | if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) |
4833 | return true; |
4834 | |
4835 | return false; |
4836 | } |
4837 | |
4838 | inline uint64_t Registers_s390x::getRegister(int regNum) const { |
4839 | if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) |
4840 | return _registers.__gpr[regNum - UNW_S390X_R0]; |
4841 | |
4842 | switch (regNum) { |
4843 | case UNW_S390X_PSWM: |
4844 | return _registers.__pswm; |
4845 | case UNW_S390X_PSWA: |
4846 | case UNW_REG_IP: |
4847 | return _registers.__pswa; |
4848 | case UNW_REG_SP: |
4849 | return _registers.__gpr[15]; |
4850 | } |
4851 | _LIBUNWIND_ABORT("unsupported s390x register" ); |
4852 | } |
4853 | |
4854 | inline void Registers_s390x::setRegister(int regNum, uint64_t value) { |
4855 | if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) { |
4856 | _registers.__gpr[regNum - UNW_S390X_R0] = value; |
4857 | return; |
4858 | } |
4859 | |
4860 | switch (regNum) { |
4861 | case UNW_S390X_PSWM: |
4862 | _registers.__pswm = value; |
4863 | return; |
4864 | case UNW_S390X_PSWA: |
4865 | case UNW_REG_IP: |
4866 | _registers.__pswa = value; |
4867 | return; |
4868 | case UNW_REG_SP: |
4869 | _registers.__gpr[15] = value; |
4870 | return; |
4871 | } |
4872 | _LIBUNWIND_ABORT("unsupported s390x register" ); |
4873 | } |
4874 | |
4875 | inline bool Registers_s390x::validFloatRegister(int regNum) const { |
4876 | return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15; |
4877 | } |
4878 | |
4879 | inline double Registers_s390x::getFloatRegister(int regNum) const { |
4880 | // NOTE: FPR DWARF register numbers are not consecutive. |
4881 | switch (regNum) { |
4882 | case UNW_S390X_F0: |
4883 | return _registers.__fpr[0]; |
4884 | case UNW_S390X_F1: |
4885 | return _registers.__fpr[1]; |
4886 | case UNW_S390X_F2: |
4887 | return _registers.__fpr[2]; |
4888 | case UNW_S390X_F3: |
4889 | return _registers.__fpr[3]; |
4890 | case UNW_S390X_F4: |
4891 | return _registers.__fpr[4]; |
4892 | case UNW_S390X_F5: |
4893 | return _registers.__fpr[5]; |
4894 | case UNW_S390X_F6: |
4895 | return _registers.__fpr[6]; |
4896 | case UNW_S390X_F7: |
4897 | return _registers.__fpr[7]; |
4898 | case UNW_S390X_F8: |
4899 | return _registers.__fpr[8]; |
4900 | case UNW_S390X_F9: |
4901 | return _registers.__fpr[9]; |
4902 | case UNW_S390X_F10: |
4903 | return _registers.__fpr[10]; |
4904 | case UNW_S390X_F11: |
4905 | return _registers.__fpr[11]; |
4906 | case UNW_S390X_F12: |
4907 | return _registers.__fpr[12]; |
4908 | case UNW_S390X_F13: |
4909 | return _registers.__fpr[13]; |
4910 | case UNW_S390X_F14: |
4911 | return _registers.__fpr[14]; |
4912 | case UNW_S390X_F15: |
4913 | return _registers.__fpr[15]; |
4914 | } |
4915 | _LIBUNWIND_ABORT("unsupported s390x register" ); |
4916 | } |
4917 | |
4918 | inline void Registers_s390x::setFloatRegister(int regNum, double value) { |
4919 | // NOTE: FPR DWARF register numbers are not consecutive. |
4920 | switch (regNum) { |
4921 | case UNW_S390X_F0: |
4922 | _registers.__fpr[0] = value; |
4923 | return; |
4924 | case UNW_S390X_F1: |
4925 | _registers.__fpr[1] = value; |
4926 | return; |
4927 | case UNW_S390X_F2: |
4928 | _registers.__fpr[2] = value; |
4929 | return; |
4930 | case UNW_S390X_F3: |
4931 | _registers.__fpr[3] = value; |
4932 | return; |
4933 | case UNW_S390X_F4: |
4934 | _registers.__fpr[4] = value; |
4935 | return; |
4936 | case UNW_S390X_F5: |
4937 | _registers.__fpr[5] = value; |
4938 | return; |
4939 | case UNW_S390X_F6: |
4940 | _registers.__fpr[6] = value; |
4941 | return; |
4942 | case UNW_S390X_F7: |
4943 | _registers.__fpr[7] = value; |
4944 | return; |
4945 | case UNW_S390X_F8: |
4946 | _registers.__fpr[8] = value; |
4947 | return; |
4948 | case UNW_S390X_F9: |
4949 | _registers.__fpr[9] = value; |
4950 | return; |
4951 | case UNW_S390X_F10: |
4952 | _registers.__fpr[10] = value; |
4953 | return; |
4954 | case UNW_S390X_F11: |
4955 | _registers.__fpr[11] = value; |
4956 | return; |
4957 | case UNW_S390X_F12: |
4958 | _registers.__fpr[12] = value; |
4959 | return; |
4960 | case UNW_S390X_F13: |
4961 | _registers.__fpr[13] = value; |
4962 | return; |
4963 | case UNW_S390X_F14: |
4964 | _registers.__fpr[14] = value; |
4965 | return; |
4966 | case UNW_S390X_F15: |
4967 | _registers.__fpr[15] = value; |
4968 | return; |
4969 | } |
4970 | _LIBUNWIND_ABORT("unsupported s390x register" ); |
4971 | } |
4972 | |
4973 | inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const { |
4974 | return false; |
4975 | } |
4976 | |
4977 | inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const { |
4978 | _LIBUNWIND_ABORT("s390x vector support not implemented" ); |
4979 | } |
4980 | |
4981 | inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) { |
4982 | _LIBUNWIND_ABORT("s390x vector support not implemented" ); |
4983 | } |
4984 | |
4985 | inline const char *Registers_s390x::getRegisterName(int regNum) { |
4986 | switch (regNum) { |
4987 | case UNW_REG_IP: |
4988 | return "ip" ; |
4989 | case UNW_REG_SP: |
4990 | return "sp" ; |
4991 | case UNW_S390X_R0: |
4992 | return "r0" ; |
4993 | case UNW_S390X_R1: |
4994 | return "r1" ; |
4995 | case UNW_S390X_R2: |
4996 | return "r2" ; |
4997 | case UNW_S390X_R3: |
4998 | return "r3" ; |
4999 | case UNW_S390X_R4: |
5000 | return "r4" ; |
5001 | case UNW_S390X_R5: |
5002 | return "r5" ; |
5003 | case UNW_S390X_R6: |
5004 | return "r6" ; |
5005 | case UNW_S390X_R7: |
5006 | return "r7" ; |
5007 | case UNW_S390X_R8: |
5008 | return "r8" ; |
5009 | case UNW_S390X_R9: |
5010 | return "r9" ; |
5011 | case UNW_S390X_R10: |
5012 | return "r10" ; |
5013 | case UNW_S390X_R11: |
5014 | return "r11" ; |
5015 | case UNW_S390X_R12: |
5016 | return "r12" ; |
5017 | case UNW_S390X_R13: |
5018 | return "r13" ; |
5019 | case UNW_S390X_R14: |
5020 | return "r14" ; |
5021 | case UNW_S390X_R15: |
5022 | return "r15" ; |
5023 | case UNW_S390X_F0: |
5024 | return "f0" ; |
5025 | case UNW_S390X_F1: |
5026 | return "f1" ; |
5027 | case UNW_S390X_F2: |
5028 | return "f2" ; |
5029 | case UNW_S390X_F3: |
5030 | return "f3" ; |
5031 | case UNW_S390X_F4: |
5032 | return "f4" ; |
5033 | case UNW_S390X_F5: |
5034 | return "f5" ; |
5035 | case UNW_S390X_F6: |
5036 | return "f6" ; |
5037 | case UNW_S390X_F7: |
5038 | return "f7" ; |
5039 | case UNW_S390X_F8: |
5040 | return "f8" ; |
5041 | case UNW_S390X_F9: |
5042 | return "f9" ; |
5043 | case UNW_S390X_F10: |
5044 | return "f10" ; |
5045 | case UNW_S390X_F11: |
5046 | return "f11" ; |
5047 | case UNW_S390X_F12: |
5048 | return "f12" ; |
5049 | case UNW_S390X_F13: |
5050 | return "f13" ; |
5051 | case UNW_S390X_F14: |
5052 | return "f14" ; |
5053 | case UNW_S390X_F15: |
5054 | return "f15" ; |
5055 | } |
5056 | return "unknown register" ; |
5057 | } |
5058 | #endif // _LIBUNWIND_TARGET_S390X |
5059 | |
5060 | #if defined(_LIBUNWIND_TARGET_LOONGARCH) |
5061 | /// Registers_loongarch holds the register state of a thread in a 64-bit |
5062 | /// LoongArch process. |
5063 | class _LIBUNWIND_HIDDEN Registers_loongarch { |
5064 | public: |
5065 | Registers_loongarch(); |
5066 | Registers_loongarch(const void *registers); |
5067 | |
5068 | bool validRegister(int num) const; |
5069 | uint64_t getRegister(int num) const; |
5070 | void setRegister(int num, uint64_t value); |
5071 | bool validFloatRegister(int num) const; |
5072 | double getFloatRegister(int num) const; |
5073 | void setFloatRegister(int num, double value); |
5074 | bool validVectorRegister(int num) const; |
5075 | v128 getVectorRegister(int num) const; |
5076 | void setVectorRegister(int num, v128 value); |
5077 | static const char *getRegisterName(int num); |
5078 | void jumpto(); |
5079 | static constexpr int lastDwarfRegNum() { |
5080 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH; |
5081 | } |
5082 | static int getArch() { return REGISTERS_LOONGARCH; } |
5083 | |
5084 | uint64_t getSP() const { return _registers.__r[3]; } |
5085 | void setSP(uint64_t value) { _registers.__r[3] = value; } |
5086 | uint64_t getIP() const { return _registers.__pc; } |
5087 | void setIP(uint64_t value) { _registers.__pc = value; } |
5088 | |
5089 | private: |
5090 | struct loongarch_thread_state_t { |
5091 | uint64_t __r[32]; |
5092 | uint64_t __pc; |
5093 | }; |
5094 | |
5095 | loongarch_thread_state_t _registers; |
5096 | #if __loongarch_frlen == 64 |
5097 | double _floats[32]; |
5098 | #endif |
5099 | }; |
5100 | |
5101 | inline Registers_loongarch::Registers_loongarch(const void *registers) { |
5102 | static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit), |
5103 | "loongarch registers do not fit into unw_context_t" ); |
5104 | memcpy(&_registers, registers, sizeof(_registers)); |
5105 | static_assert(sizeof(_registers) == 0x108, |
5106 | "expected float registers to be at offset 264" ); |
5107 | #if __loongarch_frlen == 64 |
5108 | memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers), |
5109 | sizeof(_floats)); |
5110 | #endif |
5111 | } |
5112 | |
5113 | inline Registers_loongarch::Registers_loongarch() { |
5114 | memset(&_registers, 0, sizeof(_registers)); |
5115 | #if __loongarch_frlen == 64 |
5116 | memset(&_floats, 0, sizeof(_floats)); |
5117 | #endif |
5118 | } |
5119 | |
5120 | inline bool Registers_loongarch::validRegister(int regNum) const { |
5121 | if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) |
5122 | return true; |
5123 | if (regNum < 0 || regNum > UNW_LOONGARCH_F31) |
5124 | return false; |
5125 | return true; |
5126 | } |
5127 | |
5128 | inline uint64_t Registers_loongarch::getRegister(int regNum) const { |
5129 | if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) |
5130 | return _registers.__r[regNum - UNW_LOONGARCH_R0]; |
5131 | |
5132 | if (regNum == UNW_REG_IP) |
5133 | return _registers.__pc; |
5134 | if (regNum == UNW_REG_SP) |
5135 | return _registers.__r[3]; |
5136 | _LIBUNWIND_ABORT("unsupported loongarch register" ); |
5137 | } |
5138 | |
5139 | inline void Registers_loongarch::setRegister(int regNum, uint64_t value) { |
5140 | if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) |
5141 | _registers.__r[regNum - UNW_LOONGARCH_R0] = value; |
5142 | else if (regNum == UNW_REG_IP) |
5143 | _registers.__pc = value; |
5144 | else if (regNum == UNW_REG_SP) |
5145 | _registers.__r[3] = value; |
5146 | else |
5147 | _LIBUNWIND_ABORT("unsupported loongarch register" ); |
5148 | } |
5149 | |
5150 | inline const char *Registers_loongarch::getRegisterName(int regNum) { |
5151 | switch (regNum) { |
5152 | case UNW_REG_IP: |
5153 | return "$pc" ; |
5154 | case UNW_REG_SP: |
5155 | return "$sp" ; |
5156 | case UNW_LOONGARCH_R0: |
5157 | return "$r0" ; |
5158 | case UNW_LOONGARCH_R1: |
5159 | return "$r1" ; |
5160 | case UNW_LOONGARCH_R2: |
5161 | return "$r2" ; |
5162 | case UNW_LOONGARCH_R3: |
5163 | return "$r3" ; |
5164 | case UNW_LOONGARCH_R4: |
5165 | return "$r4" ; |
5166 | case UNW_LOONGARCH_R5: |
5167 | return "$r5" ; |
5168 | case UNW_LOONGARCH_R6: |
5169 | return "$r6" ; |
5170 | case UNW_LOONGARCH_R7: |
5171 | return "$r7" ; |
5172 | case UNW_LOONGARCH_R8: |
5173 | return "$r8" ; |
5174 | case UNW_LOONGARCH_R9: |
5175 | return "$r9" ; |
5176 | case UNW_LOONGARCH_R10: |
5177 | return "$r10" ; |
5178 | case UNW_LOONGARCH_R11: |
5179 | return "$r11" ; |
5180 | case UNW_LOONGARCH_R12: |
5181 | return "$r12" ; |
5182 | case UNW_LOONGARCH_R13: |
5183 | return "$r13" ; |
5184 | case UNW_LOONGARCH_R14: |
5185 | return "$r14" ; |
5186 | case UNW_LOONGARCH_R15: |
5187 | return "$r15" ; |
5188 | case UNW_LOONGARCH_R16: |
5189 | return "$r16" ; |
5190 | case UNW_LOONGARCH_R17: |
5191 | return "$r17" ; |
5192 | case UNW_LOONGARCH_R18: |
5193 | return "$r18" ; |
5194 | case UNW_LOONGARCH_R19: |
5195 | return "$r19" ; |
5196 | case UNW_LOONGARCH_R20: |
5197 | return "$r20" ; |
5198 | case UNW_LOONGARCH_R21: |
5199 | return "$r21" ; |
5200 | case UNW_LOONGARCH_R22: |
5201 | return "$r22" ; |
5202 | case UNW_LOONGARCH_R23: |
5203 | return "$r23" ; |
5204 | case UNW_LOONGARCH_R24: |
5205 | return "$r24" ; |
5206 | case UNW_LOONGARCH_R25: |
5207 | return "$r25" ; |
5208 | case UNW_LOONGARCH_R26: |
5209 | return "$r26" ; |
5210 | case UNW_LOONGARCH_R27: |
5211 | return "$r27" ; |
5212 | case UNW_LOONGARCH_R28: |
5213 | return "$r28" ; |
5214 | case UNW_LOONGARCH_R29: |
5215 | return "$r29" ; |
5216 | case UNW_LOONGARCH_R30: |
5217 | return "$r30" ; |
5218 | case UNW_LOONGARCH_R31: |
5219 | return "$r31" ; |
5220 | case UNW_LOONGARCH_F0: |
5221 | return "$f0" ; |
5222 | case UNW_LOONGARCH_F1: |
5223 | return "$f1" ; |
5224 | case UNW_LOONGARCH_F2: |
5225 | return "$f2" ; |
5226 | case UNW_LOONGARCH_F3: |
5227 | return "$f3" ; |
5228 | case UNW_LOONGARCH_F4: |
5229 | return "$f4" ; |
5230 | case UNW_LOONGARCH_F5: |
5231 | return "$f5" ; |
5232 | case UNW_LOONGARCH_F6: |
5233 | return "$f6" ; |
5234 | case UNW_LOONGARCH_F7: |
5235 | return "$f7" ; |
5236 | case UNW_LOONGARCH_F8: |
5237 | return "$f8" ; |
5238 | case UNW_LOONGARCH_F9: |
5239 | return "$f9" ; |
5240 | case UNW_LOONGARCH_F10: |
5241 | return "$f10" ; |
5242 | case UNW_LOONGARCH_F11: |
5243 | return "$f11" ; |
5244 | case UNW_LOONGARCH_F12: |
5245 | return "$f12" ; |
5246 | case UNW_LOONGARCH_F13: |
5247 | return "$f13" ; |
5248 | case UNW_LOONGARCH_F14: |
5249 | return "$f14" ; |
5250 | case UNW_LOONGARCH_F15: |
5251 | return "$f15" ; |
5252 | case UNW_LOONGARCH_F16: |
5253 | return "$f16" ; |
5254 | case UNW_LOONGARCH_F17: |
5255 | return "$f17" ; |
5256 | case UNW_LOONGARCH_F18: |
5257 | return "$f18" ; |
5258 | case UNW_LOONGARCH_F19: |
5259 | return "$f19" ; |
5260 | case UNW_LOONGARCH_F20: |
5261 | return "$f20" ; |
5262 | case UNW_LOONGARCH_F21: |
5263 | return "$f21" ; |
5264 | case UNW_LOONGARCH_F22: |
5265 | return "$f22" ; |
5266 | case UNW_LOONGARCH_F23: |
5267 | return "$f23" ; |
5268 | case UNW_LOONGARCH_F24: |
5269 | return "$f24" ; |
5270 | case UNW_LOONGARCH_F25: |
5271 | return "$f25" ; |
5272 | case UNW_LOONGARCH_F26: |
5273 | return "$f26" ; |
5274 | case UNW_LOONGARCH_F27: |
5275 | return "$f27" ; |
5276 | case UNW_LOONGARCH_F28: |
5277 | return "$f28" ; |
5278 | case UNW_LOONGARCH_F29: |
5279 | return "$f29" ; |
5280 | case UNW_LOONGARCH_F30: |
5281 | return "$f30" ; |
5282 | case UNW_LOONGARCH_F31: |
5283 | return "$f31" ; |
5284 | default: |
5285 | return "unknown register" ; |
5286 | } |
5287 | } |
5288 | |
5289 | inline bool Registers_loongarch::validFloatRegister(int regNum) const { |
5290 | if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31) |
5291 | return false; |
5292 | return true; |
5293 | } |
5294 | |
5295 | inline double Registers_loongarch::getFloatRegister(int regNum) const { |
5296 | #if __loongarch_frlen == 64 |
5297 | assert(validFloatRegister(regNum)); |
5298 | return _floats[regNum - UNW_LOONGARCH_F0]; |
5299 | #else |
5300 | _LIBUNWIND_ABORT("libunwind not built with float support" ); |
5301 | #endif |
5302 | } |
5303 | |
5304 | inline void Registers_loongarch::setFloatRegister(int regNum, double value) { |
5305 | #if __loongarch_frlen == 64 |
5306 | assert(validFloatRegister(regNum)); |
5307 | _floats[regNum - UNW_LOONGARCH_F0] = value; |
5308 | #else |
5309 | _LIBUNWIND_ABORT("libunwind not built with float support" ); |
5310 | #endif |
5311 | } |
5312 | |
5313 | inline bool Registers_loongarch::validVectorRegister(int) const { |
5314 | return false; |
5315 | } |
5316 | |
5317 | inline v128 Registers_loongarch::getVectorRegister(int) const { |
5318 | _LIBUNWIND_ABORT("loongarch vector support not implemented" ); |
5319 | } |
5320 | |
5321 | inline void Registers_loongarch::setVectorRegister(int, v128) { |
5322 | _LIBUNWIND_ABORT("loongarch vector support not implemented" ); |
5323 | } |
5324 | #endif //_LIBUNWIND_TARGET_LOONGARCH |
5325 | |
5326 | } // namespace libunwind |
5327 | |
5328 | #endif // __REGISTERS_HPP__ |
5329 | |