1//===-- RegisterContextMinidump_ARM64.cpp -----------------------*- C++ -*-===//
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 <assert.h>
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, 0                                           \
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, 0           \
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, 0                          \
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, 0                                \
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, 0                                                    \
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, 0                                                    \
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, 0                                                    \
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    {"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     nullptr,
320     0},
321    {"lr",
322     "x30",
323     8,
324     OFFSET(x) + 30 * 8,
325     eEncodingUint,
326     eFormatHex,
327     {arm64_dwarf::x30, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
328     nullptr,
329     nullptr,
330     nullptr,
331     0},
332    {"sp",
333     "x31",
334     8,
335     OFFSET(x) + 31 * 8,
336     eEncodingUint,
337     eFormatHex,
338     {arm64_dwarf::x31, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
339     nullptr,
340     nullptr,
341     nullptr,
342     0},
343    {"pc",
344     nullptr,
345     8,
346     OFFSET(pc),
347     eEncodingUint,
348     eFormatHex,
349     {arm64_dwarf::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
350     nullptr,
351     nullptr,
352     nullptr,
353     0},
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    {"cpsr",
388     "psr",
389     4,
390     OFFSET(cpsr),
391     eEncodingUint,
392     eFormatHex,
393     {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
394     nullptr,
395     nullptr,
396     nullptr,
397     0},
398    {"fpsr",
399     nullptr,
400     4,
401     OFFSET(fpsr),
402     eEncodingUint,
403     eFormatHex,
404     {INV, INV, INV, INV, reg_fpsr},
405     nullptr,
406     nullptr,
407     nullptr,
408     0},
409    {"fpcr",
410     nullptr,
411     4,
412     OFFSET(fpcr),
413     eEncodingUint,
414     eFormatHex,
415     {INV, INV, INV, INV, reg_fpcr},
416     nullptr,
417     nullptr,
418     nullptr,
419     0},
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 = llvm::array_lengthof(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 = llvm::array_lengthof(g_gpr_regnums) - 1;
762constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1;
763
764static RegisterSet g_reg_sets[] = {
765    {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
766    {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
767};
768
769constexpr size_t k_num_reg_sets = llvm::array_lengthof(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);
776  for (unsigned i = 0; i < 32; ++i)
777    m_regs.x[i] = data.GetU64(&offset);
778  m_regs.pc = data.GetU64(&offset);
779  m_regs.cpsr = data.GetU32(&offset);
780  m_regs.fpsr = data.GetU32(&offset);
781  m_regs.fpcr = data.GetU32(&offset);
782  auto regs_data = data.GetData(&offset, sizeof(m_regs.v));
783  if (regs_data)
784    memcpy(m_regs.v, regs_data, 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, (const uint8_t *)&m_regs + reg_info->byte_offset,
817      reg_info->byte_size, 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