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[] = {
39static const RegisterSet g_reg_sets_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)) {
68 error.SetError(GetLastError(), eErrorTypeWin32);
69 LLDB_LOG(log,
"{0} Wow64GetThreadContext failed with error {1}",
77 PWOW64_CONTEXT context_ptr) {
80 if (!::Wow64SetThreadContext(thread_handle, context_ptr)) {
81 error.SetError(GetLastError(), eErrorTypeWin32);
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(
"register DR4 is obsolete");
262 return Status(
"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(
"register DR4 is obsolete");
301 return Status(
"register DR5 is obsolete");
310 return SetWoW64ThreadContextHelper(thread_handle, &tls_context);
314NativeRegisterContextWindows_WoW64::ReadRegister(
const RegisterInfo *reg_info,
318 error.SetErrorString(
"reg_info NULL");
326 error.SetErrorStringWithFormat(
"register \"%s\" is an internal-only lldb "
327 "register, cannot read directly",
333 return GPRRead(reg, reg_value);
336 return DRRead(reg, reg_value);
338 return Status(
"unimplemented");
341Status NativeRegisterContextWindows_WoW64::WriteRegister(
342 const RegisterInfo *reg_info,
const RegisterValue ®_value) {
346 error.SetErrorString(
"reg_info NULL");
354 error.SetErrorStringWithFormat(
"register \"%s\" is an internal-only lldb "
355 "register, cannot write directly",
361 return GPRWrite(reg, reg_value);
364 return DRWrite(reg, reg_value);
366 return Status(
"unimplemented");
369Status NativeRegisterContextWindows_WoW64::ReadAllRegisterValues(
370 lldb::WritableDataBufferSP &data_sp) {
372 data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
373 ::WOW64_CONTEXT tls_context;
374 Status error = GetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
378 uint8_t *dst = data_sp->GetBytes();
379 ::memcpy(dst, &tls_context, data_size);
383Status NativeRegisterContextWindows_WoW64::WriteAllRegisterValues(
384 const lldb::DataBufferSP &data_sp) {
388 error.SetErrorStringWithFormat(
389 "NativeRegisterContextWindows_WoW64::%s invalid data_sp provided",
394 if (data_sp->GetByteSize() != data_size) {
395 error.SetErrorStringWithFormatv(
396 "data_sp contained mismatched data size, expected {0}, actual {1}",
397 data_size, data_sp->GetByteSize());
401 ::WOW64_CONTEXT tls_context;
402 memcpy(&tls_context, data_sp->GetBytes(), data_size);
403 return SetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
406Status NativeRegisterContextWindows_WoW64::IsWatchpointHit(
uint32_t wp_index,
410 if (wp_index >= NumSupportedHardwareWatchpoints())
411 return Status(
"watchpoint index out of range");
418 is_hit = reg_value.
GetAsUInt32() & (1 << wp_index);
423Status NativeRegisterContextWindows_WoW64::GetWatchpointHitIndex(
427 for (
uint32_t i = 0; i < NumSupportedHardwareWatchpoints(); i++) {
442Status NativeRegisterContextWindows_WoW64::IsWatchpointVacant(
uint32_t wp_index,
446 if (wp_index >= NumSupportedHardwareWatchpoints())
447 return Status(
"Watchpoint index out of range");
454 is_vacant = !(reg_value.
GetAsUInt32() & (1 << (2 * wp_index)));
459bool NativeRegisterContextWindows_WoW64::ClearHardwareWatchpoint(
461 if (wp_index >= NumSupportedHardwareWatchpoints())
482 error = DRRead(lldb_dr7_i386, reg_value);
486 bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
488 return DRWrite(lldb_dr7_i386,
RegisterValue(control_bits)).Success();
491Status NativeRegisterContextWindows_WoW64::ClearAllHardwareWatchpoints() {
507 error = DRRead(lldb_dr7_i386, reg_value);
515uint32_t NativeRegisterContextWindows_WoW64::SetHardwareWatchpoint(
526 if (watch_flags == 0x2)
529 if (watch_flags != 0x1 && watch_flags != 0x3)
532 for (
uint32_t wp_index = 0; wp_index < NumSupportedHardwareWatchpoints();
535 if (IsWatchpointVacant(wp_index, is_vacant).Fail())
539 if (!ClearHardwareWatchpoint(wp_index))
542 if (ApplyHardwareBreakpoint(wp_index, addr, size, watch_flags).Fail())
551Status NativeRegisterContextWindows_WoW64::ApplyHardwareBreakpoint(
554 auto error = DRRead(lldb_dr7_i386, reg_value);
559 uint32_t enable_bit = 1 << (2 * wp_index);
563 uint32_t rw_bits = flags << (16 + 4 * wp_index);
568 uint32_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
570 uint32_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
573 control_bits |= enable_bit | rw_bits | size_bits;
587NativeRegisterContextWindows_WoW64::GetWatchpointAddress(
uint32_t wp_index) {
588 if (wp_index >= NumSupportedHardwareWatchpoints())
592 if (DRRead(lldb_dr0_i386 + wp_index, reg_value).Fail())
598uint32_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.
@ eRegisterKindLLDB
lldb's internal register numbers