LLDB  mainline
RegisterContextMinidump_ARM.cpp
Go to the documentation of this file.
1 //===-- RegisterContextMinidump_ARM.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 
10 
15 #include "lldb/lldb-enumerations.h"
16 
17 // C includes
18 #include <assert.h>
19 
20 // C++ includes
21 
22 using namespace lldb;
23 using namespace lldb_private;
24 using namespace minidump;
25 
26 #define INV LLDB_INVALID_REGNUM
27 #define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r))
28 
29 #define DEF_R(i) \
30  { \
31  "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \
32  {dwarf_r##i, dwarf_r##i, INV, INV, reg_r##i}, \
33  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  {dwarf_r##i, 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, {dwarf_d##i, 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  {dwarf_s##i, dwarf_s##i, INV, INV, reg_s##i}, \
54  nullptr, nullptr, nullptr, 0 \
55  }
56 
57 #define DEF_Q(i) \
58  { \
59  "q" #i, nullptr, 16, OFFSET(q) + i * 16, eEncodingVector, \
60  eFormatVectorOfUInt8, {dwarf_q##i, dwarf_q##i, INV, INV, reg_q##i}, \
61  nullptr, nullptr, nullptr, 0 \
62  }
63 
64 // Zero based LLDB register numbers for this register context
65 enum {
66  // General Purpose Registers
84  // Floating Point Registers
167 };
168 
169 static RegisterInfo g_reg_info_apple_fp = {
170  "fp",
171  "r7",
172  4,
173  OFFSET(r) + 7 * 4,
175  eFormatHex,
177  nullptr,
178  nullptr,
179  nullptr,
180  0};
181 
182 static RegisterInfo g_reg_info_fp = {
183  "fp",
184  "r11",
185  4,
186  OFFSET(r) + 11 * 4,
188  eFormatHex,
190  nullptr,
191  nullptr,
192  nullptr,
193  0};
194 
195 // Register info definitions for this register context
196 static RegisterInfo g_reg_infos[] = {
197  DEF_R_ARG(0, 1),
198  DEF_R_ARG(1, 2),
199  DEF_R_ARG(2, 3),
200  DEF_R_ARG(3, 4),
201  DEF_R(4),
202  DEF_R(5),
203  DEF_R(6),
204  DEF_R(7),
205  DEF_R(8),
206  DEF_R(9),
207  DEF_R(10),
208  DEF_R(11),
209  DEF_R(12),
210  {"sp",
211  "r13",
212  4,
213  OFFSET(r) + 13 * 4,
215  eFormatHex,
217  nullptr,
218  nullptr,
219  nullptr,
220  0},
221  {"lr",
222  "r14",
223  4,
224  OFFSET(r) + 14 * 4,
226  eFormatHex,
228  nullptr,
229  nullptr,
230  nullptr,
231  0},
232  {"pc",
233  "r15",
234  4,
235  OFFSET(r) + 15 * 4,
237  eFormatHex,
239  nullptr,
240  nullptr,
241  nullptr,
242  0},
243  {"cpsr",
244  "psr",
245  4,
246  OFFSET(cpsr),
248  eFormatHex,
250  nullptr,
251  nullptr,
252  nullptr,
253  0},
254  {"fpscr",
255  nullptr,
256  8,
257  OFFSET(fpscr),
259  eFormatHex,
260  {INV, INV, INV, INV, reg_fpscr},
261  nullptr,
262  nullptr,
263  nullptr,
264  0},
265  DEF_D(0),
266  DEF_D(1),
267  DEF_D(2),
268  DEF_D(3),
269  DEF_D(4),
270  DEF_D(5),
271  DEF_D(6),
272  DEF_D(7),
273  DEF_D(8),
274  DEF_D(9),
275  DEF_D(10),
276  DEF_D(11),
277  DEF_D(12),
278  DEF_D(13),
279  DEF_D(14),
280  DEF_D(15),
281  DEF_D(16),
282  DEF_D(17),
283  DEF_D(18),
284  DEF_D(19),
285  DEF_D(20),
286  DEF_D(21),
287  DEF_D(22),
288  DEF_D(23),
289  DEF_D(24),
290  DEF_D(25),
291  DEF_D(26),
292  DEF_D(27),
293  DEF_D(28),
294  DEF_D(29),
295  DEF_D(30),
296  DEF_D(31),
297  DEF_S(0),
298  DEF_S(1),
299  DEF_S(2),
300  DEF_S(3),
301  DEF_S(4),
302  DEF_S(5),
303  DEF_S(6),
304  DEF_S(7),
305  DEF_S(8),
306  DEF_S(9),
307  DEF_S(10),
308  DEF_S(11),
309  DEF_S(12),
310  DEF_S(13),
311  DEF_S(14),
312  DEF_S(15),
313  DEF_S(16),
314  DEF_S(17),
315  DEF_S(18),
316  DEF_S(19),
317  DEF_S(20),
318  DEF_S(21),
319  DEF_S(22),
320  DEF_S(23),
321  DEF_S(24),
322  DEF_S(25),
323  DEF_S(26),
324  DEF_S(27),
325  DEF_S(28),
326  DEF_S(29),
327  DEF_S(30),
328  DEF_S(31),
329  DEF_Q(0),
330  DEF_Q(1),
331  DEF_Q(2),
332  DEF_Q(3),
333  DEF_Q(4),
334  DEF_Q(5),
335  DEF_Q(6),
336  DEF_Q(7),
337  DEF_Q(8),
338  DEF_Q(9),
339  DEF_Q(10),
340  DEF_Q(11),
341  DEF_Q(12),
342  DEF_Q(13),
343  DEF_Q(14),
344  DEF_Q(15)};
345 
346 constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos);
347 
348 // ARM general purpose registers.
350  reg_r0,
351  reg_r1,
352  reg_r2,
353  reg_r3,
354  reg_r4,
355  reg_r5,
356  reg_r6,
357  reg_r7,
358  reg_r8,
359  reg_r9,
360  reg_r10,
361  reg_r11,
362  reg_r12,
363  reg_sp,
364  reg_lr,
365  reg_pc,
366  reg_cpsr,
367  LLDB_INVALID_REGNUM // register sets need to end with this flag
368 };
370  reg_fpscr,
371  reg_d0,
372  reg_d1,
373  reg_d2,
374  reg_d3,
375  reg_d4,
376  reg_d5,
377  reg_d6,
378  reg_d7,
379  reg_d8,
380  reg_d9,
381  reg_d10,
382  reg_d11,
383  reg_d12,
384  reg_d13,
385  reg_d14,
386  reg_d15,
387  reg_d16,
388  reg_d17,
389  reg_d18,
390  reg_d19,
391  reg_d20,
392  reg_d21,
393  reg_d22,
394  reg_d23,
395  reg_d24,
396  reg_d25,
397  reg_d26,
398  reg_d27,
399  reg_d28,
400  reg_d29,
401  reg_d30,
402  reg_d31,
403  reg_s0,
404  reg_s1,
405  reg_s2,
406  reg_s3,
407  reg_s4,
408  reg_s5,
409  reg_s6,
410  reg_s7,
411  reg_s8,
412  reg_s9,
413  reg_s10,
414  reg_s11,
415  reg_s12,
416  reg_s13,
417  reg_s14,
418  reg_s15,
419  reg_s16,
420  reg_s17,
421  reg_s18,
422  reg_s19,
423  reg_s20,
424  reg_s21,
425  reg_s22,
426  reg_s23,
427  reg_s24,
428  reg_s25,
429  reg_s26,
430  reg_s27,
431  reg_s28,
432  reg_s29,
433  reg_s30,
434  reg_s31,
435  reg_q0,
436  reg_q1,
437  reg_q2,
438  reg_q3,
439  reg_q4,
440  reg_q5,
441  reg_q6,
442  reg_q7,
443  reg_q8,
444  reg_q9,
445  reg_q10,
446  reg_q11,
447  reg_q12,
448  reg_q13,
449  reg_q14,
450  reg_q15,
451  LLDB_INVALID_REGNUM // register sets need to end with this flag
452 };
453 
454 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
455 constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1;
456 constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1;
457 
458 static RegisterSet g_reg_sets[] = {
459  {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
460  {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
461 };
462 
463 constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets);
464 
465 RegisterContextMinidump_ARM::RegisterContextMinidump_ARM(
466  lldb_private::Thread &thread, const DataExtractor &data, bool apple)
467  : RegisterContext(thread, 0), m_apple(apple) {
468  lldb::offset_t offset = 0;
469  m_regs.context_flags = data.GetU32(&offset);
470  for (unsigned i = 0; i < llvm::array_lengthof(m_regs.r); ++i)
471  m_regs.r[i] = data.GetU32(&offset);
472  m_regs.cpsr = data.GetU32(&offset);
473  m_regs.fpscr = data.GetU64(&offset);
474  for (unsigned i = 0; i < llvm::array_lengthof(m_regs.d); ++i)
475  m_regs.d[i] = data.GetU64(&offset);
477 }
478 
480 
481 const RegisterInfo *
483  if (reg < k_num_reg_infos) {
484  if (m_apple) {
485  if (reg == reg_r7)
486  return &g_reg_info_apple_fp;
487  } else {
488  if (reg == reg_r11)
489  return &g_reg_info_fp;
490  }
491  return &g_reg_infos[reg];
492  }
493  return nullptr;
494 }
495 
497  return k_num_reg_sets;
498 }
499 
500 const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) {
501  if (set < k_num_reg_sets)
502  return &g_reg_sets[set];
503  return nullptr;
504 }
505 
507  if (reg < k_num_reg_infos)
508  return g_reg_infos[reg].name;
509  return nullptr;
510 }
511 
512 bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,
513  RegisterValue &reg_value) {
514  Status error;
515  reg_value.SetFromMemoryData(
516  reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
517  reg_info->byte_size, lldb::eByteOrderLittle, error);
518  return error.Success();
519 }
520 
522  const RegisterValue &) {
523  return false;
524 }
525 
527  lldb::RegisterKind kind, uint32_t num) {
528  for (size_t i = 0; i < k_num_regs; ++i) {
529  if (g_reg_infos[i].kinds[kind] == num)
530  return i;
531  }
532  return LLDB_INVALID_REGNUM;
533 }
#define OFFSET(r)
#define LLDB_REGNUM_GENERIC_PC
Definition: lldb-defines.h:63
An data extractor class.
Definition: DataExtractor.h:47
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
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
uint64_t offset_t
Definition: lldb-types.h:87
#define DEF_D(i)
const lldb_private::RegisterSet * GetRegisterSet(size_t set) override
#define DEF_R(i)
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:67
#define DEF_Q(i)
bool Success() const
Test for success condition.
Definition: Status.cpp:287
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[]