brintos

brintos / llvm-project-archived public Read only

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