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/lldb-private-types.h" 11 #include "lldb/Core/DataBufferHeap.h" 12 #include "lldb/Core/Error.h" 13 #include "lldb/Host/windows/HostThreadWindows.h" 14 #include "lldb/Host/windows/windows.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, uint32_t concrete_frame_idx) 31 : RegisterContext(thread, concrete_frame_idx) 32 , m_context() 33 , m_context_stale(true) 34 { 35 } 36 37 RegisterContextWindows::~RegisterContextWindows() 38 { 39 } 40 41 void 42 RegisterContextWindows::InvalidateAllRegisters() 43 { 44 m_context_stale = true; 45 } 46 47 bool 48 RegisterContextWindows::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) 49 { 50 if (!CacheAllRegisterValues()) 51 return false; 52 if (data_sp->GetByteSize() < sizeof(m_context)) 53 { 54 data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); 55 } 56 memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); 57 return true; 58 } 59 60 bool 61 RegisterContextWindows::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) 62 { 63 assert(data_sp->GetByteSize() >= sizeof(m_context)); 64 memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context)); 65 66 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 67 if (!::SetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) 68 return false; 69 70 return true; 71 } 72 73 uint32_t 74 RegisterContextWindows::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) 75 { 76 const uint32_t num_regs = GetRegisterCount(); 77 78 assert(kind < kNumRegisterKinds); 79 for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) 80 { 81 const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx); 82 83 if (reg_info->kinds[kind] == num) 84 return reg_idx; 85 } 86 87 return LLDB_INVALID_REGNUM; 88 } 89 90 //------------------------------------------------------------------ 91 // Subclasses can these functions if desired 92 //------------------------------------------------------------------ 93 uint32_t 94 RegisterContextWindows::NumSupportedHardwareBreakpoints() 95 { 96 // Support for hardware breakpoints not yet implemented. 97 return 0; 98 } 99 100 uint32_t 101 RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) 102 { 103 return 0; 104 } 105 106 bool 107 RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) 108 { 109 return false; 110 } 111 112 uint32_t 113 RegisterContextWindows::NumSupportedHardwareWatchpoints() 114 { 115 // Support for hardware watchpoints not yet implemented. 116 return 0; 117 } 118 119 uint32_t 120 RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write) 121 { 122 return 0; 123 } 124 125 bool 126 RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) 127 { 128 return false; 129 } 130 131 bool 132 RegisterContextWindows::HardwareSingleStep(bool enable) 133 { 134 return false; 135 } 136 137 bool 138 RegisterContextWindows::CacheAllRegisterValues() 139 { 140 if (!m_context_stale) 141 return true; 142 143 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 144 memset(&m_context, 0, sizeof(m_context)); 145 m_context.ContextFlags = kWinContextFlags; 146 if (!::GetThreadContext(wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context)) 147 { 148 WINERR_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext failed with error %u while caching register values.", 149 ::GetLastError()); 150 return false; 151 } 152 WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "GetThreadContext successfully updated the register values.", ::GetLastError()); 153 m_context_stale = false; 154 return true; 155 } 156