1 //===-- NativeThreadWindows.cpp -------------------------------------------===// 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 "NativeThreadWindows.h" 10 #include "NativeProcessWindows.h" 11 12 #include "lldb/Host/HostThread.h" 13 #include "lldb/Host/windows/HostThreadWindows.h" 14 #include "lldb/Host/windows/windows.h" 15 #include "lldb/Target/Process.h" 16 #include "lldb/Utility/Log.h" 17 #include "lldb/Utility/State.h" 18 19 #include "lldb/lldb-forward.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 NativeThreadWindows::NativeThreadWindows(NativeProcessWindows &process, 25 const HostThread &thread) 26 : NativeThreadProtocol(process, thread.GetNativeThread().GetThreadId()), 27 m_stop_info(), m_stop_description(), m_host_thread(thread) { 28 m_reg_context_up = 29 (NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows( 30 process.GetArchitecture(), *this)); 31 } 32 33 Status NativeThreadWindows::DoStop() { 34 if (m_state != eStateStopped) { 35 DWORD previous_suspend_count = 36 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); 37 if (previous_suspend_count == (DWORD)-1) 38 return Status(::GetLastError(), eErrorTypeWin32); 39 40 m_state = eStateStopped; 41 } 42 return Status(); 43 } 44 45 Status NativeThreadWindows::DoResume(lldb::StateType resume_state) { 46 StateType current_state = GetState(); 47 if (resume_state == current_state) 48 return Status(); 49 50 if (resume_state == eStateStepping) { 51 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 52 53 uint32_t flags_index = 54 GetRegisterContext().ConvertRegisterKindToRegisterNumber( 55 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 56 uint64_t flags_value = 57 GetRegisterContext().ReadRegisterAsUnsigned(flags_index, 0); 58 NativeProcessProtocol &process = GetProcess(); 59 const ArchSpec &arch = process.GetArchitecture(); 60 switch (arch.GetMachine()) { 61 case llvm::Triple::x86: 62 case llvm::Triple::x86_64: 63 flags_value |= 0x100; // Set the trap flag on the CPU 64 break; 65 case llvm::Triple::aarch64: 66 case llvm::Triple::arm: 67 case llvm::Triple::thumb: 68 flags_value |= 0x200000; // The SS bit in PState 69 break; 70 default: 71 LLDB_LOG(log, "single stepping unsupported on this architecture"); 72 break; 73 } 74 GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value); 75 } 76 77 if (resume_state == eStateStepping || resume_state == eStateRunning) { 78 DWORD previous_suspend_count = 0; 79 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 80 do { 81 // ResumeThread returns -1 on error, or the thread's *previous* suspend 82 // count on success. This means that the return value is 1 when the thread 83 // was restarted. Note that DWORD is an unsigned int, so we need to 84 // explicitly compare with -1. 85 previous_suspend_count = ::ResumeThread(thread_handle); 86 87 if (previous_suspend_count == (DWORD)-1) 88 return Status(::GetLastError(), eErrorTypeWin32); 89 90 } while (previous_suspend_count > 1); 91 m_state = eStateRunning; 92 } 93 94 return Status(); 95 } 96 97 std::string NativeThreadWindows::GetName() { 98 if (!m_name.empty()) 99 return m_name; 100 101 // Name is not a property of the Windows thread. Create one with the 102 // process's. 103 NativeProcessProtocol &process = GetProcess(); 104 ProcessInstanceInfo process_info; 105 if (Host::GetProcessInfo(process.GetID(), process_info)) { 106 std::string process_name(process_info.GetName()); 107 m_name = process_name; 108 } 109 return m_name; 110 } 111 112 void NativeThreadWindows::SetStopReason(ThreadStopInfo stop_info, 113 std::string description) { 114 m_state = eStateStopped; 115 m_stop_info = stop_info; 116 m_stop_description = description; 117 } 118 119 bool NativeThreadWindows::GetStopReason(ThreadStopInfo &stop_info, 120 std::string &description) { 121 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 122 123 switch (m_state) { 124 case eStateStopped: 125 case eStateCrashed: 126 case eStateExited: 127 case eStateSuspended: 128 case eStateUnloaded: 129 stop_info = m_stop_info; 130 description = m_stop_description; 131 return true; 132 133 case eStateInvalid: 134 case eStateConnected: 135 case eStateAttaching: 136 case eStateLaunching: 137 case eStateRunning: 138 case eStateStepping: 139 case eStateDetached: 140 if (log) { 141 log->Printf("NativeThreadWindows::%s tid %" PRIu64 142 " in state %s cannot answer stop reason", 143 __FUNCTION__, GetID(), StateAsCString(m_state)); 144 } 145 return false; 146 } 147 llvm_unreachable("unhandled StateType!"); 148 } 149 150 Status NativeThreadWindows::SetWatchpoint(lldb::addr_t addr, size_t size, 151 uint32_t watch_flags, bool hardware) { 152 if (!hardware) 153 return Status("not implemented"); 154 if (m_state == eStateLaunching) 155 return Status(); 156 Status error = RemoveWatchpoint(addr); 157 if (error.Fail()) 158 return error; 159 uint32_t wp_index = 160 m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags); 161 if (wp_index == LLDB_INVALID_INDEX32) 162 return Status("Setting hardware watchpoint failed."); 163 m_watchpoint_index_map.insert({addr, wp_index}); 164 return Status(); 165 } 166 167 Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) { 168 auto wp = m_watchpoint_index_map.find(addr); 169 if (wp == m_watchpoint_index_map.end()) 170 return Status(); 171 uint32_t wp_index = wp->second; 172 m_watchpoint_index_map.erase(wp); 173 if (m_reg_context_up->ClearHardwareWatchpoint(wp_index)) 174 return Status(); 175 return Status("Clearing hardware watchpoint failed."); 176 } 177 178 Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr, 179 size_t size) { 180 return Status("unimplemented."); 181 } 182 183 Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) { 184 return Status("unimplemented."); 185 } 186