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 
21 using namespace lldb;
22 using namespace lldb_private;
23 using 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,                                                      \
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,                      \
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,                                     \
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,                                           \
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,                                                               \
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,                                                               \
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,                                                               \
74   }
75 
76 // Zero based LLDB register numbers for this register context
77 enum {
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
280 static 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     {"fp",
311      "x29",
312      8,
313      OFFSET(x) + 29 * 8,
314      eEncodingUint,
315      eFormatHex,
316      {arm64_dwarf::x29, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, INV, reg_fp},
317      nullptr,
318      nullptr,
319     },
320     {"lr",
321      "x30",
322      8,
323      OFFSET(x) + 30 * 8,
324      eEncodingUint,
325      eFormatHex,
326      {arm64_dwarf::x30, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
327      nullptr,
328      nullptr,
329     },
330     {"sp",
331      "x31",
332      8,
333      OFFSET(x) + 31 * 8,
334      eEncodingUint,
335      eFormatHex,
336      {arm64_dwarf::x31, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
337      nullptr,
338      nullptr,
339     },
340     {"pc",
341      nullptr,
342      8,
343      OFFSET(pc),
344      eEncodingUint,
345      eFormatHex,
346      {arm64_dwarf::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
347      nullptr,
348      nullptr,
349     },
350     // w0 - w31
351     DEF_W(0),
352     DEF_W(1),
353     DEF_W(2),
354     DEF_W(3),
355     DEF_W(4),
356     DEF_W(5),
357     DEF_W(6),
358     DEF_W(7),
359     DEF_W(8),
360     DEF_W(9),
361     DEF_W(10),
362     DEF_W(11),
363     DEF_W(12),
364     DEF_W(13),
365     DEF_W(14),
366     DEF_W(15),
367     DEF_W(16),
368     DEF_W(17),
369     DEF_W(18),
370     DEF_W(19),
371     DEF_W(20),
372     DEF_W(21),
373     DEF_W(22),
374     DEF_W(23),
375     DEF_W(24),
376     DEF_W(25),
377     DEF_W(26),
378     DEF_W(27),
379     DEF_W(28),
380     DEF_W(29),
381     DEF_W(30),
382     DEF_W(31),
383     {"cpsr",
384      "psr",
385      4,
386      OFFSET(cpsr),
387      eEncodingUint,
388      eFormatHex,
389      {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
390      nullptr,
391      nullptr,
392     },
393     {"fpsr",
394      nullptr,
395      4,
396      OFFSET(fpsr),
397      eEncodingUint,
398      eFormatHex,
399      {INV, INV, INV, INV, reg_fpsr},
400      nullptr,
401      nullptr,
402     },
403     {"fpcr",
404      nullptr,
405      4,
406      OFFSET(fpcr),
407      eEncodingUint,
408      eFormatHex,
409      {INV, INV, INV, INV, reg_fpcr},
410      nullptr,
411      nullptr,
412     },
413     // v0 - v31
414     DEF_V(0),
415     DEF_V(1),
416     DEF_V(2),
417     DEF_V(3),
418     DEF_V(4),
419     DEF_V(5),
420     DEF_V(6),
421     DEF_V(7),
422     DEF_V(8),
423     DEF_V(9),
424     DEF_V(10),
425     DEF_V(11),
426     DEF_V(12),
427     DEF_V(13),
428     DEF_V(14),
429     DEF_V(15),
430     DEF_V(16),
431     DEF_V(17),
432     DEF_V(18),
433     DEF_V(19),
434     DEF_V(20),
435     DEF_V(21),
436     DEF_V(22),
437     DEF_V(23),
438     DEF_V(24),
439     DEF_V(25),
440     DEF_V(26),
441     DEF_V(27),
442     DEF_V(28),
443     DEF_V(29),
444     DEF_V(30),
445     DEF_V(31),
446     // d0 - d31
447     DEF_D(0),
448     DEF_D(1),
449     DEF_D(2),
450     DEF_D(3),
451     DEF_D(4),
452     DEF_D(5),
453     DEF_D(6),
454     DEF_D(7),
455     DEF_D(8),
456     DEF_D(9),
457     DEF_D(10),
458     DEF_D(11),
459     DEF_D(12),
460     DEF_D(13),
461     DEF_D(14),
462     DEF_D(15),
463     DEF_D(16),
464     DEF_D(17),
465     DEF_D(18),
466     DEF_D(19),
467     DEF_D(20),
468     DEF_D(21),
469     DEF_D(22),
470     DEF_D(23),
471     DEF_D(24),
472     DEF_D(25),
473     DEF_D(26),
474     DEF_D(27),
475     DEF_D(28),
476     DEF_D(29),
477     DEF_D(30),
478     DEF_D(31),
479     // s0 - s31
480     DEF_S(0),
481     DEF_S(1),
482     DEF_S(2),
483     DEF_S(3),
484     DEF_S(4),
485     DEF_S(5),
486     DEF_S(6),
487     DEF_S(7),
488     DEF_S(8),
489     DEF_S(9),
490     DEF_S(10),
491     DEF_S(11),
492     DEF_S(12),
493     DEF_S(13),
494     DEF_S(14),
495     DEF_S(15),
496     DEF_S(16),
497     DEF_S(17),
498     DEF_S(18),
499     DEF_S(19),
500     DEF_S(20),
501     DEF_S(21),
502     DEF_S(22),
503     DEF_S(23),
504     DEF_S(24),
505     DEF_S(25),
506     DEF_S(26),
507     DEF_S(27),
508     DEF_S(28),
509     DEF_S(29),
510     DEF_S(30),
511     DEF_S(31),
512     // h0 - h31
513     DEF_H(0),
514     DEF_H(1),
515     DEF_H(2),
516     DEF_H(3),
517     DEF_H(4),
518     DEF_H(5),
519     DEF_H(6),
520     DEF_H(7),
521     DEF_H(8),
522     DEF_H(9),
523     DEF_H(10),
524     DEF_H(11),
525     DEF_H(12),
526     DEF_H(13),
527     DEF_H(14),
528     DEF_H(15),
529     DEF_H(16),
530     DEF_H(17),
531     DEF_H(18),
532     DEF_H(19),
533     DEF_H(20),
534     DEF_H(21),
535     DEF_H(22),
536     DEF_H(23),
537     DEF_H(24),
538     DEF_H(25),
539     DEF_H(26),
540     DEF_H(27),
541     DEF_H(28),
542     DEF_H(29),
543     DEF_H(30),
544     DEF_H(31),
545 };
546 
547 constexpr size_t k_num_reg_infos = std::size(g_reg_infos);
548 
549 // ARM64 general purpose registers.
550 const uint32_t g_gpr_regnums[] = {
551     reg_x0,
552     reg_x1,
553     reg_x2,
554     reg_x3,
555     reg_x4,
556     reg_x5,
557     reg_x6,
558     reg_x7,
559     reg_x8,
560     reg_x9,
561     reg_x10,
562     reg_x11,
563     reg_x12,
564     reg_x13,
565     reg_x14,
566     reg_x15,
567     reg_x16,
568     reg_x17,
569     reg_x18,
570     reg_x19,
571     reg_x20,
572     reg_x21,
573     reg_x22,
574     reg_x23,
575     reg_x24,
576     reg_x25,
577     reg_x26,
578     reg_x27,
579     reg_x28,
580     reg_fp,
581     reg_lr,
582     reg_sp,
583     reg_w0,
584     reg_w1,
585     reg_w2,
586     reg_w3,
587     reg_w4,
588     reg_w5,
589     reg_w6,
590     reg_w7,
591     reg_w8,
592     reg_w9,
593     reg_w10,
594     reg_w11,
595     reg_w12,
596     reg_w13,
597     reg_w14,
598     reg_w15,
599     reg_w16,
600     reg_w17,
601     reg_w18,
602     reg_w19,
603     reg_w20,
604     reg_w21,
605     reg_w22,
606     reg_w23,
607     reg_w24,
608     reg_w25,
609     reg_w26,
610     reg_w27,
611     reg_w28,
612     reg_w29,
613     reg_w30,
614     reg_w31,
615     reg_pc,
616     reg_cpsr,
617     LLDB_INVALID_REGNUM // register sets need to end with this flag
618 };
619 const uint32_t g_fpu_regnums[] = {
620     reg_v0,
621     reg_v1,
622     reg_v2,
623     reg_v3,
624     reg_v4,
625     reg_v5,
626     reg_v6,
627     reg_v7,
628     reg_v8,
629     reg_v9,
630     reg_v10,
631     reg_v11,
632     reg_v12,
633     reg_v13,
634     reg_v14,
635     reg_v15,
636     reg_v16,
637     reg_v17,
638     reg_v18,
639     reg_v19,
640     reg_v20,
641     reg_v21,
642     reg_v22,
643     reg_v23,
644     reg_v24,
645     reg_v25,
646     reg_v26,
647     reg_v27,
648     reg_v28,
649     reg_v29,
650     reg_v30,
651     reg_v31,
652     reg_d0,
653     reg_d1,
654     reg_d2,
655     reg_d3,
656     reg_d4,
657     reg_d5,
658     reg_d6,
659     reg_d7,
660     reg_d8,
661     reg_d9,
662     reg_d10,
663     reg_d11,
664     reg_d12,
665     reg_d13,
666     reg_d14,
667     reg_d15,
668     reg_d16,
669     reg_d17,
670     reg_d18,
671     reg_d19,
672     reg_d20,
673     reg_d21,
674     reg_d22,
675     reg_d23,
676     reg_d24,
677     reg_d25,
678     reg_d26,
679     reg_d27,
680     reg_d28,
681     reg_d29,
682     reg_d30,
683     reg_d31,
684     reg_s0,
685     reg_s1,
686     reg_s2,
687     reg_s3,
688     reg_s4,
689     reg_s5,
690     reg_s6,
691     reg_s7,
692     reg_s8,
693     reg_s9,
694     reg_s10,
695     reg_s11,
696     reg_s12,
697     reg_s13,
698     reg_s14,
699     reg_s15,
700     reg_s16,
701     reg_s17,
702     reg_s18,
703     reg_s19,
704     reg_s20,
705     reg_s21,
706     reg_s22,
707     reg_s23,
708     reg_s24,
709     reg_s25,
710     reg_s26,
711     reg_s27,
712     reg_s28,
713     reg_s29,
714     reg_s30,
715     reg_s31,
716     reg_h0,
717     reg_h1,
718     reg_h2,
719     reg_h3,
720     reg_h4,
721     reg_h5,
722     reg_h6,
723     reg_h7,
724     reg_h8,
725     reg_h9,
726     reg_h10,
727     reg_h11,
728     reg_h12,
729     reg_h13,
730     reg_h14,
731     reg_h15,
732     reg_h16,
733     reg_h17,
734     reg_h18,
735     reg_h19,
736     reg_h20,
737     reg_h21,
738     reg_h22,
739     reg_h23,
740     reg_h24,
741     reg_h25,
742     reg_h26,
743     reg_h27,
744     reg_h28,
745     reg_h29,
746     reg_h30,
747     reg_h31,
748     reg_fpsr,
749     reg_fpcr,
750     LLDB_INVALID_REGNUM // register sets need to end with this flag
751 };
752 
753 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
754 constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1;
755 constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1;
756 
757 static RegisterSet g_reg_sets[] = {
758     {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
759     {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
760 };
761 
762 constexpr size_t k_num_reg_sets = std::size(g_reg_sets);
763 
764 RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64(
765     lldb_private::Thread &thread, const DataExtractor &data)
766     : RegisterContext(thread, 0) {
767   lldb::offset_t offset = 0;
768   m_regs.context_flags = data.GetU64(&offset);
769   for (unsigned i = 0; i < 32; ++i)
770     m_regs.x[i] = data.GetU64(&offset);
771   m_regs.pc = data.GetU64(&offset);
772   m_regs.cpsr = data.GetU32(&offset);
773   m_regs.fpsr = data.GetU32(&offset);
774   m_regs.fpcr = data.GetU32(&offset);
775   auto regs_data = data.GetData(&offset, sizeof(m_regs.v));
776   if (regs_data)
777     memcpy(m_regs.v, regs_data, sizeof(m_regs.v));
778   static_assert(k_num_regs == k_num_reg_infos);
779 }
780 size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; }
781 
782 const RegisterInfo *
783 RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) {
784   if (reg < k_num_reg_infos)
785     return &g_reg_infos[reg];
786   return nullptr;
787 }
788 
789 size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() {
790   return k_num_reg_sets;
791 }
792 
793 const RegisterSet *RegisterContextMinidump_ARM64::GetRegisterSet(size_t set) {
794   if (set < k_num_reg_sets)
795     return &g_reg_sets[set];
796   return nullptr;
797 }
798 
799 const char *RegisterContextMinidump_ARM64::GetRegisterName(unsigned reg) {
800   if (reg < k_num_reg_infos)
801     return g_reg_infos[reg].name;
802   return nullptr;
803 }
804 
805 bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info,
806                                                  RegisterValue &reg_value) {
807   Status error;
808   reg_value.SetFromMemoryData(
809       *reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
810       reg_info->byte_size, lldb::eByteOrderLittle, error);
811   return error.Success();
812 }
813 
814 bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *,
815                                                   const RegisterValue &) {
816   return false;
817 }
818 
819 uint32_t RegisterContextMinidump_ARM64::ConvertRegisterKindToRegisterNumber(
820     lldb::RegisterKind kind, uint32_t num) {
821   for (size_t i = 0; i < k_num_regs; ++i) {
822     if (g_reg_infos[i].kinds[kind] == num)
823       return i;
824   }
825   return LLDB_INVALID_REGNUM;
826 }
827