205 lines · cpp
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-exception6//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#endif28 29using namespace lldb;30using namespace lldb_private;31 32using GetThreadDescriptionFunctionPtr =33 HRESULT(WINAPI *)(HANDLE hThread, PWSTR *ppszThreadDescription);34 35TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,36 const HostThread &thread)37 : Thread(process, thread.GetNativeThread().GetThreadId()),38 m_thread_reg_ctx_sp(), m_host_thread(thread) {}39 40TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }41 42void TargetThreadWindows::RefreshStateAfterStop() {43 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());44 SetState(eStateStopped);45 GetRegisterContext()->InvalidateIfNeeded(false);46}47 48void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}49 50void TargetThreadWindows::DidStop() {}51 52RegisterContextSP TargetThreadWindows::GetRegisterContext() {53 if (!m_reg_context_sp)54 m_reg_context_sp = CreateRegisterContextForFrame(nullptr);55 56 return m_reg_context_sp;57}58 59RegisterContextSP60TargetThreadWindows::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#else78 LLDB_LOG(log, "debugging foreign targets is currently unsupported");79#endif80 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#else87 LLDB_LOG(log, "debugging foreign targets is currently unsupported");88#endif89 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#else96 LLDB_LOG(log, "debugging foreign targets is currently unsupported");97#endif98 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#else105 LLDB_LOG(log, "debugging foreign targets is currently unsupported");106#endif107 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 121bool TargetThreadWindows::CalculateStopInfo() {122 SetStopInfo(m_stop_info_sp);123 return true;124}125 126Status 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 CPU146 break;147 case llvm::Triple::aarch64:148 case llvm::Triple::arm:149 case llvm::Triple::thumb:150 flags_value |= 0x200000; // The SS bit in PState151 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* suspend164 // count on success. This means that the return value is 1 when the thread165 // was restarted. Note that DWORD is an unsigned int, so we need to166 // 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 178const char *TargetThreadWindows::GetName() {179 Log *log = GetLog(LLDBLog::Thread);180 static GetThreadDescriptionFunctionPtr GetThreadDescription = []() {181 HMODULE hModule = ::LoadLibraryW(L"Kernel32.dll");182 return hModule183 ? 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 m_name.clear();196 llvm::convertUTF16ToUTF8String(197 llvm::ArrayRef(reinterpret_cast<char *>(pszThreadName),198 wcslen(pszThreadName) * sizeof(wchar_t)),199 m_name);200 ::LocalFree(pszThreadName);201 }202 203 return m_name.c_str();204}205