9#if defined(__x86_64__) || defined(_M_X64)
24#include "llvm/ADT/STLExtras.h"
29#define REG_CONTEXT_SIZE sizeof(::CONTEXT)
42static const uint32_t g_fpr_regnums_x86_64[] = {
53 {
"Floating Point Registers",
"fpr", std::size(g_fpr_regnums_x86_64) - 1,
54 g_fpr_regnums_x86_64}};
61CreateRegisterInfoInterface(
const ArchSpec &target_arch) {
62 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
63 "Register setting path assumes this is a 64-bit host");
69 const DWORD control_flag) {
73 memset(context_ptr, 0,
sizeof(::CONTEXT));
74 context_ptr->ContextFlags = control_flag;
75 if (!::GetThreadContext(thread_handle, context_ptr)) {
76 error.SetError(GetLastError(), eErrorTypeWin32);
77 LLDB_LOG(log,
"{0} GetThreadContext failed with error {1}", __FUNCTION__,
85 PCONTEXT context_ptr) {
89 if (!::SetThreadContext(thread_handle, context_ptr)) {
90 error.SetError(GetLastError(), eErrorTypeWin32);
91 LLDB_LOG(log,
"{0} SetThreadContext failed with error {1}", __FUNCTION__,
98std::unique_ptr<NativeRegisterContextWindows>
99NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
103 return std::make_unique<NativeRegisterContextWindows_WoW64>(target_arch,
107 return std::make_unique<NativeRegisterContextWindows_x86_64>(target_arch,
111NativeRegisterContextWindows_x86_64::NativeRegisterContextWindows_x86_64(
114 CreateRegisterInfoInterface(target_arch)) {}
116bool NativeRegisterContextWindows_x86_64::IsGPR(uint32_t reg_index)
const {
117 return (reg_index >= k_first_gpr_x86_64 && reg_index < k_first_alias_x86_64);
120bool NativeRegisterContextWindows_x86_64::IsFPR(uint32_t reg_index)
const {
121 return (reg_index >= lldb_xmm0_x86_64 && reg_index <= k_last_fpr_x86_64);
124bool NativeRegisterContextWindows_x86_64::IsDR(uint32_t reg_index)
const {
125 return (reg_index >= lldb_dr0_x86_64 && reg_index <= lldb_dr7_x86_64);
128uint32_t NativeRegisterContextWindows_x86_64::GetRegisterSetCount()
const {
133NativeRegisterContextWindows_x86_64::GetRegisterSet(uint32_t set_index)
const {
139Status NativeRegisterContextWindows_x86_64::GPRRead(
const uint32_t reg,
141 ::CONTEXT tls_context;
142 DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
144 GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
201 reg_value.
SetUInt64(tls_context.EFlags | 0x2);
227NativeRegisterContextWindows_x86_64::GPRWrite(
const uint32_t reg,
229 ::CONTEXT tls_context;
230 DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
231 auto thread_handle = GetThreadHandle();
233 GetThreadContextHelper(thread_handle, &tls_context, context_flag);
312 return SetThreadContextHelper(thread_handle, &tls_context);
315Status NativeRegisterContextWindows_x86_64::FPRRead(
const uint32_t reg,
317 ::CONTEXT tls_context;
318 DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
320 GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
326 reg_value.
SetBytes(&tls_context.Xmm0, 16, endian::InlHostByteOrder());
329 reg_value.
SetBytes(&tls_context.Xmm1, 16, endian::InlHostByteOrder());
332 reg_value.
SetBytes(&tls_context.Xmm2, 16, endian::InlHostByteOrder());
335 reg_value.
SetBytes(&tls_context.Xmm3, 16, endian::InlHostByteOrder());
338 reg_value.
SetBytes(&tls_context.Xmm4, 16, endian::InlHostByteOrder());
341 reg_value.
SetBytes(&tls_context.Xmm5, 16, endian::InlHostByteOrder());
344 reg_value.
SetBytes(&tls_context.Xmm6, 16, endian::InlHostByteOrder());
347 reg_value.
SetBytes(&tls_context.Xmm7, 16, endian::InlHostByteOrder());
350 reg_value.
SetBytes(&tls_context.Xmm8, 16, endian::InlHostByteOrder());
353 reg_value.
SetBytes(&tls_context.Xmm9, 16, endian::InlHostByteOrder());
356 reg_value.
SetBytes(&tls_context.Xmm10, 16, endian::InlHostByteOrder());
359 reg_value.
SetBytes(&tls_context.Xmm11, 16, endian::InlHostByteOrder());
362 reg_value.
SetBytes(&tls_context.Xmm12, 16, endian::InlHostByteOrder());
365 reg_value.
SetBytes(&tls_context.Xmm13, 16, endian::InlHostByteOrder());
368 reg_value.
SetBytes(&tls_context.Xmm14, 16, endian::InlHostByteOrder());
371 reg_value.
SetBytes(&tls_context.Xmm15, 16, endian::InlHostByteOrder());
379NativeRegisterContextWindows_x86_64::FPRWrite(
const uint32_t reg,
381 ::CONTEXT tls_context;
382 DWORD context_flag = CONTEXT_CONTROL | CONTEXT_FLOATING_POINT;
383 auto thread_handle = GetThreadHandle();
385 GetThreadContextHelper(thread_handle, &tls_context, context_flag);
391 memcpy(&tls_context.Xmm0, reg_value.
GetBytes(), 16);
394 memcpy(&tls_context.Xmm1, reg_value.
GetBytes(), 16);
397 memcpy(&tls_context.Xmm2, reg_value.
GetBytes(), 16);
400 memcpy(&tls_context.Xmm3, reg_value.
GetBytes(), 16);
403 memcpy(&tls_context.Xmm4, reg_value.
GetBytes(), 16);
406 memcpy(&tls_context.Xmm5, reg_value.
GetBytes(), 16);
409 memcpy(&tls_context.Xmm6, reg_value.
GetBytes(), 16);
412 memcpy(&tls_context.Xmm7, reg_value.
GetBytes(), 16);
415 memcpy(&tls_context.Xmm8, reg_value.
GetBytes(), 16);
418 memcpy(&tls_context.Xmm9, reg_value.
GetBytes(), 16);
421 memcpy(&tls_context.Xmm10, reg_value.
GetBytes(), 16);
424 memcpy(&tls_context.Xmm11, reg_value.
GetBytes(), 16);
427 memcpy(&tls_context.Xmm12, reg_value.
GetBytes(), 16);
430 memcpy(&tls_context.Xmm13, reg_value.
GetBytes(), 16);
433 memcpy(&tls_context.Xmm14, reg_value.
GetBytes(), 16);
436 memcpy(&tls_context.Xmm15, reg_value.
GetBytes(), 16);
440 return SetThreadContextHelper(thread_handle, &tls_context);
443Status NativeRegisterContextWindows_x86_64::DRRead(
const uint32_t reg,
445 ::CONTEXT tls_context;
446 DWORD context_flag = CONTEXT_DEBUG_REGISTERS;
448 GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
466 return Status(
"register DR4 is obsolete");
468 return Status(
"register DR5 is obsolete");
481NativeRegisterContextWindows_x86_64::DRWrite(
const uint32_t reg,
483 ::CONTEXT tls_context;
484 DWORD context_flag = CONTEXT_DEBUG_REGISTERS;
485 auto thread_handle = GetThreadHandle();
487 GetThreadContextHelper(thread_handle, &tls_context, context_flag);
505 return Status(
"register DR4 is obsolete");
507 return Status(
"register DR5 is obsolete");
516 return SetThreadContextHelper(thread_handle, &tls_context);
520NativeRegisterContextWindows_x86_64::ReadRegister(
const RegisterInfo *reg_info,
524 error.SetErrorString(
"reg_info NULL");
532 error.SetErrorStringWithFormat(
"register \"%s\" is an internal-only lldb "
533 "register, cannot read directly",
539 return GPRRead(reg, reg_value);
542 return FPRRead(reg, reg_value);
545 return DRRead(reg, reg_value);
547 return Status(
"unimplemented");
550Status NativeRegisterContextWindows_x86_64::WriteRegister(
555 error.SetErrorString(
"reg_info NULL");
563 error.SetErrorStringWithFormat(
"register \"%s\" is an internal-only lldb "
564 "register, cannot write directly",
570 return GPRWrite(reg, reg_value);
573 return FPRWrite(reg, reg_value);
576 return DRWrite(reg, reg_value);
578 return Status(
"unimplemented");
581Status NativeRegisterContextWindows_x86_64::ReadAllRegisterValues(
584 data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
585 ::CONTEXT tls_context;
587 GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);
591 uint8_t *dst = data_sp->GetBytes();
592 ::memcpy(dst, &tls_context, data_size);
596Status NativeRegisterContextWindows_x86_64::WriteAllRegisterValues(
601 error.SetErrorStringWithFormat(
602 "NativeRegisterContextWindows_x86_64::%s invalid data_sp provided",
607 if (data_sp->GetByteSize() != data_size) {
608 error.SetErrorStringWithFormatv(
609 "data_sp contained mismatched data size, expected {0}, actual {1}",
610 data_size, data_sp->GetByteSize());
614 ::CONTEXT tls_context;
615 memcpy(&tls_context, data_sp->GetBytes(), data_size);
616 return SetThreadContextHelper(GetThreadHandle(), &tls_context);
619Status NativeRegisterContextWindows_x86_64::IsWatchpointHit(uint32_t wp_index,
623 if (wp_index >= NumSupportedHardwareWatchpoints())
624 return Status(
"watchpoint index out of range");
631 is_hit = reg_value.
GetAsUInt64() & (1ULL << wp_index);
636Status NativeRegisterContextWindows_x86_64::GetWatchpointHitIndex(
640 for (uint32_t i = 0; i < NumSupportedHardwareWatchpoints(); i++) {
656NativeRegisterContextWindows_x86_64::IsWatchpointVacant(uint32_t wp_index,
660 if (wp_index >= NumSupportedHardwareWatchpoints())
661 return Status(
"Watchpoint index out of range");
668 is_vacant = !(reg_value.
GetAsUInt64() & (1ULL << (2 * wp_index)));
673bool NativeRegisterContextWindows_x86_64::ClearHardwareWatchpoint(
675 if (wp_index >= NumSupportedHardwareWatchpoints())
686 uint64_t bit_mask = 1ULL << wp_index;
687 uint64_t status_bits = reg_value.
GetAsUInt64() & ~bit_mask;
696 error = DRRead(lldb_dr7_x86_64, reg_value);
700 bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
701 uint64_t control_bits = reg_value.
GetAsUInt64() & ~bit_mask;
702 return DRWrite(lldb_dr7_x86_64,
RegisterValue(control_bits)).Success();
705Status NativeRegisterContextWindows_x86_64::ClearAllHardwareWatchpoints() {
714 uint64_t status_bits = reg_value.
GetAsUInt64() & ~0xFULL;
721 error = DRRead(lldb_dr7_x86_64, reg_value);
725 uint64_t control_bits = reg_value.
GetAsUInt64() & ~0xFFFF00FFULL;
726 return DRWrite(lldb_dr7_x86_64,
RegisterValue(control_bits));
729uint32_t NativeRegisterContextWindows_x86_64::SetHardwareWatchpoint(
741 if (watch_flags == 0x2)
744 if (watch_flags != 0x1 && watch_flags != 0x3)
747 for (uint32_t wp_index = 0; wp_index < NumSupportedHardwareWatchpoints();
750 if (IsWatchpointVacant(wp_index, is_vacant).Fail())
754 if (!ClearHardwareWatchpoint(wp_index))
757 if (ApplyHardwareBreakpoint(wp_index, addr, size, watch_flags).Fail())
766Status NativeRegisterContextWindows_x86_64::ApplyHardwareBreakpoint(
767 uint32_t wp_index,
lldb::addr_t addr,
size_t size, uint32_t flags) {
769 auto error = DRRead(lldb_dr7_x86_64, reg_value);
774 uint64_t enable_bit = 1ULL << (2 * wp_index);
778 uint64_t rw_bits = flags << (16 + 4 * wp_index);
783 uint64_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
785 uint64_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
787 uint64_t control_bits = reg_value.
GetAsUInt64() & ~bit_mask;
788 control_bits |= enable_bit | rw_bits | size_bits;
802NativeRegisterContextWindows_x86_64::GetWatchpointAddress(uint32_t wp_index) {
803 if (wp_index >= NumSupportedHardwareWatchpoints())
807 if (DRRead(lldb_dr0_x86_64 + wp_index, reg_value).Fail())
814NativeRegisterContextWindows_x86_64::NumSupportedHardwareWatchpoints() {
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
constexpr size_t k_num_register_sets
static const uint32_t g_gpr_regnums_x86_64[]
static const RegisterSet g_reg_sets_x86_64[]
An architecture specification class.
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
RegisterInfo interface to patch RegisterInfo structure for archs.
uint16_t GetAsUInt16(uint16_t fail_value=UINT16_MAX, bool *success_ptr=nullptr) const
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
void SetUInt16(uint16_t uint)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
void SetBytes(const void *bytes, size_t length, lldb::ByteOrder byte_order)
const void * GetBytes() const
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_REGNUM
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.
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.