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)) {
64 error.SetError(GetLastError(), eErrorTypeWin32);
65 LLDB_LOG(log,
"{0} GetThreadContext failed with error {1}", __FUNCTION__,
73 PCONTEXT context_ptr) {
77 if (!::SetThreadContext(thread_handle, context_ptr)) {
78 error.SetError(GetLastError(), eErrorTypeWin32);
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(
"register DR4 is obsolete");
270 return Status(
"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(
"register DR4 is obsolete");
309 return Status(
"register DR5 is obsolete");
318 return SetThreadContextHelper(thread_handle, &tls_context);
322NativeRegisterContextWindows_i386::ReadRegister(
const RegisterInfo *reg_info,
327 error.SetErrorString(
"reg_info NULL");
335 error.SetErrorStringWithFormat(
"register \"%s\" is an internal-only lldb "
336 "register, cannot read directly",
342 return GPRRead(reg, reg_value);
345 return DRRead(reg, reg_value);
347 return Status(
"unimplemented");
350Status NativeRegisterContextWindows_i386::WriteRegister(
351 const RegisterInfo *reg_info,
const RegisterValue ®_value) {
355 error.SetErrorString(
"reg_info NULL");
363 error.SetErrorStringWithFormat(
"register \"%s\" is an internal-only lldb "
364 "register, cannot write directly",
370 return GPRWrite(reg, reg_value);
373 return DRWrite(reg, reg_value);
375 return Status(
"unimplemented");
378Status NativeRegisterContextWindows_i386::ReadAllRegisterValues(
379 lldb::WritableDataBufferSP &data_sp) {
381 data_sp = std::make_shared<DataBufferHeap>(data_size, 0);
382 ::CONTEXT tls_context;
384 GetThreadContextHelper(GetThreadHandle(), &tls_context, CONTEXT_ALL);
388 uint8_t *dst = data_sp->GetBytes();
389 ::memcpy(dst, &tls_context, data_size);
393Status NativeRegisterContextWindows_i386::WriteAllRegisterValues(
394 const lldb::DataBufferSP &data_sp) {
398 error.SetErrorStringWithFormat(
399 "NativeRegisterContextWindows_i386::%s invalid data_sp provided",
404 if (data_sp->GetByteSize() != data_size) {
405 error.SetErrorStringWithFormatv(
406 "data_sp contained mismatched data size, expected {0}, actual {1}",
407 data_size, data_sp->GetByteSize());
411 ::CONTEXT tls_context;
412 memcpy(&tls_context, data_sp->GetBytes(), data_size);
413 return SetThreadContextHelper(GetThreadHandle(), &tls_context);
416Status NativeRegisterContextWindows_i386::IsWatchpointHit(
uint32_t wp_index,
420 if (wp_index >= NumSupportedHardwareWatchpoints())
421 return Status(
"watchpoint index out of range");
428 is_hit = reg_value.
GetAsUInt32() & (1 << wp_index);
433Status NativeRegisterContextWindows_i386::GetWatchpointHitIndex(
437 for (
uint32_t i = 0; i < NumSupportedHardwareWatchpoints(); i++) {
452Status NativeRegisterContextWindows_i386::IsWatchpointVacant(
uint32_t wp_index,
456 if (wp_index >= NumSupportedHardwareWatchpoints())
457 return Status(
"Watchpoint index out of range");
464 is_vacant = !(reg_value.
GetAsUInt32() & (1 << (2 * wp_index)));
469bool NativeRegisterContextWindows_i386::ClearHardwareWatchpoint(
471 if (wp_index >= NumSupportedHardwareWatchpoints())
492 error = DRRead(lldb_dr7_i386, reg_value);
496 bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
498 return DRWrite(lldb_dr7_i386,
RegisterValue(control_bits)).Success();
501Status NativeRegisterContextWindows_i386::ClearAllHardwareWatchpoints() {
517 error = DRRead(lldb_dr7_i386, reg_value);
525uint32_t NativeRegisterContextWindows_i386::SetHardwareWatchpoint(
536 if (watch_flags == 0x2)
539 if (watch_flags != 0x1 && watch_flags != 0x3)
542 for (
uint32_t wp_index = 0; wp_index < NumSupportedHardwareWatchpoints();
545 if (IsWatchpointVacant(wp_index, is_vacant).Fail())
549 if (!ClearHardwareWatchpoint(wp_index))
552 if (ApplyHardwareBreakpoint(wp_index, addr, size, watch_flags).Fail())
561Status NativeRegisterContextWindows_i386::ApplyHardwareBreakpoint(
564 auto error = DRRead(lldb_dr7_i386, reg_value);
569 uint32_t enable_bit = 1 << (2 * wp_index);
573 uint32_t rw_bits = flags << (16 + 4 * wp_index);
578 uint32_t size_bits = (size == 8 ? 0x2 : size - 1) << (18 + 4 * wp_index);
580 uint32_t bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
583 control_bits |= enable_bit | rw_bits | size_bits;
597NativeRegisterContextWindows_i386::GetWatchpointAddress(
uint32_t wp_index) {
598 if (wp_index >= NumSupportedHardwareWatchpoints())
602 if (DRRead(lldb_dr0_i386 + wp_index, reg_value).Fail())
608uint32_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[k_num_register_sets]
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.
@ eRegisterKindLLDB
lldb's internal register numbers