brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.6 KiB · b2b66f2 Raw
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