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_CONTROL | CONTEXT_INTEGER; 25 26 //------------------------------------------------------------------ 27 // Constructors and Destructors 28 //------------------------------------------------------------------ 29 RegisterContextWindows::RegisterContextWindows(Thread &thread, 30 uint32_t concrete_frame_idx) 31 : RegisterContext(thread, concrete_frame_idx), m_context(), 32 m_context_stale(true) {} 33 34 RegisterContextWindows::~RegisterContextWindows() {} 35 36 void RegisterContextWindows::InvalidateAllRegisters() { 37 m_context_stale = true; 38 } 39 40 bool RegisterContextWindows::ReadAllRegisterValues( 41 lldb::DataBufferSP &data_sp) { 42 43 if (!CacheAllRegisterValues()) 44 return false; 45 46 data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0)); 47 memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context)); 48 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 Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS); 117 if (!m_context_stale) 118 return true; 119 120 TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread); 121 memset(&m_context, 0, sizeof(m_context)); 122 m_context.ContextFlags = kWinContextFlags; 123 if (!::GetThreadContext( 124 wthread.GetHostThread().GetNativeThread().GetSystemHandle(), 125 &m_context)) { 126 LLDB_LOG( 127 log, 128 "GetThreadContext failed with error {0} while caching register values.", 129 ::GetLastError()); 130 return false; 131 } 132 LLDB_LOG(log, "successfully updated the register values."); 133 m_context_stale = false; 134 return true; 135 } 136