1//===-- RegisterContextMinidump_ARM64.cpp ---------------------------------===//
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
9#include "RegisterContextMinidump_ARM64.h"
10
11#include "Utility/ARM64_DWARF_Registers.h"
12#include "lldb/Utility/RegisterValue.h"
13#include "lldb/Utility/DataExtractor.h"
14#include "lldb/lldb-enumerations.h"
15
16// C includes
17#include <cassert>
18
19// C++ includes
20
21using namespace lldb;
22using namespace lldb_private;
23using namespace minidump;
24
25#define INV LLDB_INVALID_REGNUM
26#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM64::Context, r))
27
28#define DEF_X(i) \
29 { \
30 "x" #i, nullptr, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
31 {arm64_dwarf::x##i, arm64_dwarf::x##i, INV, INV, reg_x##i}, \
32 nullptr, nullptr, nullptr, \
33 }
34
35#define DEF_W(i) \
36 { \
37 "w" #i, nullptr, 4, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
38 {INV, INV, INV, INV, reg_w##i}, nullptr, nullptr, nullptr, \
39 }
40
41#define DEF_X_ARG(i, n) \
42 { \
43 "x" #i, "arg" #n, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
44 {arm64_dwarf::x##i, arm64_dwarf::x##i, LLDB_REGNUM_GENERIC_ARG1 + i, \
45 INV, reg_x##i}, nullptr, nullptr, nullptr, \
46 }
47
48#define DEF_V(i) \
49 { \
50 "v" #i, nullptr, 16, OFFSET(v) + i * 16, eEncodingVector, \
51 eFormatVectorOfUInt8, {arm64_dwarf::v##i, arm64_dwarf::v##i, INV, INV, \
52 reg_v##i}, nullptr, nullptr, nullptr, \
53 }
54
55#define DEF_D(i) \
56 { \
57 "d" #i, nullptr, 8, OFFSET(v) + i * 16, eEncodingVector, \
58 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_d##i}, nullptr, \
59 nullptr, nullptr, \
60 }
61
62#define DEF_S(i) \
63 { \
64 "s" #i, nullptr, 4, OFFSET(v) + i * 16, eEncodingVector, \
65 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_s##i}, nullptr, \
66 nullptr, nullptr, \
67 }
68
69#define DEF_H(i) \
70 { \
71 "h" #i, nullptr, 2, OFFSET(v) + i * 16, eEncodingVector, \
72 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_h##i}, nullptr, \
73 nullptr, nullptr, \
74 }
75
76// Zero based LLDB register numbers for this register context
77enum {
78 // General Purpose Registers
79 reg_x0 = 0,
80 reg_x1,
81 reg_x2,
82 reg_x3,
83 reg_x4,
84 reg_x5,
85 reg_x6,
86 reg_x7,
87 reg_x8,
88 reg_x9,
89 reg_x10,
90 reg_x11,
91 reg_x12,
92 reg_x13,
93 reg_x14,
94 reg_x15,
95 reg_x16,
96 reg_x17,
97 reg_x18,
98 reg_x19,
99 reg_x20,
100 reg_x21,
101 reg_x22,
102 reg_x23,
103 reg_x24,
104 reg_x25,
105 reg_x26,
106 reg_x27,
107 reg_x28,
108 reg_fp,
109 reg_lr,
110 reg_sp,
111 reg_pc,
112 reg_w0,
113 reg_w1,
114 reg_w2,
115 reg_w3,
116 reg_w4,
117 reg_w5,
118 reg_w6,
119 reg_w7,
120 reg_w8,
121 reg_w9,
122 reg_w10,
123 reg_w11,
124 reg_w12,
125 reg_w13,
126 reg_w14,
127 reg_w15,
128 reg_w16,
129 reg_w17,
130 reg_w18,
131 reg_w19,
132 reg_w20,
133 reg_w21,
134 reg_w22,
135 reg_w23,
136 reg_w24,
137 reg_w25,
138 reg_w26,
139 reg_w27,
140 reg_w28,
141 reg_w29,
142 reg_w30,
143 reg_w31,
144 reg_cpsr,
145 // Floating Point Registers
146 reg_fpsr,
147 reg_fpcr,
148 reg_v0,
149 reg_v1,
150 reg_v2,
151 reg_v3,
152 reg_v4,
153 reg_v5,
154 reg_v6,
155 reg_v7,
156 reg_v8,
157 reg_v9,
158 reg_v10,
159 reg_v11,
160 reg_v12,
161 reg_v13,
162 reg_v14,
163 reg_v15,
164 reg_v16,
165 reg_v17,
166 reg_v18,
167 reg_v19,
168 reg_v20,
169 reg_v21,
170 reg_v22,
171 reg_v23,
172 reg_v24,
173 reg_v25,
174 reg_v26,
175 reg_v27,
176 reg_v28,
177 reg_v29,
178 reg_v30,
179 reg_v31,
180 reg_d0,
181 reg_d1,
182 reg_d2,
183 reg_d3,
184 reg_d4,
185 reg_d5,
186 reg_d6,
187 reg_d7,
188 reg_d8,
189 reg_d9,
190 reg_d10,
191 reg_d11,
192 reg_d12,
193 reg_d13,
194 reg_d14,
195 reg_d15,
196 reg_d16,
197 reg_d17,
198 reg_d18,
199 reg_d19,
200 reg_d20,
201 reg_d21,
202 reg_d22,
203 reg_d23,
204 reg_d24,
205 reg_d25,
206 reg_d26,
207 reg_d27,
208 reg_d28,
209 reg_d29,
210 reg_d30,
211 reg_d31,
212 reg_s0,
213 reg_s1,
214 reg_s2,
215 reg_s3,
216 reg_s4,
217 reg_s5,
218 reg_s6,
219 reg_s7,
220 reg_s8,
221 reg_s9,
222 reg_s10,
223 reg_s11,
224 reg_s12,
225 reg_s13,
226 reg_s14,
227 reg_s15,
228 reg_s16,
229 reg_s17,
230 reg_s18,
231 reg_s19,
232 reg_s20,
233 reg_s21,
234 reg_s22,
235 reg_s23,
236 reg_s24,
237 reg_s25,
238 reg_s26,
239 reg_s27,
240 reg_s28,
241 reg_s29,
242 reg_s30,
243 reg_s31,
244 reg_h0,
245 reg_h1,
246 reg_h2,
247 reg_h3,
248 reg_h4,
249 reg_h5,
250 reg_h6,
251 reg_h7,
252 reg_h8,
253 reg_h9,
254 reg_h10,
255 reg_h11,
256 reg_h12,
257 reg_h13,
258 reg_h14,
259 reg_h15,
260 reg_h16,
261 reg_h17,
262 reg_h18,
263 reg_h19,
264 reg_h20,
265 reg_h21,
266 reg_h22,
267 reg_h23,
268 reg_h24,
269 reg_h25,
270 reg_h26,
271 reg_h27,
272 reg_h28,
273 reg_h29,
274 reg_h30,
275 reg_h31,
276 k_num_regs
277};
278
279// Register info definitions for this register context
280static RegisterInfo g_reg_infos[] = {
281 DEF_X_ARG(0, 1),
282 DEF_X_ARG(1, 2),
283 DEF_X_ARG(2, 3),
284 DEF_X_ARG(3, 4),
285 DEF_X_ARG(4, 5),
286 DEF_X_ARG(5, 6),
287 DEF_X_ARG(6, 7),
288 DEF_X_ARG(7, 8),
289 DEF_X(8),
290 DEF_X(9),
291 DEF_X(10),
292 DEF_X(11),
293 DEF_X(12),
294 DEF_X(13),
295 DEF_X(14),
296 DEF_X(15),
297 DEF_X(16),
298 DEF_X(17),
299 DEF_X(18),
300 DEF_X(19),
301 DEF_X(20),
302 DEF_X(21),
303 DEF_X(22),
304 DEF_X(23),
305 DEF_X(24),
306 DEF_X(25),
307 DEF_X(26),
308 DEF_X(27),
309 DEF_X(28),
310 {.name: "fp",
311 .alt_name: "x29",
312 .byte_size: 8,
313 OFFSET(x) + 29 * 8,
314 .encoding: eEncodingUint,
315 .format: eFormatHex,
316 .kinds: {arm64_dwarf::x29, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, INV, reg_fp},
317 .value_regs: nullptr,
318 .invalidate_regs: nullptr,
319 .flags_type: nullptr,
320 },
321 {.name: "lr",
322 .alt_name: "x30",
323 .byte_size: 8,
324 OFFSET(x) + 30 * 8,
325 .encoding: eEncodingUint,
326 .format: eFormatHex,
327 .kinds: {arm64_dwarf::x30, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
328 .value_regs: nullptr,
329 .invalidate_regs: nullptr,
330 .flags_type: nullptr,
331 },
332 {.name: "sp",
333 .alt_name: "x31",
334 .byte_size: 8,
335 OFFSET(x) + 31 * 8,
336 .encoding: eEncodingUint,
337 .format: eFormatHex,
338 .kinds: {arm64_dwarf::x31, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
339 .value_regs: nullptr,
340 .invalidate_regs: nullptr,
341 .flags_type: nullptr,
342 },
343 {.name: "pc",
344 .alt_name: nullptr,
345 .byte_size: 8,
346 OFFSET(pc),
347 .encoding: eEncodingUint,
348 .format: eFormatHex,
349 .kinds: {arm64_dwarf::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
350 .value_regs: nullptr,
351 .invalidate_regs: nullptr,
352 .flags_type: nullptr,
353 },
354 // w0 - w31
355 DEF_W(0),
356 DEF_W(1),
357 DEF_W(2),
358 DEF_W(3),
359 DEF_W(4),
360 DEF_W(5),
361 DEF_W(6),
362 DEF_W(7),
363 DEF_W(8),
364 DEF_W(9),
365 DEF_W(10),
366 DEF_W(11),
367 DEF_W(12),
368 DEF_W(13),
369 DEF_W(14),
370 DEF_W(15),
371 DEF_W(16),
372 DEF_W(17),
373 DEF_W(18),
374 DEF_W(19),
375 DEF_W(20),
376 DEF_W(21),
377 DEF_W(22),
378 DEF_W(23),
379 DEF_W(24),
380 DEF_W(25),
381 DEF_W(26),
382 DEF_W(27),
383 DEF_W(28),
384 DEF_W(29),
385 DEF_W(30),
386 DEF_W(31),
387 {.name: "cpsr",
388 .alt_name: "psr",
389 .byte_size: 4,
390 OFFSET(cpsr),
391 .encoding: eEncodingUint,
392 .format: eFormatHex,
393 .kinds: {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
394 .value_regs: nullptr,
395 .invalidate_regs: nullptr,
396 .flags_type: nullptr,
397 },
398 {.name: "fpsr",
399 .alt_name: nullptr,
400 .byte_size: 4,
401 OFFSET(fpsr),
402 .encoding: eEncodingUint,
403 .format: eFormatHex,
404 .kinds: {INV, INV, INV, INV, reg_fpsr},
405 .value_regs: nullptr,
406 .invalidate_regs: nullptr,
407 .flags_type: nullptr,
408 },
409 {.name: "fpcr",
410 .alt_name: nullptr,
411 .byte_size: 4,
412 OFFSET(fpcr),
413 .encoding: eEncodingUint,
414 .format: eFormatHex,
415 .kinds: {INV, INV, INV, INV, reg_fpcr},
416 .value_regs: nullptr,
417 .invalidate_regs: nullptr,
418 .flags_type: nullptr,
419 },
420 // v0 - v31
421 DEF_V(0),
422 DEF_V(1),
423 DEF_V(2),
424 DEF_V(3),
425 DEF_V(4),
426 DEF_V(5),
427 DEF_V(6),
428 DEF_V(7),
429 DEF_V(8),
430 DEF_V(9),
431 DEF_V(10),
432 DEF_V(11),
433 DEF_V(12),
434 DEF_V(13),
435 DEF_V(14),
436 DEF_V(15),
437 DEF_V(16),
438 DEF_V(17),
439 DEF_V(18),
440 DEF_V(19),
441 DEF_V(20),
442 DEF_V(21),
443 DEF_V(22),
444 DEF_V(23),
445 DEF_V(24),
446 DEF_V(25),
447 DEF_V(26),
448 DEF_V(27),
449 DEF_V(28),
450 DEF_V(29),
451 DEF_V(30),
452 DEF_V(31),
453 // d0 - d31
454 DEF_D(0),
455 DEF_D(1),
456 DEF_D(2),
457 DEF_D(3),
458 DEF_D(4),
459 DEF_D(5),
460 DEF_D(6),
461 DEF_D(7),
462 DEF_D(8),
463 DEF_D(9),
464 DEF_D(10),
465 DEF_D(11),
466 DEF_D(12),
467 DEF_D(13),
468 DEF_D(14),
469 DEF_D(15),
470 DEF_D(16),
471 DEF_D(17),
472 DEF_D(18),
473 DEF_D(19),
474 DEF_D(20),
475 DEF_D(21),
476 DEF_D(22),
477 DEF_D(23),
478 DEF_D(24),
479 DEF_D(25),
480 DEF_D(26),
481 DEF_D(27),
482 DEF_D(28),
483 DEF_D(29),
484 DEF_D(30),
485 DEF_D(31),
486 // s0 - s31
487 DEF_S(0),
488 DEF_S(1),
489 DEF_S(2),
490 DEF_S(3),
491 DEF_S(4),
492 DEF_S(5),
493 DEF_S(6),
494 DEF_S(7),
495 DEF_S(8),
496 DEF_S(9),
497 DEF_S(10),
498 DEF_S(11),
499 DEF_S(12),
500 DEF_S(13),
501 DEF_S(14),
502 DEF_S(15),
503 DEF_S(16),
504 DEF_S(17),
505 DEF_S(18),
506 DEF_S(19),
507 DEF_S(20),
508 DEF_S(21),
509 DEF_S(22),
510 DEF_S(23),
511 DEF_S(24),
512 DEF_S(25),
513 DEF_S(26),
514 DEF_S(27),
515 DEF_S(28),
516 DEF_S(29),
517 DEF_S(30),
518 DEF_S(31),
519 // h0 - h31
520 DEF_H(0),
521 DEF_H(1),
522 DEF_H(2),
523 DEF_H(3),
524 DEF_H(4),
525 DEF_H(5),
526 DEF_H(6),
527 DEF_H(7),
528 DEF_H(8),
529 DEF_H(9),
530 DEF_H(10),
531 DEF_H(11),
532 DEF_H(12),
533 DEF_H(13),
534 DEF_H(14),
535 DEF_H(15),
536 DEF_H(16),
537 DEF_H(17),
538 DEF_H(18),
539 DEF_H(19),
540 DEF_H(20),
541 DEF_H(21),
542 DEF_H(22),
543 DEF_H(23),
544 DEF_H(24),
545 DEF_H(25),
546 DEF_H(26),
547 DEF_H(27),
548 DEF_H(28),
549 DEF_H(29),
550 DEF_H(30),
551 DEF_H(31),
552};
553
554constexpr size_t k_num_reg_infos = std::size(g_reg_infos);
555
556// ARM64 general purpose registers.
557const uint32_t g_gpr_regnums[] = {
558 reg_x0,
559 reg_x1,
560 reg_x2,
561 reg_x3,
562 reg_x4,
563 reg_x5,
564 reg_x6,
565 reg_x7,
566 reg_x8,
567 reg_x9,
568 reg_x10,
569 reg_x11,
570 reg_x12,
571 reg_x13,
572 reg_x14,
573 reg_x15,
574 reg_x16,
575 reg_x17,
576 reg_x18,
577 reg_x19,
578 reg_x20,
579 reg_x21,
580 reg_x22,
581 reg_x23,
582 reg_x24,
583 reg_x25,
584 reg_x26,
585 reg_x27,
586 reg_x28,
587 reg_fp,
588 reg_lr,
589 reg_sp,
590 reg_w0,
591 reg_w1,
592 reg_w2,
593 reg_w3,
594 reg_w4,
595 reg_w5,
596 reg_w6,
597 reg_w7,
598 reg_w8,
599 reg_w9,
600 reg_w10,
601 reg_w11,
602 reg_w12,
603 reg_w13,
604 reg_w14,
605 reg_w15,
606 reg_w16,
607 reg_w17,
608 reg_w18,
609 reg_w19,
610 reg_w20,
611 reg_w21,
612 reg_w22,
613 reg_w23,
614 reg_w24,
615 reg_w25,
616 reg_w26,
617 reg_w27,
618 reg_w28,
619 reg_w29,
620 reg_w30,
621 reg_w31,
622 reg_pc,
623 reg_cpsr,
624 LLDB_INVALID_REGNUM // register sets need to end with this flag
625};
626const uint32_t g_fpu_regnums[] = {
627 reg_v0,
628 reg_v1,
629 reg_v2,
630 reg_v3,
631 reg_v4,
632 reg_v5,
633 reg_v6,
634 reg_v7,
635 reg_v8,
636 reg_v9,
637 reg_v10,
638 reg_v11,
639 reg_v12,
640 reg_v13,
641 reg_v14,
642 reg_v15,
643 reg_v16,
644 reg_v17,
645 reg_v18,
646 reg_v19,
647 reg_v20,
648 reg_v21,
649 reg_v22,
650 reg_v23,
651 reg_v24,
652 reg_v25,
653 reg_v26,
654 reg_v27,
655 reg_v28,
656 reg_v29,
657 reg_v30,
658 reg_v31,
659 reg_d0,
660 reg_d1,
661 reg_d2,
662 reg_d3,
663 reg_d4,
664 reg_d5,
665 reg_d6,
666 reg_d7,
667 reg_d8,
668 reg_d9,
669 reg_d10,
670 reg_d11,
671 reg_d12,
672 reg_d13,
673 reg_d14,
674 reg_d15,
675 reg_d16,
676 reg_d17,
677 reg_d18,
678 reg_d19,
679 reg_d20,
680 reg_d21,
681 reg_d22,
682 reg_d23,
683 reg_d24,
684 reg_d25,
685 reg_d26,
686 reg_d27,
687 reg_d28,
688 reg_d29,
689 reg_d30,
690 reg_d31,
691 reg_s0,
692 reg_s1,
693 reg_s2,
694 reg_s3,
695 reg_s4,
696 reg_s5,
697 reg_s6,
698 reg_s7,
699 reg_s8,
700 reg_s9,
701 reg_s10,
702 reg_s11,
703 reg_s12,
704 reg_s13,
705 reg_s14,
706 reg_s15,
707 reg_s16,
708 reg_s17,
709 reg_s18,
710 reg_s19,
711 reg_s20,
712 reg_s21,
713 reg_s22,
714 reg_s23,
715 reg_s24,
716 reg_s25,
717 reg_s26,
718 reg_s27,
719 reg_s28,
720 reg_s29,
721 reg_s30,
722 reg_s31,
723 reg_h0,
724 reg_h1,
725 reg_h2,
726 reg_h3,
727 reg_h4,
728 reg_h5,
729 reg_h6,
730 reg_h7,
731 reg_h8,
732 reg_h9,
733 reg_h10,
734 reg_h11,
735 reg_h12,
736 reg_h13,
737 reg_h14,
738 reg_h15,
739 reg_h16,
740 reg_h17,
741 reg_h18,
742 reg_h19,
743 reg_h20,
744 reg_h21,
745 reg_h22,
746 reg_h23,
747 reg_h24,
748 reg_h25,
749 reg_h26,
750 reg_h27,
751 reg_h28,
752 reg_h29,
753 reg_h30,
754 reg_h31,
755 reg_fpsr,
756 reg_fpcr,
757 LLDB_INVALID_REGNUM // register sets need to end with this flag
758};
759
760// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
761constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1;
762constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1;
763
764static RegisterSet g_reg_sets[] = {
765 {.name: "General Purpose Registers", .short_name: "gpr", .num_registers: k_num_gpr_regs, .registers: g_gpr_regnums},
766 {.name: "Floating Point Registers", .short_name: "fpu", .num_registers: k_num_fpu_regs, .registers: g_fpu_regnums},
767};
768
769constexpr size_t k_num_reg_sets = std::size(g_reg_sets);
770
771RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64(
772 lldb_private::Thread &thread, const DataExtractor &data)
773 : RegisterContext(thread, 0) {
774 lldb::offset_t offset = 0;
775 m_regs.context_flags = data.GetU64(offset_ptr: &offset);
776 for (unsigned i = 0; i < 32; ++i)
777 m_regs.x[i] = data.GetU64(offset_ptr: &offset);
778 m_regs.pc = data.GetU64(offset_ptr: &offset);
779 m_regs.cpsr = data.GetU32(offset_ptr: &offset);
780 m_regs.fpsr = data.GetU32(offset_ptr: &offset);
781 m_regs.fpcr = data.GetU32(offset_ptr: &offset);
782 auto regs_data = data.GetData(offset_ptr: &offset, length: sizeof(m_regs.v));
783 if (regs_data)
784 memcpy(dest: m_regs.v, src: regs_data, n: sizeof(m_regs.v));
785 static_assert(k_num_regs == k_num_reg_infos);
786}
787size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; }
788
789const RegisterInfo *
790RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) {
791 if (reg < k_num_reg_infos)
792 return &g_reg_infos[reg];
793 return nullptr;
794}
795
796size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() {
797 return k_num_reg_sets;
798}
799
800const RegisterSet *RegisterContextMinidump_ARM64::GetRegisterSet(size_t set) {
801 if (set < k_num_reg_sets)
802 return &g_reg_sets[set];
803 return nullptr;
804}
805
806const char *RegisterContextMinidump_ARM64::GetRegisterName(unsigned reg) {
807 if (reg < k_num_reg_infos)
808 return g_reg_infos[reg].name;
809 return nullptr;
810}
811
812bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info,
813 RegisterValue &reg_value) {
814 Status error;
815 reg_value.SetFromMemoryData(
816 reg_info: *reg_info, src: (const uint8_t *)&m_regs + reg_info->byte_offset,
817 src_len: reg_info->byte_size, src_byte_order: lldb::eByteOrderLittle, error);
818 return error.Success();
819}
820
821bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *,
822 const RegisterValue &) {
823 return false;
824}
825
826uint32_t RegisterContextMinidump_ARM64::ConvertRegisterKindToRegisterNumber(
827 lldb::RegisterKind kind, uint32_t num) {
828 for (size_t i = 0; i < k_num_regs; ++i) {
829 if (g_reg_infos[i].kinds[kind] == num)
830 return i;
831 }
832 return LLDB_INVALID_REGNUM;
833}
834

source code of lldb/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp