1 //===-- RegisterContextMinidump_ARM.cpp -------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "RegisterContextMinidump_ARM.h"
11 #include "Utility/ARM_DWARF_Registers.h"
12 #include "lldb/Utility/RegisterValue.h"
13 #include "lldb/Utility/DataExtractor.h"
14 #include "lldb/Utility/LLDBAssert.h"
15 #include "lldb/lldb-enumerations.h"
23 using namespace lldb_private;
24 using namespace minidump;
26 #define INV LLDB_INVALID_REGNUM
27 #define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r))
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 \
36 #define DEF_R_ARG(i, n) \
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 \
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 \
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 \
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 \
64 // Zero based LLDB register numbers for this register context
66 // General Purpose Registers
84 // Floating Point Registers
169 static RegisterInfo g_reg_info_apple_fp = {
176 {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},
182 static RegisterInfo g_reg_info_fp = {
189 {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},
195 // Register info definitions for this register context
196 static RegisterInfo g_reg_infos[] = {
216 {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
227 {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
238 {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
249 {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
260 {INV, INV, INV, INV, reg_fpscr},
346 constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos);
348 // ARM general purpose registers.
349 const uint32_t g_gpr_regnums[] = {
367 LLDB_INVALID_REGNUM // register sets need to end with this flag
369 const uint32_t g_fpu_regnums[] = {
451 LLDB_INVALID_REGNUM // register sets need to end with this flag
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;
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},
463 constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets);
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);
476 lldbassert(k_num_regs == k_num_reg_infos);
479 size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; }
482 RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {
483 if (reg < k_num_reg_infos) {
486 return &g_reg_info_apple_fp;
489 return &g_reg_info_fp;
491 return &g_reg_infos[reg];
496 size_t RegisterContextMinidump_ARM::GetRegisterSetCount() {
497 return k_num_reg_sets;
500 const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) {
501 if (set < k_num_reg_sets)
502 return &g_reg_sets[set];
506 const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) {
507 if (reg < k_num_reg_infos)
508 return g_reg_infos[reg].name;
512 bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,
513 RegisterValue ®_value) {
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();
521 bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *,
522 const RegisterValue &) {
526 uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber(
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)
532 return LLDB_INVALID_REGNUM;