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