9#if defined(__aarch64__) || defined(_M_ARM64)
20#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/ScopeExit.h"
26#define REG_CONTEXT_SIZE sizeof(::CONTEXT)
50 "g_gpr_regnums_arm64 has wrong number of register infos");
52static const uint32_t g_fpr_regnums_arm64[] = {
81static_assert(((
sizeof g_fpr_regnums_arm64 /
sizeof g_fpr_regnums_arm64[0]) -
83 "g_fpu_regnums_arm64 has wrong number of register infos");
88 {
"Floating Point Registers",
"fpr", std::size(g_fpr_regnums_arm64) - 1,
97CreateRegisterInfoInterface(
const ArchSpec &target_arch) {
98 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
99 "Register setting path assumes this is a 64-bit host");
104static Status GetThreadContextLength(DWORD context_flags,
105 DWORD &context_length) {
109 if (InitializeContext(
nullptr, context_flags,
nullptr, &context_length)) {
115 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
118 "InitializeContext failed with unexpected error {0}, expected "
119 "ERROR_INSUFFICIENT_BUFFER",
128 DWORD context_flags, PCONTEXT &context,
132 DWORD context_length = 0;
134 if (!context_buffer) {
140 error = GetThreadContextLength(context_flags, context_length);
144 if (context_buffer->
SetByteSize(context_length) != context_length) {
150 if (!InitializeContext(context_buffer->
GetBytes(), context_flags, &context,
153 LLDB_LOG(log,
"InitializeContext failed with error {0}",
error);
157 if (!::GetThreadContext(thread_handle, context)) {
159 LLDB_LOG(log,
"GetThreadContext failed with error {0}",
error);
170 if (!::SetThreadContext(thread_handle, context)) {
172 LLDB_LOG(log,
"SetThreadContext failed with error {0}",
error);
178std::unique_ptr<NativeRegisterContextWindows>
182 return std::make_unique<NativeRegisterContextWindows_arm64>(target_arch,
186NativeRegisterContextWindows_arm64::NativeRegisterContextWindows_arm64(
189 native_thread, CreateRegisterInfoInterface(target_arch)),
190 m_context(nullptr), m_context_buffer(nullptr) {
194 m_max_hwp_supported = 1;
197bool NativeRegisterContextWindows_arm64::IsGPR(uint32_t reg_index)
const {
201bool NativeRegisterContextWindows_arm64::IsFPR(uint32_t reg_index)
const {
205uint32_t NativeRegisterContextWindows_arm64::GetRegisterSetCount()
const {
210NativeRegisterContextWindows_arm64::GetRegisterSet(uint32_t set_index)
const {
216Status NativeRegisterContextWindows_arm64::GPRRead(
const uint32_t reg,
301 static_cast<uint32_t
>(m_context->X[reg -
gpr_w0_arm64] & 0xffffffff));
309NativeRegisterContextWindows_arm64::GPRWrite(
const uint32_t reg,
311 auto cleanup = llvm::make_scope_exit([&]() { m_context =
nullptr; });
313 PCONTEXT context =
nullptr;
315 DWORD context_flags = CONTEXT_CONTROL | CONTEXT_INTEGER;
316 auto thread_handle = GetThreadHandle();
318 Status error = GetThreadContextHelper(thread_handle, context_flags, context,
405 return SetThreadContextHelper(thread_handle, context);
408Status NativeRegisterContextWindows_arm64::FPRRead(
const uint32_t reg,
534NativeRegisterContextWindows_arm64::FPRWrite(
const uint32_t reg,
536 auto cleanup = llvm::make_scope_exit([&]() { m_context =
nullptr; });
538 PCONTEXT context =
nullptr;
540 DWORD context_flags = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
541 auto thread_handle = GetThreadHandle();
543 Status error = GetThreadContextHelper(thread_handle, context_flags, context,
663 return SetThreadContextHelper(thread_handle, context);
667NativeRegisterContextWindows_arm64::ReadRegister(
const RegisterInfo *reg_info,
680 "register \"%s\" is an internal-only lldb "
681 "register, cannot read directly",
687 return GPRRead(reg, reg_value);
690 return FPRRead(reg, reg_value);
695Status NativeRegisterContextWindows_arm64::WriteRegister(
709 "register \"%s\" is an internal-only lldb "
710 "register, cannot write directly",
716 return GPRWrite(reg, reg_value);
719 return FPRWrite(reg, reg_value);
724Status NativeRegisterContextWindows_arm64::ReadAllRegisterValues(
732 if (!m_context_buffer) {
738 data_sp = std::make_shared<DataBufferHeap>(m_context_buffer->GetBytes(),
739 m_context_buffer->GetByteSize());
744Status NativeRegisterContextWindows_arm64::WriteAllRegisterValues(
746 auto cleanup = llvm::make_scope_exit([&]() { m_context =
nullptr; });
757 DWORD context_flags = CONTEXT_ALL;
758 DWORD context_length = 0;
760 error = GetThreadContextLength(context_flags, context_length);
764 if (data_sp->GetByteSize() != context_length) {
766 "data_sp contained mismatched data size, expected {0}, actual {1}",
767 context_length, data_sp->GetByteSize());
772 PCONTEXT context =
nullptr;
774 error = GetThreadContextHelper(GetThreadHandle(), context_flags, context,
779 ::memcpy(context_buffer.
GetBytes(), data_sp->GetBytes(), context_length);
781 return SetThreadContextHelper(GetThreadHandle(), context);
784llvm::Error NativeRegisterContextWindows_arm64::ReadHardwareDebugInfo() {
787 return error.ToError();
789 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
790 m_hwp_regs[i].address = m_context->Wvr[i];
791 m_hwp_regs[i].control = m_context->Wcr[i];
794 return llvm::Error::success();
798NativeRegisterContextWindows_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
799 auto cleanup = llvm::make_scope_exit([&]() { m_context =
nullptr; });
801 PCONTEXT context =
nullptr;
803 DWORD context_flags = CONTEXT_DEBUG_REGISTERS;
804 auto thread_handle = GetThreadHandle();
806 Status error = GetThreadContextHelper(thread_handle, context_flags, context,
809 return error.ToError();
811 if (hwbType == eDREGTypeWATCH) {
812 for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
813 context->Wvr[i] = m_hwp_regs[i].address;
814 context->Wcr[i] = m_hwp_regs[i].control;
818 return SetThreadContextHelper(GetThreadHandle(), context).ToError();
821void NativeRegisterContextWindows_arm64::InvalidateAllRegisters() {
823 m_context_buffer.reset();
826Status NativeRegisterContextWindows_arm64::CacheAllRegisterValues() {
828 DWORD context_flags = CONTEXT_ALL;
830 if (m_context && (m_context->ContextFlags & context_flags) == context_flags)
835 if (!m_context_buffer)
836 m_context_buffer = std::make_shared<DataBufferHeap>();
838 error = GetThreadContextHelper(GetThreadHandle(), context_flags, m_context,
839 m_context_buffer.get());
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
static const uint32_t g_gpr_regnums_arm64[]
static const lldb_private::RegisterSet g_reg_sets_arm64[k_num_register_sets]
A subclass of DataBuffer that stores a data buffer on the heap.
lldb::offset_t SetByteSize(lldb::offset_t byte_size)
Set the number of bytes in the data buffer.
static std::unique_ptr< NativeRegisterContextWindows > CreateHostNativeRegisterContextWindows(const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
double GetAsDouble(double fail_value=0.0, bool *success_ptr=nullptr) const
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
float GetAsFloat(float fail_value=0.0f, bool *success_ptr=nullptr) const
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order)
const void * GetBytes() const
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
uint8_t * GetBytes()
Get a pointer to the data.
#define LLDB_INVALID_REGNUM
lldb::ByteOrder InlHostByteOrder()
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
@ k_num_gpr_registers_arm64
@ k_num_fpr_registers_arm64
@ eErrorTypeWin32
Standard Win32 error codes.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
Registers are grouped into register sets.