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/Host/windows/HostThreadWindows.h" 11 #include "lldb/Host/windows/windows.h" 12 #include "lldb/Utility/DataBufferHeap.h" 13 #include "lldb/Utility/Status.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 44 if (!CacheAllRegisterValues()) 45 return false; 46 47 data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); 48 memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); 49 50 return true; 51 } 52 53 bool RegisterContextWindows::WriteAllRegisterValues( 54 const lldb::DataBufferSP &data_sp) { 55 assert(data_sp->GetByteSize() >= sizeof(m_context)); 56 memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); 57 58 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 59 if (!::SetThreadContext( 60 wthread.GetHostThread().GetNativeThread().GetSystemHandle(), 61 &m_context)) 62 return false; 63 64 return true; 65 } 66 67 uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber( 68 lldb::RegisterKind kind, uint32_t num) { 69 const uint32_t num_regs = GetRegisterCount(); 70 71 assert(kind < kNumRegisterKinds); 72 for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { 73 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); 74 75 if (reg_info->kinds[kind] == num) 76 return reg_idx; 77 } 78 79 return LLDB_INVALID_REGNUM; 80 } 81 82 //------------------------------------------------------------------ 83 // Subclasses can these functions if desired 84 //------------------------------------------------------------------ 85 uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() { 86 // Support for hardware breakpoints not yet implemented. 87 return 0; 88 } 89 90 uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, 91 size_t size) { 92 return 0; 93 } 94 95 bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) { 96 return false; 97 } 98 99 uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() { 100 // Support for hardware watchpoints not yet implemented. 101 return 0; 102 } 103 104 uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, 105 size_t size, bool read, 106 bool write) { 107 return 0; 108 } 109 110 bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) { 111 return false; 112 } 113 114 bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; } 115 116 bool RegisterContextWindows::CacheAllRegisterValues() { 117 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); 118 if (!m_context_stale) 119 return true; 120 121 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 122 memset(&m_context, 0, sizeof(m_context)); 123 m_context.ContextFlags = kWinContextFlags; 124 if (!::GetThreadContext( 125 wthread.GetHostThread().GetNativeThread().GetSystemHandle(), 126 &m_context)) { 127 LLDB_LOG( 128 log, 129 "GetThreadContext failed with error {0} while caching register values.", 130 ::GetLastError()); 131 return false; 132 } 133 LLDB_LOG(log, "successfully updated the register values."); 134 m_context_stale = false; 135 return true; 136 } 137