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