1 //===-- RegisterContextMinidump_ARM64.cpp ---------------------------------===//
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, \
37 "w" #i, nullptr, 4, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
38 {INV, INV, INV, INV, reg_w##i}, nullptr, nullptr, nullptr, \
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, \
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, \
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
= std::size(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
= std::size(g_gpr_regnums
) - 1;
762 constexpr size_t k_num_fpu_regs
= std::size(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
= std::size(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
;