1 //===-- RegisterContextMinidump_ARM64.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_ARM64.h"
11 #include "Utility/ARM64_DWARF_Registers.h"
12 #include "lldb/Utility/RegisterValue.h"
13 #include "lldb/Utility/DataExtractor.h"
14 #include "lldb/lldb-enumerations.h"
22 using namespace lldb_private;
23 using namespace minidump;
25 #define INV LLDB_INVALID_REGNUM
26 #define OFFSET(r) (offsetof(RegisterContextMinidump_ARM64::Context, r))
30 "x" #i, nullptr, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
31 {arm64_dwarf::x##i, arm64_dwarf::x##i, INV, INV, reg_x##i}, \
32 nullptr, nullptr, nullptr, 0 \
37 "w" #i, nullptr, 4, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
38 {INV, INV, INV, INV, reg_w##i}, nullptr, nullptr, nullptr, 0 \
41 #define DEF_X_ARG(i, n) \
43 "x" #i, "arg" #n, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
44 {arm64_dwarf::x##i, arm64_dwarf::x##i, LLDB_REGNUM_GENERIC_ARG1 + i, \
45 INV, reg_x##i}, nullptr, nullptr, nullptr, 0 \
50 "v" #i, nullptr, 16, OFFSET(v) + i * 16, eEncodingVector, \
51 eFormatVectorOfUInt8, {arm64_dwarf::v##i, arm64_dwarf::v##i, INV, INV, \
52 reg_v##i}, nullptr, nullptr, nullptr, 0 \
57 "d" #i, nullptr, 8, OFFSET(v) + i * 16, eEncodingVector, \
58 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_d##i}, nullptr, \
64 "s" #i, nullptr, 4, OFFSET(v) + i * 16, eEncodingVector, \
65 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_s##i}, nullptr, \
71 "h" #i, nullptr, 2, OFFSET(v) + i * 16, eEncodingVector, \
72 eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_h##i}, nullptr, \
76 // Zero based LLDB register numbers for this register context
78 // General Purpose Registers
145 // Floating Point Registers
279 // Register info definitions for this register context
280 static RegisterInfo g_reg_infos[] = {
316 {arm64_dwarf::x29, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, INV, reg_fp},
327 {arm64_dwarf::x30, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
338 {arm64_dwarf::x31, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
349 {arm64_dwarf::pc, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
393 {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
404 {INV, INV, INV, INV, reg_fpsr},
415 {INV, INV, INV, INV, reg_fpcr},
554 constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos);
556 // ARM64 general purpose registers.
557 const uint32_t g_gpr_regnums[] = {
624 LLDB_INVALID_REGNUM // register sets need to end with this flag
626 const uint32_t g_fpu_regnums[] = {
757 LLDB_INVALID_REGNUM // register sets need to end with this flag
760 // Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
761 constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1;
762 constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1;
764 static RegisterSet g_reg_sets[] = {
765 {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
766 {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
769 constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets);
771 RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64(
772 lldb_private::Thread &thread, const DataExtractor &data)
773 : RegisterContext(thread, 0) {
774 lldb::offset_t offset = 0;
775 m_regs.context_flags = data.GetU64(&offset);
776 for (unsigned i = 0; i < 32; ++i)
777 m_regs.x[i] = data.GetU64(&offset);
778 m_regs.pc = data.GetU64(&offset);
779 m_regs.cpsr = data.GetU32(&offset);
780 m_regs.fpsr = data.GetU32(&offset);
781 m_regs.fpcr = data.GetU32(&offset);
782 auto regs_data = data.GetData(&offset, sizeof(m_regs.v));
784 memcpy(m_regs.v, regs_data, sizeof(m_regs.v));
785 static_assert(k_num_regs == k_num_reg_infos, "");
787 size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; }
790 RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) {
791 if (reg < k_num_reg_infos)
792 return &g_reg_infos[reg];
796 size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() {
797 return k_num_reg_sets;
800 const RegisterSet *RegisterContextMinidump_ARM64::GetRegisterSet(size_t set) {
801 if (set < k_num_reg_sets)
802 return &g_reg_sets[set];
806 const char *RegisterContextMinidump_ARM64::GetRegisterName(unsigned reg) {
807 if (reg < k_num_reg_infos)
808 return g_reg_infos[reg].name;
812 bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info,
813 RegisterValue ®_value) {
815 reg_value.SetFromMemoryData(
816 reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
817 reg_info->byte_size, lldb::eByteOrderLittle, error);
818 return error.Success();
821 bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *,
822 const RegisterValue &) {
826 uint32_t RegisterContextMinidump_ARM64::ConvertRegisterKindToRegisterNumber(
827 lldb::RegisterKind kind, uint32_t num) {
828 for (size_t i = 0; i < k_num_regs; ++i) {
829 if (g_reg_infos[i].kinds[kind] == num)
832 return LLDB_INVALID_REGNUM;