blob: b3f507128f824982dd8a4279af16bed0d43ec427 [file] [log] [blame]
//===-- RegisterContextWindows.cpp ------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-types.h"
#include "ProcessWindowsLog.h"
#include "RegisterContextWindows.h"
#include "TargetThreadWindows.h"
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindows::RegisterContextWindows(Thread &thread,
uint32_t concrete_frame_idx)
: RegisterContext(thread, concrete_frame_idx), m_context(),
m_context_stale(true) {}
RegisterContextWindows::~RegisterContextWindows() {}
void RegisterContextWindows::InvalidateAllRegisters() {
m_context_stale = true;
}
bool RegisterContextWindows::ReadAllRegisterValues(
lldb::DataBufferSP &data_sp) {
if (!CacheAllRegisterValues())
return false;
if (data_sp->GetByteSize() < sizeof(m_context)) {
data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
}
memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));
return true;
}
bool RegisterContextWindows::WriteAllRegisterValues(
const lldb::DataBufferSP &data_sp) {
assert(data_sp->GetByteSize() >= sizeof(m_context));
memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context));
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
if (!::SetThreadContext(
wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
&m_context))
return false;
return true;
}
uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
assert(kind < kNumRegisterKinds);
for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
if (reg_info->kinds[kind] == num)
return reg_idx;
}
return LLDB_INVALID_REGNUM;
}
//------------------------------------------------------------------
// Subclasses can these functions if desired
//------------------------------------------------------------------
uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() {
// Support for hardware breakpoints not yet implemented.
return 0;
}
uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr,
size_t size) {
return 0;
}
bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) {
return false;
}
uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() {
// Support for hardware watchpoints not yet implemented.
return 0;
}
uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr,
size_t size, bool read,
bool write) {
return 0;
}
bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) {
return false;
}
bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; }
bool RegisterContextWindows::CacheAllRegisterValues() {
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
if (!m_context_stale)
return true;
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
memset(&m_context, 0, sizeof(m_context));
m_context.ContextFlags = kWinContextFlags;
if (!::GetThreadContext(
wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
&m_context)) {
LLDB_LOG(
log,
"GetThreadContext failed with error {0} while caching register values.",
::GetLastError());
return false;
}
LLDB_LOG(log, "successfully updated the register values.");
m_context_stale = false;
return true;
}