//===-- 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(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(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; }