1*5146a9eaSAaron Smith //===-- NativeThreadWindows.cpp ---------------------------------*- C++ -*-===// 2*5146a9eaSAaron Smith // 3*5146a9eaSAaron Smith // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5146a9eaSAaron Smith // See https://llvm.org/LICENSE.txt for license information. 5*5146a9eaSAaron Smith // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5146a9eaSAaron Smith // 7*5146a9eaSAaron Smith //===----------------------------------------------------------------------===// 8*5146a9eaSAaron Smith 9*5146a9eaSAaron Smith #include "NativeThreadWindows.h" 10*5146a9eaSAaron Smith #include "NativeProcessWindows.h" 11*5146a9eaSAaron Smith 12*5146a9eaSAaron Smith #include "lldb/Host/HostThread.h" 13*5146a9eaSAaron Smith #include "lldb/Host/Windows/HostThreadWindows.h" 14*5146a9eaSAaron Smith #include "lldb/Host/windows/windows.h" 15*5146a9eaSAaron Smith #include "lldb/Target/Process.h" 16*5146a9eaSAaron Smith #include "lldb/Utility/Log.h" 17*5146a9eaSAaron Smith #include "lldb/Utility/State.h" 18*5146a9eaSAaron Smith 19*5146a9eaSAaron Smith #include "lldb/lldb-forward.h" 20*5146a9eaSAaron Smith 21*5146a9eaSAaron Smith using namespace lldb; 22*5146a9eaSAaron Smith using namespace lldb_private; 23*5146a9eaSAaron Smith 24*5146a9eaSAaron Smith NativeThreadWindows::NativeThreadWindows(NativeProcessWindows &process, 25*5146a9eaSAaron Smith const HostThread &thread) 26*5146a9eaSAaron Smith : NativeThreadProtocol(process, thread.GetNativeThread().GetThreadId()), 27*5146a9eaSAaron Smith m_stop_info(), m_stop_description(), m_host_thread(thread) { 28*5146a9eaSAaron Smith m_reg_context_up = 29*5146a9eaSAaron Smith (NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows( 30*5146a9eaSAaron Smith process.GetArchitecture(), *this)); 31*5146a9eaSAaron Smith } 32*5146a9eaSAaron Smith 33*5146a9eaSAaron Smith Status NativeThreadWindows::DoStop() { 34*5146a9eaSAaron Smith if (m_state != eStateStopped) { 35*5146a9eaSAaron Smith DWORD previous_suspend_count = 36*5146a9eaSAaron Smith ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); 37*5146a9eaSAaron Smith if (previous_suspend_count == (DWORD)-1) 38*5146a9eaSAaron Smith return Status(::GetLastError(), eErrorTypeWin32); 39*5146a9eaSAaron Smith 40*5146a9eaSAaron Smith m_state = eStateStopped; 41*5146a9eaSAaron Smith } 42*5146a9eaSAaron Smith return Status(); 43*5146a9eaSAaron Smith } 44*5146a9eaSAaron Smith 45*5146a9eaSAaron Smith Status NativeThreadWindows::DoResume(lldb::StateType resume_state) { 46*5146a9eaSAaron Smith StateType current_state = GetState(); 47*5146a9eaSAaron Smith if (resume_state == current_state) 48*5146a9eaSAaron Smith return Status(); 49*5146a9eaSAaron Smith 50*5146a9eaSAaron Smith if (resume_state == eStateStepping) { 51*5146a9eaSAaron Smith uint32_t flags_index = 52*5146a9eaSAaron Smith GetRegisterContext().ConvertRegisterKindToRegisterNumber( 53*5146a9eaSAaron Smith eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 54*5146a9eaSAaron Smith uint64_t flags_value = 55*5146a9eaSAaron Smith GetRegisterContext().ReadRegisterAsUnsigned(flags_index, 0); 56*5146a9eaSAaron Smith flags_value |= 0x100; // Set the trap flag on the CPU 57*5146a9eaSAaron Smith GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value); 58*5146a9eaSAaron Smith } 59*5146a9eaSAaron Smith 60*5146a9eaSAaron Smith if (resume_state == eStateStepping || resume_state == eStateRunning) { 61*5146a9eaSAaron Smith DWORD previous_suspend_count = 0; 62*5146a9eaSAaron Smith HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 63*5146a9eaSAaron Smith do { 64*5146a9eaSAaron Smith // ResumeThread returns -1 on error, or the thread's *previous* suspend 65*5146a9eaSAaron Smith // count on success. This means that the return value is 1 when the thread 66*5146a9eaSAaron Smith // was restarted. Note that DWORD is an unsigned int, so we need to 67*5146a9eaSAaron Smith // explicitly compare with -1. 68*5146a9eaSAaron Smith previous_suspend_count = ::ResumeThread(thread_handle); 69*5146a9eaSAaron Smith 70*5146a9eaSAaron Smith if (previous_suspend_count == (DWORD)-1) 71*5146a9eaSAaron Smith return Status(::GetLastError(), eErrorTypeWin32); 72*5146a9eaSAaron Smith 73*5146a9eaSAaron Smith } while (previous_suspend_count > 1); 74*5146a9eaSAaron Smith m_state = eStateRunning; 75*5146a9eaSAaron Smith } 76*5146a9eaSAaron Smith 77*5146a9eaSAaron Smith return Status(); 78*5146a9eaSAaron Smith } 79*5146a9eaSAaron Smith 80*5146a9eaSAaron Smith std::string NativeThreadWindows::GetName() { 81*5146a9eaSAaron Smith if (!m_name.empty()) 82*5146a9eaSAaron Smith return m_name; 83*5146a9eaSAaron Smith 84*5146a9eaSAaron Smith // Name is not a property of the Windows thread. Create one with the 85*5146a9eaSAaron Smith // process's. 86*5146a9eaSAaron Smith NativeProcessProtocol &process = GetProcess(); 87*5146a9eaSAaron Smith ProcessInstanceInfo process_info; 88*5146a9eaSAaron Smith if (Host::GetProcessInfo(process.GetID(), process_info)) { 89*5146a9eaSAaron Smith std::string process_name(process_info.GetName()); 90*5146a9eaSAaron Smith m_name = process_name; 91*5146a9eaSAaron Smith } 92*5146a9eaSAaron Smith return m_name; 93*5146a9eaSAaron Smith } 94*5146a9eaSAaron Smith 95*5146a9eaSAaron Smith void NativeThreadWindows::SetStopReason(ThreadStopInfo stop_info, 96*5146a9eaSAaron Smith std::string description) { 97*5146a9eaSAaron Smith m_state = eStateStopped; 98*5146a9eaSAaron Smith m_stop_info = stop_info; 99*5146a9eaSAaron Smith m_stop_description = description; 100*5146a9eaSAaron Smith } 101*5146a9eaSAaron Smith 102*5146a9eaSAaron Smith bool NativeThreadWindows::GetStopReason(ThreadStopInfo &stop_info, 103*5146a9eaSAaron Smith std::string &description) { 104*5146a9eaSAaron Smith Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 105*5146a9eaSAaron Smith 106*5146a9eaSAaron Smith switch (m_state) { 107*5146a9eaSAaron Smith case eStateStopped: 108*5146a9eaSAaron Smith case eStateCrashed: 109*5146a9eaSAaron Smith case eStateExited: 110*5146a9eaSAaron Smith case eStateSuspended: 111*5146a9eaSAaron Smith case eStateUnloaded: 112*5146a9eaSAaron Smith stop_info = m_stop_info; 113*5146a9eaSAaron Smith description = m_stop_description; 114*5146a9eaSAaron Smith return true; 115*5146a9eaSAaron Smith 116*5146a9eaSAaron Smith case eStateInvalid: 117*5146a9eaSAaron Smith case eStateConnected: 118*5146a9eaSAaron Smith case eStateAttaching: 119*5146a9eaSAaron Smith case eStateLaunching: 120*5146a9eaSAaron Smith case eStateRunning: 121*5146a9eaSAaron Smith case eStateStepping: 122*5146a9eaSAaron Smith case eStateDetached: 123*5146a9eaSAaron Smith if (log) { 124*5146a9eaSAaron Smith log->Printf("NativeThreadWindows::%s tid %" PRIu64 125*5146a9eaSAaron Smith " in state %s cannot answer stop reason", 126*5146a9eaSAaron Smith __FUNCTION__, GetID(), StateAsCString(m_state)); 127*5146a9eaSAaron Smith } 128*5146a9eaSAaron Smith return false; 129*5146a9eaSAaron Smith } 130*5146a9eaSAaron Smith llvm_unreachable("unhandled StateType!"); 131*5146a9eaSAaron Smith } 132*5146a9eaSAaron Smith 133*5146a9eaSAaron Smith Status NativeThreadWindows::SetWatchpoint(lldb::addr_t addr, size_t size, 134*5146a9eaSAaron Smith uint32_t watch_flags, bool hardware) { 135*5146a9eaSAaron Smith return Status("unimplemented."); 136*5146a9eaSAaron Smith } 137*5146a9eaSAaron Smith 138*5146a9eaSAaron Smith Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) { 139*5146a9eaSAaron Smith return Status("unimplemented"); 140*5146a9eaSAaron Smith } 141*5146a9eaSAaron Smith 142*5146a9eaSAaron Smith Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr, 143*5146a9eaSAaron Smith size_t size) { 144*5146a9eaSAaron Smith return Status("unimplemented."); 145*5146a9eaSAaron Smith } 146*5146a9eaSAaron Smith 147*5146a9eaSAaron Smith Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) { 148*5146a9eaSAaron Smith return Status("unimplemented."); 149*5146a9eaSAaron Smith } 150