1 //===-- RegisterContextWindows.cpp ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Core/DataBufferHeap.h" 11 #include "lldb/Core/Error.h" 12 #include "lldb/Host/windows/HostThreadWindows.h" 13 #include "lldb/Host/windows/windows.h" 14 #include "lldb/lldb-private-types.h" 15 16 #include "ProcessWindowsLog.h" 17 #include "RegisterContextWindows.h" 18 #include "TargetThreadWindows.h" 19 20 #include "llvm/ADT/STLExtras.h" 21 22 using namespace lldb; 23 using namespace lldb_private; 24 25 const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; 26 27 //------------------------------------------------------------------ 28 // Constructors and Destructors 29 //------------------------------------------------------------------ 30 RegisterContextWindows::RegisterContextWindows(Thread &thread, 31 uint32_t concrete_frame_idx) 32 : RegisterContext(thread, concrete_frame_idx), m_context(), 33 m_context_stale(true) {} 34 35 RegisterContextWindows::~RegisterContextWindows() {} 36 37 void RegisterContextWindows::InvalidateAllRegisters() { 38 m_context_stale = true; 39 } 40 41 bool RegisterContextWindows::ReadAllRegisterValues( 42 lldb::DataBufferSP &data_sp) { 43 if (!CacheAllRegisterValues()) 44 return false; 45 if (data_sp->GetByteSize() < sizeof(m_context)) { 46 data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); 47 } 48 memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); 49 return true; 50 } 51 52 bool RegisterContextWindows::WriteAllRegisterValues( 53 const lldb::DataBufferSP &data_sp) { 54 assert(data_sp->GetByteSize() >= sizeof(m_context)); 55 memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); 56 57 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 58 if (!::SetThreadContext( 59 wthread.GetHostThread().GetNativeThread().GetSystemHandle(), 60 &m_context)) 61 return false; 62 63 return true; 64 } 65 66 uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber( 67 lldb::RegisterKind kind, uint32_t num) { 68 const uint32_t num_regs = GetRegisterCount(); 69 70 assert(kind < kNumRegisterKinds); 71 for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { 72 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); 73 74 if (reg_info->kinds[kind] == num) 75 return reg_idx; 76 } 77 78 return LLDB_INVALID_REGNUM; 79 } 80 81 //------------------------------------------------------------------ 82 // Subclasses can these functions if desired 83 //------------------------------------------------------------------ 84 uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() { 85 // Support for hardware breakpoints not yet implemented. 86 return 0; 87 } 88 89 uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, 90 size_t size) { 91 return 0; 92 } 93 94 bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) { 95 return false; 96 } 97 98 uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() { 99 // Support for hardware watchpoints not yet implemented. 100 return 0; 101 } 102 103 uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, 104 size_t size, bool read, 105 bool write) { 106 return 0; 107 } 108 109 bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) { 110 return false; 111 } 112 113 bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; } 114 115 bool RegisterContextWindows::CacheAllRegisterValues() { 116 if (!m_context_stale) 117 return true; 118 119 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 120 memset(&m_context, 0, sizeof(m_context)); 121 m_context.ContextFlags = kWinContextFlags; 122 if (!::GetThreadContext( 123 wthread.GetHostThread().GetNativeThread().GetSystemHandle(), 124 &m_context)) { 125 WINERR_IFALL( 126 WINDOWS_LOG_REGISTERS, 127 "GetThreadContext failed with error %lu while caching register values.", 128 ::GetLastError()); 129 return false; 130 } 131 WINLOG_IFALL(WINDOWS_LOG_REGISTERS, 132 "GetThreadContext successfully updated the register values."); 133 m_context_stale = false; 134 return true; 135 } 136