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 &reg_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