9 #if defined(__x86_64__) || defined(_M_X64)
23 #include "llvm/ADT/STLExtras.h"
28 #define REG_CONTEXT_SIZE sizeof(::WOW64_CONTEXT)
31 static const uint32_t g_gpr_regnums_WoW64[] = {
39 static const RegisterSet g_reg_sets_WoW64[] = {
40 {
"General Purpose Registers",
"gpr",
41 llvm::array_lengthof(g_gpr_regnums_WoW64) - 1, g_gpr_regnums_WoW64},
45 static const DWORD kWoW64ContextFlags =
46 WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS;
51 CreateRegisterInfoInterface(
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}",
89 NativeRegisterContextWindows_WoW64::NativeRegisterContextWindows_WoW64(
92 CreateRegisterInfoInterface(target_arch)) {}
94 bool NativeRegisterContextWindows_WoW64::IsGPR(
uint32_t reg_index)
const {
98 bool NativeRegisterContextWindows_WoW64::IsDR(
uint32_t reg_index)
const {
102 uint32_t NativeRegisterContextWindows_WoW64::GetRegisterSetCount()
const {
107 NativeRegisterContextWindows_WoW64::GetRegisterSet(
uint32_t set_index)
const {
110 return &g_reg_sets_WoW64[set_index];
113 Status NativeRegisterContextWindows_WoW64::GPRRead(
const uint32_t reg,
115 ::WOW64_CONTEXT tls_context;
116 Status error = GetWoW64ThreadContextHelper(GetThreadHandle(), &tls_context);
175 NativeRegisterContextWindows_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);
237 Status 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");
275 NativeRegisterContextWindows_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);
314 NativeRegisterContextWindows_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");
341 Status 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");
369 Status 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);
383 Status 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);
406 Status 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);
423 Status NativeRegisterContextWindows_WoW64::GetWatchpointHitIndex(
427 for (
uint32_t i = 0; i < NumSupportedHardwareWatchpoints(); i++) {
442 Status 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)));
459 bool NativeRegisterContextWindows_WoW64::ClearHardwareWatchpoint(
461 if (wp_index >= NumSupportedHardwareWatchpoints())
486 bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
491 Status NativeRegisterContextWindows_WoW64::ClearAllHardwareWatchpoints() {
515 uint32_t NativeRegisterContextWindows_WoW64::SetHardwareWatchpoint(
526 if (watch_flags == 0
x2)
529 if (watch_flags != 0
x1 && watch_flags != 0
x3)
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())
551 Status NativeRegisterContextWindows_WoW64::ApplyHardwareBreakpoint(
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;
587 NativeRegisterContextWindows_WoW64::GetWatchpointAddress(
uint32_t wp_index) {
588 if (wp_index >= NumSupportedHardwareWatchpoints())
598 uint32_t NativeRegisterContextWindows_WoW64::NumSupportedHardwareWatchpoints() {
602 #endif // defined(__x86_64__) || defined(_M_X64)