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