LLDB  mainline
RegisterContextMinidump_ARM.cpp
Go to the documentation of this file.
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 
10 
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
85  // Floating Point Registers
168 };
169 
170 static RegisterInfo g_reg_info_apple_fp = {
171  "fp",
172  "r7",
173  4,
174  OFFSET(r) + 7 * 4,
176  eFormatHex,
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,
189  eFormatHex,
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,
216  eFormatHex,
218  nullptr,
219  nullptr,
220  nullptr,
221  0},
222  {"lr",
223  "r14",
224  4,
225  OFFSET(r) + 14 * 4,
227  eFormatHex,
229  nullptr,
230  nullptr,
231  nullptr,
232  0},
233  {"pc",
234  "r15",
235  4,
236  OFFSET(r) + 15 * 4,
238  eFormatHex,
240  nullptr,
241  nullptr,
242  nullptr,
243  0},
244  {"cpsr",
245  "psr",
246  4,
247  OFFSET(cpsr),
249  eFormatHex,
251  nullptr,
252  nullptr,
253  nullptr,
254  0},
255  {"fpscr",
256  nullptr,
257  8,
258  OFFSET(fpscr),
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.
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 };
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 
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);
478 }
479 
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).
487  return GetRegisterCountStatic();
488 }
489 
490 // Used for unit testing so we can verify register info is filled in.
491 const RegisterInfo *
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 *
510 }
511 
513  return k_num_reg_sets;
514 }
515 
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 
523  if (reg < k_num_reg_infos)
524  return g_reg_infos[reg].name;
525  return nullptr;
526 }
527 
528 bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,
529  RegisterValue &reg_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 
538  const RegisterValue &) {
539  return false;
540 }
541 
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 }
#define OFFSET(r)
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
An data extractor class.
Definition: DataExtractor.h:46
A class that represents a running process on the host machine.
constexpr size_t k_num_reg_infos
#define lldbassert(x)
Definition: LLDBAssert.h:15
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
#define LLDB_REGNUM_GENERIC_RA
Definition: lldb-defines.h:66
constexpr size_t k_num_fpu_regs
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override
Convert from a given register numbering scheme to the lldb register numbering scheme.
bool ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override
#define LLDB_REGNUM_GENERIC_SP
Definition: lldb-defines.h:64
#define DEF_R_ARG(i, n)
#define DEF_S(i)
#define LLDB_REGNUM_GENERIC_FP
Definition: lldb-defines.h:65
RegisterKind
Register numbering types.
uint64_t offset_t
Definition: lldb-types.h:87
static const lldb_private::RegisterInfo * GetRegisterInfoAtIndexStatic(size_t reg, bool apple)
#define DEF_D(i)
const lldb_private::RegisterSet * GetRegisterSet(size_t set) override
#define DEF_R(i)
unsigned integer
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:67
#define DEF_Q(i)
bool Success() const
Test for success condition.
Definition: Status.cpp:288
const uint32_t g_fpu_regnums[]
static RegisterSet g_reg_sets[]
bool WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override
static RegisterInfo g_reg_info_apple_fp
constexpr size_t k_num_gpr_regs
constexpr size_t k_num_reg_sets
Definition: SBAddress.h:15
static RegisterInfo g_reg_info_fp
uint32_t SetFromMemoryData(const RegisterInfo *reg_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
static RegisterInfo g_reg_infos[]
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
An error handling class.
Definition: Status.h:44
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:90
const uint32_t g_gpr_regnums[]