1 //===-- RegisterContextMinidump_ARM.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_ARM.h"
10 
11 #include "Utility/ARM_DWARF_Registers.h"
12 #include "Utility/ARM_ehframe_Registers.h"
13 #include "lldb/Utility/RegisterValue.h"
14 #include "lldb/Utility/DataExtractor.h"
15 #include "lldb/Utility/LLDBAssert.h"
16 #include "lldb/lldb-enumerations.h"
17 
18 // C includes
19 #include <cassert>
20 
21 // C++ includes
22 
23 using namespace lldb;
24 using namespace lldb_private;
25 using namespace minidump;
26 
27 #define INV LLDB_INVALID_REGNUM
28 #define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r))
29 
30 #define DEF_R(i)                                                               \
31   {                                                                            \
32     "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex,          \
33         {ehframe_r##i, dwarf_r##i, INV, INV, reg_r##i}, nullptr, nullptr,      \
34         nullptr,                                                               \
35   }
36 
37 #define DEF_R_ARG(i, n)                                                        \
38   {                                                                            \
39     "r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex,         \
40         {ehframe_r##i, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV,          \
41          reg_r##i},                                                            \
42         nullptr, nullptr, nullptr,                                             \
43   }
44 
45 #define DEF_D(i)                                                               \
46   {                                                                            \
47     "d" #i, nullptr, 8, OFFSET(d) + i * 8, eEncodingVector,                    \
48         eFormatVectorOfUInt8, {dwarf_d##i, dwarf_d##i, INV, INV, reg_d##i},    \
49         nullptr, nullptr, nullptr,                                             \
50   }
51 
52 #define DEF_S(i)                                                               \
53   {                                                                            \
54     "s" #i, nullptr, 4, OFFSET(s) + i * 4, eEncodingIEEE754, eFormatFloat,     \
55         {dwarf_s##i, dwarf_s##i, INV, INV, reg_s##i}, nullptr, nullptr,        \
56         nullptr,                                                               \
57   }
58 
59 #define DEF_Q(i)                                                               \
60   {                                                                            \
61     "q" #i, nullptr, 16, OFFSET(q) + i * 16, eEncodingVector,                  \
62         eFormatVectorOfUInt8, {dwarf_q##i, dwarf_q##i, INV, INV, reg_q##i},    \
63         nullptr, nullptr, nullptr,                                             \
64   }
65 
66 // Zero based LLDB register numbers for this register context
67 enum {
68   // General Purpose Registers
69   reg_r0,
70   reg_r1,
71   reg_r2,
72   reg_r3,
73   reg_r4,
74   reg_r5,
75   reg_r6,
76   reg_r7,
77   reg_r8,
78   reg_r9,
79   reg_r10,
80   reg_r11,
81   reg_r12,
82   reg_sp,
83   reg_lr,
84   reg_pc,
85   reg_cpsr,
86   // Floating Point Registers
87   reg_fpscr,
88   reg_d0,
89   reg_d1,
90   reg_d2,
91   reg_d3,
92   reg_d4,
93   reg_d5,
94   reg_d6,
95   reg_d7,
96   reg_d8,
97   reg_d9,
98   reg_d10,
99   reg_d11,
100   reg_d12,
101   reg_d13,
102   reg_d14,
103   reg_d15,
104   reg_d16,
105   reg_d17,
106   reg_d18,
107   reg_d19,
108   reg_d20,
109   reg_d21,
110   reg_d22,
111   reg_d23,
112   reg_d24,
113   reg_d25,
114   reg_d26,
115   reg_d27,
116   reg_d28,
117   reg_d29,
118   reg_d30,
119   reg_d31,
120   reg_s0,
121   reg_s1,
122   reg_s2,
123   reg_s3,
124   reg_s4,
125   reg_s5,
126   reg_s6,
127   reg_s7,
128   reg_s8,
129   reg_s9,
130   reg_s10,
131   reg_s11,
132   reg_s12,
133   reg_s13,
134   reg_s14,
135   reg_s15,
136   reg_s16,
137   reg_s17,
138   reg_s18,
139   reg_s19,
140   reg_s20,
141   reg_s21,
142   reg_s22,
143   reg_s23,
144   reg_s24,
145   reg_s25,
146   reg_s26,
147   reg_s27,
148   reg_s28,
149   reg_s29,
150   reg_s30,
151   reg_s31,
152   reg_q0,
153   reg_q1,
154   reg_q2,
155   reg_q3,
156   reg_q4,
157   reg_q5,
158   reg_q6,
159   reg_q7,
160   reg_q8,
161   reg_q9,
162   reg_q10,
163   reg_q11,
164   reg_q12,
165   reg_q13,
166   reg_q14,
167   reg_q15,
168   k_num_regs
169 };
170 
171 static RegisterInfo g_reg_info_apple_fp = {
172     "fp",
173     "r7",
174     4,
175     OFFSET(r) + 7 * 4,
176     eEncodingUint,
177     eFormatHex,
178     {ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},
179     nullptr,
180     nullptr,
181     nullptr,
182 };
183 
184 static RegisterInfo g_reg_info_fp = {
185     "fp",
186     "r11",
187     4,
188     OFFSET(r) + 11 * 4,
189     eEncodingUint,
190     eFormatHex,
191     {ehframe_r11, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},
192     nullptr,
193     nullptr,
194     nullptr,
195 };
196 
197 // Register info definitions for this register context
198 static RegisterInfo g_reg_infos[] = {
199     DEF_R_ARG(0, 1),
200     DEF_R_ARG(1, 2),
201     DEF_R_ARG(2, 3),
202     DEF_R_ARG(3, 4),
203     DEF_R(4),
204     DEF_R(5),
205     DEF_R(6),
206     DEF_R(7),
207     DEF_R(8),
208     DEF_R(9),
209     DEF_R(10),
210     DEF_R(11),
211     DEF_R(12),
212     {"sp",
213      "r13",
214      4,
215      OFFSET(r) + 13 * 4,
216      eEncodingUint,
217      eFormatHex,
218      {ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
219      nullptr,
220      nullptr,
221      nullptr,
222     },
223     {"lr",
224      "r14",
225      4,
226      OFFSET(r) + 14 * 4,
227      eEncodingUint,
228      eFormatHex,
229      {ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
230      nullptr,
231      nullptr,
232      nullptr,
233     },
234     {"pc",
235      "r15",
236      4,
237      OFFSET(r) + 15 * 4,
238      eEncodingUint,
239      eFormatHex,
240      {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
241      nullptr,
242      nullptr,
243      nullptr,
244     },
245     {"cpsr",
246      "psr",
247      4,
248      OFFSET(cpsr),
249      eEncodingUint,
250      eFormatHex,
251      {ehframe_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
252      nullptr,
253      nullptr,
254      nullptr,
255     },
256     {"fpscr",
257      nullptr,
258      8,
259      OFFSET(fpscr),
260      eEncodingUint,
261      eFormatHex,
262      {INV, INV, INV, INV, reg_fpscr},
263      nullptr,
264      nullptr,
265      nullptr,
266     },
267     DEF_D(0),
268     DEF_D(1),
269     DEF_D(2),
270     DEF_D(3),
271     DEF_D(4),
272     DEF_D(5),
273     DEF_D(6),
274     DEF_D(7),
275     DEF_D(8),
276     DEF_D(9),
277     DEF_D(10),
278     DEF_D(11),
279     DEF_D(12),
280     DEF_D(13),
281     DEF_D(14),
282     DEF_D(15),
283     DEF_D(16),
284     DEF_D(17),
285     DEF_D(18),
286     DEF_D(19),
287     DEF_D(20),
288     DEF_D(21),
289     DEF_D(22),
290     DEF_D(23),
291     DEF_D(24),
292     DEF_D(25),
293     DEF_D(26),
294     DEF_D(27),
295     DEF_D(28),
296     DEF_D(29),
297     DEF_D(30),
298     DEF_D(31),
299     DEF_S(0),
300     DEF_S(1),
301     DEF_S(2),
302     DEF_S(3),
303     DEF_S(4),
304     DEF_S(5),
305     DEF_S(6),
306     DEF_S(7),
307     DEF_S(8),
308     DEF_S(9),
309     DEF_S(10),
310     DEF_S(11),
311     DEF_S(12),
312     DEF_S(13),
313     DEF_S(14),
314     DEF_S(15),
315     DEF_S(16),
316     DEF_S(17),
317     DEF_S(18),
318     DEF_S(19),
319     DEF_S(20),
320     DEF_S(21),
321     DEF_S(22),
322     DEF_S(23),
323     DEF_S(24),
324     DEF_S(25),
325     DEF_S(26),
326     DEF_S(27),
327     DEF_S(28),
328     DEF_S(29),
329     DEF_S(30),
330     DEF_S(31),
331     DEF_Q(0),
332     DEF_Q(1),
333     DEF_Q(2),
334     DEF_Q(3),
335     DEF_Q(4),
336     DEF_Q(5),
337     DEF_Q(6),
338     DEF_Q(7),
339     DEF_Q(8),
340     DEF_Q(9),
341     DEF_Q(10),
342     DEF_Q(11),
343     DEF_Q(12),
344     DEF_Q(13),
345     DEF_Q(14),
346     DEF_Q(15)};
347 
348 constexpr size_t k_num_reg_infos = std::size(g_reg_infos);
349 
350 // ARM general purpose registers.
351 const uint32_t g_gpr_regnums[] = {
352     reg_r0,
353     reg_r1,
354     reg_r2,
355     reg_r3,
356     reg_r4,
357     reg_r5,
358     reg_r6,
359     reg_r7,
360     reg_r8,
361     reg_r9,
362     reg_r10,
363     reg_r11,
364     reg_r12,
365     reg_sp,
366     reg_lr,
367     reg_pc,
368     reg_cpsr,
369     LLDB_INVALID_REGNUM // register sets need to end with this flag
370 };
371 const uint32_t g_fpu_regnums[] = {
372     reg_fpscr,
373     reg_d0,
374     reg_d1,
375     reg_d2,
376     reg_d3,
377     reg_d4,
378     reg_d5,
379     reg_d6,
380     reg_d7,
381     reg_d8,
382     reg_d9,
383     reg_d10,
384     reg_d11,
385     reg_d12,
386     reg_d13,
387     reg_d14,
388     reg_d15,
389     reg_d16,
390     reg_d17,
391     reg_d18,
392     reg_d19,
393     reg_d20,
394     reg_d21,
395     reg_d22,
396     reg_d23,
397     reg_d24,
398     reg_d25,
399     reg_d26,
400     reg_d27,
401     reg_d28,
402     reg_d29,
403     reg_d30,
404     reg_d31,
405     reg_s0,
406     reg_s1,
407     reg_s2,
408     reg_s3,
409     reg_s4,
410     reg_s5,
411     reg_s6,
412     reg_s7,
413     reg_s8,
414     reg_s9,
415     reg_s10,
416     reg_s11,
417     reg_s12,
418     reg_s13,
419     reg_s14,
420     reg_s15,
421     reg_s16,
422     reg_s17,
423     reg_s18,
424     reg_s19,
425     reg_s20,
426     reg_s21,
427     reg_s22,
428     reg_s23,
429     reg_s24,
430     reg_s25,
431     reg_s26,
432     reg_s27,
433     reg_s28,
434     reg_s29,
435     reg_s30,
436     reg_s31,
437     reg_q0,
438     reg_q1,
439     reg_q2,
440     reg_q3,
441     reg_q4,
442     reg_q5,
443     reg_q6,
444     reg_q7,
445     reg_q8,
446     reg_q9,
447     reg_q10,
448     reg_q11,
449     reg_q12,
450     reg_q13,
451     reg_q14,
452     reg_q15,
453     LLDB_INVALID_REGNUM // register sets need to end with this flag
454 };
455 
456 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
457 constexpr size_t k_num_gpr_regs = std::size(g_gpr_regnums) - 1;
458 constexpr size_t k_num_fpu_regs = std::size(g_fpu_regnums) - 1;
459 
460 static RegisterSet g_reg_sets[] = {
461     {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
462     {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
463 };
464 
465 constexpr size_t k_num_reg_sets = std::size(g_reg_sets);
466 
467 RegisterContextMinidump_ARM::RegisterContextMinidump_ARM(
468     lldb_private::Thread &thread, const DataExtractor &data, bool apple)
469     : RegisterContext(thread, 0), m_apple(apple) {
470   lldb::offset_t offset = 0;
471   m_regs.context_flags = data.GetU32(&offset);
472   for (unsigned i = 0; i < std::size(m_regs.r); ++i)
473     m_regs.r[i] = data.GetU32(&offset);
474   m_regs.cpsr = data.GetU32(&offset);
475   m_regs.fpscr = data.GetU64(&offset);
476   for (unsigned i = 0; i < std::size(m_regs.d); ++i)
477     m_regs.d[i] = data.GetU64(&offset);
478   lldbassert(k_num_regs == k_num_reg_infos);
479 }
480 
481 size_t RegisterContextMinidump_ARM::GetRegisterCountStatic() {
482   return k_num_regs;
483 }
484 
485 // Used for unit testing so we can verify register info is filled in for
486 // all register flavors (DWARF, EH Frame, generic, etc).
487 size_t RegisterContextMinidump_ARM::GetRegisterCount() {
488   return GetRegisterCountStatic();
489 }
490 
491 // Used for unit testing so we can verify register info is filled in.
492 const RegisterInfo *
493 RegisterContextMinidump_ARM::GetRegisterInfoAtIndexStatic(size_t reg,
494                                                           bool apple) {
495   if (reg < k_num_reg_infos) {
496     if (apple) {
497       if (reg == reg_r7)
498         return &g_reg_info_apple_fp;
499     } else {
500       if (reg == reg_r11)
501         return &g_reg_info_fp;
502     }
503     return &g_reg_infos[reg];
504   }
505   return nullptr;
506 }
507 
508 const RegisterInfo *
509 RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {
510   return GetRegisterInfoAtIndexStatic(reg, m_apple);
511 }
512 
513 size_t RegisterContextMinidump_ARM::GetRegisterSetCount() {
514   return k_num_reg_sets;
515 }
516 
517 const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) {
518   if (set < k_num_reg_sets)
519     return &g_reg_sets[set];
520   return nullptr;
521 }
522 
523 const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) {
524   if (reg < k_num_reg_infos)
525     return g_reg_infos[reg].name;
526   return nullptr;
527 }
528 
529 bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,
530                                                RegisterValue &reg_value) {
531   Status error;
532   reg_value.SetFromMemoryData(
533       *reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
534       reg_info->byte_size, lldb::eByteOrderLittle, error);
535   return error.Success();
536 }
537 
538 bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *,
539                                                 const RegisterValue &) {
540   return false;
541 }
542 
543 uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber(
544     lldb::RegisterKind kind, uint32_t num) {
545   for (size_t i = 0; i < k_num_regs; ++i) {
546     if (g_reg_infos[i].kinds[kind] == num)
547       return i;
548   }
549   return LLDB_INVALID_REGNUM;
550 }
551