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