1 //===-- TargetThreadWindows.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 "lldb/Host/HostInfo.h" 10 #include "lldb/Target/Unwind.h" 11 #include "lldb/Utility/LLDBLog.h" 12 #include "lldb/Utility/Log.h" 13 14 #include "ProcessWindows.h" 15 #include "TargetThreadWindows.h" 16 #include "lldb/Host/windows/HostThreadWindows.h" 17 #include <llvm/Support/ConvertUTF.h> 18 19 #if defined(__x86_64__) || defined(_M_AMD64) 20 #include "x64/RegisterContextWindows_x64.h" 21 #elif defined(__i386__) || defined(_M_IX86) 22 #include "x86/RegisterContextWindows_x86.h" 23 #elif defined(__aarch64__) || defined(_M_ARM64) 24 #include "arm64/RegisterContextWindows_arm64.h" 25 #elif defined(__arm__) || defined(_M_ARM) 26 #include "arm/RegisterContextWindows_arm.h" 27 #endif 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 using GetThreadDescriptionFunctionPtr = 33 HRESULT(WINAPI *)(HANDLE hThread, PWSTR *ppszThreadDescription); 34 35 TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, 36 const HostThread &thread) 37 : Thread(process, thread.GetNativeThread().GetThreadId()), 38 m_thread_reg_ctx_sp(), m_host_thread(thread) {} 39 40 TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } 41 42 void TargetThreadWindows::RefreshStateAfterStop() { 43 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); 44 SetState(eStateStopped); 45 GetRegisterContext()->InvalidateIfNeeded(false); 46 } 47 48 void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} 49 50 void TargetThreadWindows::DidStop() {} 51 52 RegisterContextSP TargetThreadWindows::GetRegisterContext() { 53 if (!m_reg_context_sp) 54 m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 55 56 return m_reg_context_sp; 57 } 58 59 RegisterContextSP 60 TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { 61 RegisterContextSP reg_ctx_sp; 62 uint32_t concrete_frame_idx = 0; 63 Log *log = GetLog(LLDBLog::Thread); 64 65 if (frame) 66 concrete_frame_idx = frame->GetConcreteFrameIndex(); 67 68 if (concrete_frame_idx == 0) { 69 if (!m_thread_reg_ctx_sp) { 70 ArchSpec arch = HostInfo::GetArchitecture(); 71 switch (arch.GetMachine()) { 72 case llvm::Triple::arm: 73 case llvm::Triple::thumb: 74 #if defined(__arm__) || defined(_M_ARM) 75 m_thread_reg_ctx_sp.reset( 76 new RegisterContextWindows_arm(*this, concrete_frame_idx)); 77 #else 78 LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 79 #endif 80 break; 81 82 case llvm::Triple::aarch64: 83 #if defined(__aarch64__) || defined(_M_ARM64) 84 m_thread_reg_ctx_sp.reset( 85 new RegisterContextWindows_arm64(*this, concrete_frame_idx)); 86 #else 87 LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 88 #endif 89 break; 90 91 case llvm::Triple::x86: 92 #if defined(__i386__) || defined(_M_IX86) 93 m_thread_reg_ctx_sp.reset( 94 new RegisterContextWindows_x86(*this, concrete_frame_idx)); 95 #else 96 LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 97 #endif 98 break; 99 100 case llvm::Triple::x86_64: 101 #if defined(__x86_64__) || defined(_M_AMD64) 102 m_thread_reg_ctx_sp.reset( 103 new RegisterContextWindows_x64(*this, concrete_frame_idx)); 104 #else 105 LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 106 #endif 107 break; 108 109 default: 110 break; 111 } 112 } 113 reg_ctx_sp = m_thread_reg_ctx_sp; 114 } else { 115 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); 116 } 117 118 return reg_ctx_sp; 119 } 120 121 bool TargetThreadWindows::CalculateStopInfo() { 122 SetStopInfo(m_stop_info_sp); 123 return true; 124 } 125 126 Status TargetThreadWindows::DoResume() { 127 StateType resume_state = GetTemporaryResumeState(); 128 StateType current_state = GetState(); 129 if (resume_state == current_state) 130 return Status(); 131 132 if (resume_state == eStateStepping) { 133 Log *log = GetLog(LLDBLog::Thread); 134 135 uint32_t flags_index = 136 GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 137 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 138 uint64_t flags_value = 139 GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); 140 ProcessSP process = GetProcess(); 141 const ArchSpec &arch = process->GetTarget().GetArchitecture(); 142 switch (arch.GetMachine()) { 143 case llvm::Triple::x86: 144 case llvm::Triple::x86_64: 145 flags_value |= 0x100; // Set the trap flag on the CPU 146 break; 147 case llvm::Triple::aarch64: 148 case llvm::Triple::arm: 149 case llvm::Triple::thumb: 150 flags_value |= 0x200000; // The SS bit in PState 151 break; 152 default: 153 LLDB_LOG(log, "single stepping unsupported on this architecture"); 154 break; 155 } 156 GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); 157 } 158 159 if (resume_state == eStateStepping || resume_state == eStateRunning) { 160 DWORD previous_suspend_count = 0; 161 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 162 do { 163 // ResumeThread returns -1 on error, or the thread's *previous* suspend 164 // count on success. This means that the return value is 1 when the thread 165 // was restarted. Note that DWORD is an unsigned int, so we need to 166 // explicitly compare with -1. 167 previous_suspend_count = ::ResumeThread(thread_handle); 168 169 if (previous_suspend_count == (DWORD)-1) 170 return Status(::GetLastError(), eErrorTypeWin32); 171 172 } while (previous_suspend_count > 1); 173 } 174 175 return Status(); 176 } 177 178 const char *TargetThreadWindows::GetName() { 179 Log *log = GetLog(LLDBLog::Thread); 180 static GetThreadDescriptionFunctionPtr GetThreadDescription = []() { 181 HMODULE hModule = ::LoadLibraryW(L"Kernel32.dll"); 182 return hModule 183 ? reinterpret_cast<GetThreadDescriptionFunctionPtr>( 184 (void *)::GetProcAddress(hModule, "GetThreadDescription")) 185 : nullptr; 186 }(); 187 LLDB_LOGF(log, "GetProcAddress: %p", 188 reinterpret_cast<void *>(GetThreadDescription)); 189 if (!GetThreadDescription) 190 return m_name.c_str(); 191 PWSTR pszThreadName; 192 if (SUCCEEDED(GetThreadDescription( 193 m_host_thread.GetNativeThread().GetSystemHandle(), &pszThreadName))) { 194 LLDB_LOGF(log, "GetThreadDescription: %ls", pszThreadName); 195 llvm::convertUTF16ToUTF8String( 196 llvm::ArrayRef(reinterpret_cast<char *>(pszThreadName), 197 wcslen(pszThreadName) * sizeof(wchar_t)), 198 m_name); 199 ::LocalFree(pszThreadName); 200 } 201 202 return m_name.c_str(); 203 } 204