9#if defined(__x86_64__) || defined(_M_X64)
23#include "llvm/ADT/STLExtras.h"
28#define REG_CONTEXT_SIZE sizeof(::WOW64_CONTEXT)
31static const uint32_t g_gpr_regnums_WoW64[] = {
40 {
"General Purpose Registers",
"gpr", std::size(g_gpr_regnums_WoW64) - 1,
45static const DWORD kWoW64ContextFlags =
46 WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS;
51CreateRegisterInfoInterface(
const ArchSpec &target_arch) {
54 HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
55 "Register setting path assumes this is a 64-bit host");
61 PWOW64_CONTEXT context_ptr,
62 const DWORD control_flag = kWoW64ContextFlags) {
65 memset(context_ptr, 0,
sizeof(::WOW64_CONTEXT));
66 context_ptr->ContextFlags = control_flag;
67 if (!::Wow64GetThreadContext(thread_handle, context_ptr)) {
69 LLDB_LOG(log,
"{0} Wow64GetThreadContext failed with error {1}",
77 PWOW64_CONTEXT context_ptr) {
80 if (!::Wow64SetThreadContext(thread_handle, context_ptr)) {
82 LLDB_LOG(log,
"{0} Wow64SetThreadContext failed with error {1}",
89NativeRegisterContextWindows_WoW64::NativeRegisterContextWindows_WoW64(
92 CreateRegisterInfoInterface(target_arch)) {}
94bool NativeRegisterContextWindows_WoW64::IsGPR(uint32_t reg_index)
const {
95 return (reg_index >= k_first_gpr_i386 && reg_index < k_first_alias_i386);
98bool NativeRegisterContextWindows_WoW64::IsDR(uint32_t reg_index)
const {
99 return (reg_index >= lldb_dr0_i386 && reg_index <= lldb_dr7_i386);
102uint32_t NativeRegisterContextWindows_WoW64::GetRegisterSetCount()
const {
107NativeRegisterContextWindows_WoW64::GetRegisterSet(uint32_t set_index)
const {
110 return &g_reg_sets_WoW64[set_index];
113Status NativeRegisterContextWindows_WoW64::GPRRead(
const uint32_t reg,
115 ::WOW64_CONTEXT tls_context;
116 Status error = GetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
175NativeRegisterContextWindows_WoW64::GPRWrite(
const uint32_t reg,
177 ::WOW64_CONTEXT tls_context;
178 auto thread_handle = GetThreadHandle();
179 Status error = GetWoW64ThreadContextHelper(thread_handle, &tls_context);
234 return SetWoW64ThreadContextHelper(thread_handle, &tls_context);
237Status NativeRegisterContextWindows_WoW64::DRRead(
const uint32_t reg,
239 ::WOW64_CONTEXT tls_context;
240 DWORD context_flag = CONTEXT_DEBUG_REGISTERS;
241 Status error = GetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context,
260 return Status::FromErrorString(
"register DR4 is obsolete");
262 return Status::FromErrorString(
"register DR5 is obsolete");
275NativeRegisterContextWindows_WoW64::DRWrite(
const uint32_t reg,
277 ::WOW64_CONTEXT tls_context;
278 DWORD context_flag = CONTEXT_DEBUG_REGISTERS;
279 auto thread_handle = GetThreadHandle();
281 GetWoW64ThreadContextHelper(thread_handle, &tls_context, context_flag);
299 return Status::FromErrorString(
"register DR4 is obsolete");
301 return Status::FromErrorString(
"register DR5 is obsolete");
310 return SetWoW64ThreadContextHelper(thread_handle, &tls_context);
314NativeRegisterContextWindows_WoW64::ReadRegister(
const RegisterInfo *reg_info,
318 error = Status::FromErrorString(
"reg_info NULL");
326 error = Status::FromErrorStringWithFormat(
327 "register \"%s\" is an internal-only lldb "
328 "register, cannot read directly",
334 return GPRRead(reg, reg_value);
337 return DRRead(reg, reg_value);
339 return Status::FromErrorString(
"unimplemented");
342Status NativeRegisterContextWindows_WoW64::WriteRegister(
347 error = Status::FromErrorString(
"reg_info NULL");
355 error = Status::FromErrorStringWithFormat(
356 "register \"%s\" is an internal-only lldb "
357 "register, cannot write directly",
363 return GPRWrite(reg, reg_value);
366 return DRWrite(reg, reg_value);
368 return Status::FromErrorString(
"unimplemented");
371Status NativeRegisterContextWindows_WoW64::ReadAllRegisterValues(
374 data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
375 ::WOW64_CONTEXT tls_context;
376 Status error = GetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
380 uint8_t *dst = data_sp->GetBytes();
381 ::memcpy(dst, &tls_context, data_size);
385Status NativeRegisterContextWindows_WoW64::WriteAllRegisterValues(
390 error = Status::FromErrorStringWithFormat(
391 "NativeRegisterContextWindows_WoW64::%s invalid data_sp provided",
396 if (data_sp->GetByteSize() != data_size) {
397 error = Status::FromErrorStringWithFormatv(
398 "data_sp contained mismatched data size, expected {0}, actual {1}",
399 data_size, data_sp->GetByteSize());
403 ::WOW64_CONTEXT tls_context;
404 memcpy(&tls_context, data_sp->GetBytes(), data_size);
405 return SetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
408Status NativeRegisterContextWindows_WoW64::IsWatchpointHit(uint32_t wp_index,
412 if (wp_index >= NumSupportedHardwareWatchpoints())
413 return Status::FromErrorString(
"watchpoint index out of range");
420 is_hit = reg_value.
GetAsUInt32() & (1 << wp_index);
425Status NativeRegisterContextWindows_WoW64::GetWatchpointHitIndex(
429 for (uint32_t i = 0; i < NumSupportedHardwareWatchpoints(); i++) {
444Status NativeRegisterContextWindows_WoW64::IsWatchpointVacant(uint32_t wp_index,
448 if (wp_index >= NumSupportedHardwareWatchpoints())
449 return Status::FromErrorString(
"Watchpoint index out of range");
456 is_vacant = !(reg_value.
GetAsUInt32() & (1 << (2 * wp_index)));
461bool NativeRegisterContextWindows_WoW64::ClearHardwareWatchpoint(
463 if (wp_index >= NumSupportedHardwareWatchpoints())
474 uint32_t bit_mask = 1 << wp_index;
475 uint32_t status_bits = reg_value.
GetAsUInt32() & ~bit_mask;
484 error = DRRead(lldb_dr7_i386, reg_value);
488 bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
489 uint32_t control_bits = reg_value.
GetAsUInt32() & ~bit_mask;
490 return DRWrite(lldb_dr7_i386,
RegisterValue(control_bits)).Success();
493Status NativeRegisterContextWindows_WoW64::ClearAllHardwareWatchpoints() {
502 uint32_t status_bits = reg_value.
GetAsUInt32() & ~0xF;
509 error = DRRead(lldb_dr7_i386, reg_value);
513 uint32_t control_bits = reg_value.
GetAsUInt32() & ~0xFFFF00FF;
517uint32_t NativeRegisterContextWindows_WoW64::SetHardwareWatchpoint(
528 if (watch_flags == 0x2)
531 if (watch_flags != 0x1 && watch_flags != 0x3)
534 for (uint32_t wp_index = 0; wp_index < NumSupportedHardwareWatchpoints();
537 if (IsWatchpointVacant(wp_index, is_vacant).Fail())
541 if (!ClearHardwareWatchpoint(wp_index))
544 if (ApplyHardwareBreakpoint(wp_index, addr, size, watch_flags).Fail())
553Status NativeRegisterContextWindows_WoW64::ApplyHardwareBreakpoint(
554 uint32_t wp_index,
lldb::addr_t addr,
size_t size, uint32_t flags) {
556 auto error = DRRead(lldb_dr7_i386, reg_value);
561 uint32_t enable_bit = 1 << (2 * wp_index);
565 uint32_t rw_bits = flags << (16 + 4 * wp_index);
570 uint32_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
572 uint32_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
574 uint32_t control_bits = reg_value.
GetAsUInt32() & ~bit_mask;
575 control_bits |= enable_bit | rw_bits | size_bits;
589NativeRegisterContextWindows_WoW64::GetWatchpointAddress(uint32_t wp_index) {
590 if (wp_index >= NumSupportedHardwareWatchpoints())
594 if (DRRead(lldb_dr0_i386 + wp_index, reg_value).Fail())
600uint32_t NativeRegisterContextWindows_WoW64::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
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.
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
#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.