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