9#if defined(__i386__) || defined(_M_IX86)
23#include "llvm/ADT/STLExtras.h"
28#define REG_CONTEXT_SIZE sizeof(::CONTEXT)
49CreateRegisterInfoInterface(
const ArchSpec &target_arch) {
50 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 4) &&
51 "Register setting path assumes this is a 32-bit host");
57 const DWORD control_flag) {
61 memset(context_ptr, 0,
sizeof(::CONTEXT));
62 context_ptr->ContextFlags = control_flag;
63 if (!::GetThreadContext(thread_handle, context_ptr)) {
65 LLDB_LOG(log,
"{0} GetThreadContext failed with error {1}", __FUNCTION__,
73 PCONTEXT context_ptr) {
77 if (!::SetThreadContext(thread_handle, context_ptr)) {
79 LLDB_LOG(log,
"{0} SetThreadContext failed with error {1}", __FUNCTION__,
86std::unique_ptr<NativeRegisterContextWindows>
87NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
89 return std::make_unique<NativeRegisterContextWindows_i386>(target_arch,
93NativeRegisterContextWindows_i386::NativeRegisterContextWindows_i386(
96 CreateRegisterInfoInterface(target_arch)) {}
98bool NativeRegisterContextWindows_i386::IsGPR(uint32_t reg_index)
const {
99 return (reg_index < k_first_alias_i386);
102bool NativeRegisterContextWindows_i386::IsDR(uint32_t reg_index)
const {
103 return (reg_index >= lldb_dr0_i386 && reg_index <= lldb_dr7_i386);
106uint32_t NativeRegisterContextWindows_i386::GetRegisterSetCount()
const {
111NativeRegisterContextWindows_i386::GetRegisterSet(uint32_t set_index)
const {
117Status NativeRegisterContextWindows_i386::GPRRead(
const uint32_t reg,
119 ::CONTEXT tls_context;
120 DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
122 GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
181NativeRegisterContextWindows_i386::GPRWrite(
const uint32_t reg,
183 ::CONTEXT tls_context;
184 DWORD context_flag = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS;
185 auto thread_handle = GetThreadHandle();
187 GetThreadContextHelper(thread_handle, &tls_context, context_flag);
242 return SetThreadContextHelper(thread_handle, &tls_context);
245Status NativeRegisterContextWindows_i386::DRRead(
const uint32_t reg,
247 ::CONTEXT tls_context;
248 DWORD context_flag = CONTEXT_DEBUG_REGISTERS;
250 GetThreadContextHelper(GetThreadHandle(), &tls_context, context_flag);
268 return Status::FromErrorString(
"register DR4 is obsolete");
270 return Status::FromErrorString(
"register DR5 is obsolete");
283NativeRegisterContextWindows_i386::DRWrite(
const uint32_t reg,
285 ::CONTEXT tls_context;
286 DWORD context_flag = CONTEXT_DEBUG_REGISTERS;
287 auto thread_handle = GetThreadHandle();
289 GetThreadContextHelper(thread_handle, &tls_context, context_flag);
307 return Status::FromErrorString(
"register DR4 is obsolete");
309 return Status::FromErrorString(
"register DR5 is obsolete");
318 return SetThreadContextHelper(thread_handle, &tls_context);
322NativeRegisterContextWindows_i386::ReadRegister(
const RegisterInfo *reg_info,
327 error = Status::FromErrorString(
"reg_info NULL");
335 error = Status::FromErrorStringWithFormat(
336 "register \"%s\" is an internal-only lldb "
337 "register, cannot read directly",
343 return GPRRead(reg, reg_value);
346 return DRRead(reg, reg_value);
348 return Status::FromErrorString(
"unimplemented");
351Status NativeRegisterContextWindows_i386::WriteRegister(
356 error = Status::FromErrorString(
"reg_info NULL");
364 error = Status::FromErrorStringWithFormat(
365 "register \"%s\" is an internal-only lldb "
366 "register, cannot write directly",
372 return GPRWrite(reg, reg_value);
375 return DRWrite(reg, reg_value);
377 return Status::FromErrorString(
"unimplemented");
380Status NativeRegisterContextWindows_i386::ReadAllRegisterValues(
383 data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
384 ::CONTEXT tls_context;
386 GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);
390 uint8_t *dst = data_sp->GetBytes();
391 ::memcpy(dst, &tls_context, data_size);
395Status NativeRegisterContextWindows_i386::WriteAllRegisterValues(
400 error = Status::FromErrorStringWithFormat(
401 "NativeRegisterContextWindows_i386::%s invalid data_sp provided",
406 if (data_sp->GetByteSize() != data_size) {
407 error = Status::FromErrorStringWithFormatv(
408 "data_sp contained mismatched data size, expected {0}, actual {1}",
409 data_size, data_sp->GetByteSize());
413 ::CONTEXT tls_context;
414 memcpy(&tls_context, data_sp->GetBytes(), data_size);
415 return SetThreadContextHelper(GetThreadHandle(), &tls_context);
418Status NativeRegisterContextWindows_i386::IsWatchpointHit(uint32_t wp_index,
422 if (wp_index >= NumSupportedHardwareWatchpoints())
423 return Status::FromErrorString(
"watchpoint index out of range");
430 is_hit = reg_value.
GetAsUInt32() & (1 << wp_index);
435Status NativeRegisterContextWindows_i386::GetWatchpointHitIndex(
439 for (uint32_t i = 0; i < NumSupportedHardwareWatchpoints(); i++) {
454Status NativeRegisterContextWindows_i386::IsWatchpointVacant(uint32_t wp_index,
458 if (wp_index >= NumSupportedHardwareWatchpoints())
459 return Status::FromErrorString(
"Watchpoint index out of range");
466 is_vacant = !(reg_value.
GetAsUInt32() & (1 << (2 * wp_index)));
471bool NativeRegisterContextWindows_i386::ClearHardwareWatchpoint(
473 if (wp_index >= NumSupportedHardwareWatchpoints())
484 uint32_t bit_mask = 1 << wp_index;
485 uint32_t status_bits = reg_value.
GetAsUInt32() & ~bit_mask;
494 error = DRRead(lldb_dr7_i386, reg_value);
498 bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
499 uint32_t control_bits = reg_value.
GetAsUInt32() & ~bit_mask;
500 return DRWrite(lldb_dr7_i386,
RegisterValue(control_bits)).Success();
503Status NativeRegisterContextWindows_i386::ClearAllHardwareWatchpoints() {
512 uint32_t status_bits = reg_value.
GetAsUInt32() & ~0xF;
519 error = DRRead(lldb_dr7_i386, reg_value);
523 uint32_t control_bits = reg_value.
GetAsUInt32() & ~0xFFFF00FF;
527uint32_t NativeRegisterContextWindows_i386::SetHardwareWatchpoint(
538 if (watch_flags == 0x2)
541 if (watch_flags != 0x1 && watch_flags != 0x3)
544 for (uint32_t wp_index = 0; wp_index < NumSupportedHardwareWatchpoints();
547 if (IsWatchpointVacant(wp_index, is_vacant).Fail())
551 if (!ClearHardwareWatchpoint(wp_index))
554 if (ApplyHardwareBreakpoint(wp_index, addr, size, watch_flags).Fail())
563Status NativeRegisterContextWindows_i386::ApplyHardwareBreakpoint(
564 uint32_t wp_index,
lldb::addr_t addr,
size_t size, uint32_t flags) {
566 auto error = DRRead(lldb_dr7_i386, reg_value);
571 uint32_t enable_bit = 1 << (2 * wp_index);
575 uint32_t rw_bits = flags << (16 + 4 * wp_index);
580 uint32_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
582 uint32_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
584 uint32_t control_bits = reg_value.
GetAsUInt32() & ~bit_mask;
585 control_bits |= enable_bit | rw_bits | size_bits;
599NativeRegisterContextWindows_i386::GetWatchpointAddress(uint32_t wp_index) {
600 if (wp_index >= NumSupportedHardwareWatchpoints())
604 if (DRRead(lldb_dr0_i386 + wp_index, reg_value).Fail())
610uint32_t NativeRegisterContextWindows_i386::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 RegisterSet g_reg_sets_i386[]
const uint32_t g_gpr_regnums_i386[]
An architecture specification class.
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.