1dda28197Spatrick //===-- NativeThreadWindows.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "NativeThreadWindows.h"
10061da546Spatrick #include "NativeProcessWindows.h"
11061da546Spatrick
12061da546Spatrick #include "lldb/Host/HostThread.h"
13061da546Spatrick #include "lldb/Host/windows/HostThreadWindows.h"
14061da546Spatrick #include "lldb/Host/windows/windows.h"
15061da546Spatrick #include "lldb/Target/Process.h"
16*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
17061da546Spatrick #include "lldb/Utility/Log.h"
18061da546Spatrick #include "lldb/Utility/State.h"
19061da546Spatrick
20061da546Spatrick #include "lldb/lldb-forward.h"
21061da546Spatrick
22061da546Spatrick using namespace lldb;
23061da546Spatrick using namespace lldb_private;
24061da546Spatrick
NativeThreadWindows(NativeProcessWindows & process,const HostThread & thread)25061da546Spatrick NativeThreadWindows::NativeThreadWindows(NativeProcessWindows &process,
26061da546Spatrick const HostThread &thread)
27061da546Spatrick : NativeThreadProtocol(process, thread.GetNativeThread().GetThreadId()),
28061da546Spatrick m_stop_info(), m_stop_description(), m_host_thread(thread) {
29061da546Spatrick m_reg_context_up =
30061da546Spatrick (NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
31061da546Spatrick process.GetArchitecture(), *this));
32061da546Spatrick }
33061da546Spatrick
DoStop()34061da546Spatrick Status NativeThreadWindows::DoStop() {
35061da546Spatrick if (m_state != eStateStopped) {
36061da546Spatrick DWORD previous_suspend_count =
37061da546Spatrick ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
38061da546Spatrick if (previous_suspend_count == (DWORD)-1)
39061da546Spatrick return Status(::GetLastError(), eErrorTypeWin32);
40061da546Spatrick
41061da546Spatrick m_state = eStateStopped;
42061da546Spatrick }
43061da546Spatrick return Status();
44061da546Spatrick }
45061da546Spatrick
DoResume(lldb::StateType resume_state)46061da546Spatrick Status NativeThreadWindows::DoResume(lldb::StateType resume_state) {
47061da546Spatrick StateType current_state = GetState();
48061da546Spatrick if (resume_state == current_state)
49061da546Spatrick return Status();
50061da546Spatrick
51061da546Spatrick if (resume_state == eStateStepping) {
52*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Thread);
53*f6aab3d8Srobert
54061da546Spatrick uint32_t flags_index =
55061da546Spatrick GetRegisterContext().ConvertRegisterKindToRegisterNumber(
56061da546Spatrick eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
57061da546Spatrick uint64_t flags_value =
58061da546Spatrick GetRegisterContext().ReadRegisterAsUnsigned(flags_index, 0);
59*f6aab3d8Srobert NativeProcessProtocol &process = GetProcess();
60*f6aab3d8Srobert const ArchSpec &arch = process.GetArchitecture();
61*f6aab3d8Srobert switch (arch.GetMachine()) {
62*f6aab3d8Srobert case llvm::Triple::x86:
63*f6aab3d8Srobert case llvm::Triple::x86_64:
64061da546Spatrick flags_value |= 0x100; // Set the trap flag on the CPU
65*f6aab3d8Srobert break;
66*f6aab3d8Srobert case llvm::Triple::aarch64:
67*f6aab3d8Srobert case llvm::Triple::arm:
68*f6aab3d8Srobert case llvm::Triple::thumb:
69*f6aab3d8Srobert flags_value |= 0x200000; // The SS bit in PState
70*f6aab3d8Srobert break;
71*f6aab3d8Srobert default:
72*f6aab3d8Srobert LLDB_LOG(log, "single stepping unsupported on this architecture");
73*f6aab3d8Srobert break;
74*f6aab3d8Srobert }
75061da546Spatrick GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value);
76061da546Spatrick }
77061da546Spatrick
78061da546Spatrick if (resume_state == eStateStepping || resume_state == eStateRunning) {
79061da546Spatrick DWORD previous_suspend_count = 0;
80061da546Spatrick HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
81061da546Spatrick do {
82061da546Spatrick // ResumeThread returns -1 on error, or the thread's *previous* suspend
83061da546Spatrick // count on success. This means that the return value is 1 when the thread
84061da546Spatrick // was restarted. Note that DWORD is an unsigned int, so we need to
85061da546Spatrick // explicitly compare with -1.
86061da546Spatrick previous_suspend_count = ::ResumeThread(thread_handle);
87061da546Spatrick
88061da546Spatrick if (previous_suspend_count == (DWORD)-1)
89061da546Spatrick return Status(::GetLastError(), eErrorTypeWin32);
90061da546Spatrick
91061da546Spatrick } while (previous_suspend_count > 1);
92061da546Spatrick m_state = eStateRunning;
93061da546Spatrick }
94061da546Spatrick
95061da546Spatrick return Status();
96061da546Spatrick }
97061da546Spatrick
GetName()98061da546Spatrick std::string NativeThreadWindows::GetName() {
99061da546Spatrick if (!m_name.empty())
100061da546Spatrick return m_name;
101061da546Spatrick
102061da546Spatrick // Name is not a property of the Windows thread. Create one with the
103061da546Spatrick // process's.
104061da546Spatrick NativeProcessProtocol &process = GetProcess();
105061da546Spatrick ProcessInstanceInfo process_info;
106061da546Spatrick if (Host::GetProcessInfo(process.GetID(), process_info)) {
107061da546Spatrick std::string process_name(process_info.GetName());
108061da546Spatrick m_name = process_name;
109061da546Spatrick }
110061da546Spatrick return m_name;
111061da546Spatrick }
112061da546Spatrick
SetStopReason(ThreadStopInfo stop_info,std::string description)113061da546Spatrick void NativeThreadWindows::SetStopReason(ThreadStopInfo stop_info,
114061da546Spatrick std::string description) {
115061da546Spatrick m_state = eStateStopped;
116061da546Spatrick m_stop_info = stop_info;
117061da546Spatrick m_stop_description = description;
118061da546Spatrick }
119061da546Spatrick
GetStopReason(ThreadStopInfo & stop_info,std::string & description)120061da546Spatrick bool NativeThreadWindows::GetStopReason(ThreadStopInfo &stop_info,
121061da546Spatrick std::string &description) {
122*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Thread);
123061da546Spatrick
124061da546Spatrick switch (m_state) {
125061da546Spatrick case eStateStopped:
126061da546Spatrick case eStateCrashed:
127061da546Spatrick case eStateExited:
128061da546Spatrick case eStateSuspended:
129061da546Spatrick case eStateUnloaded:
130061da546Spatrick stop_info = m_stop_info;
131061da546Spatrick description = m_stop_description;
132061da546Spatrick return true;
133061da546Spatrick
134061da546Spatrick case eStateInvalid:
135061da546Spatrick case eStateConnected:
136061da546Spatrick case eStateAttaching:
137061da546Spatrick case eStateLaunching:
138061da546Spatrick case eStateRunning:
139061da546Spatrick case eStateStepping:
140061da546Spatrick case eStateDetached:
141061da546Spatrick if (log) {
142061da546Spatrick log->Printf("NativeThreadWindows::%s tid %" PRIu64
143061da546Spatrick " in state %s cannot answer stop reason",
144061da546Spatrick __FUNCTION__, GetID(), StateAsCString(m_state));
145061da546Spatrick }
146061da546Spatrick return false;
147061da546Spatrick }
148061da546Spatrick llvm_unreachable("unhandled StateType!");
149061da546Spatrick }
150061da546Spatrick
SetWatchpoint(lldb::addr_t addr,size_t size,uint32_t watch_flags,bool hardware)151061da546Spatrick Status NativeThreadWindows::SetWatchpoint(lldb::addr_t addr, size_t size,
152061da546Spatrick uint32_t watch_flags, bool hardware) {
153061da546Spatrick if (!hardware)
154061da546Spatrick return Status("not implemented");
155061da546Spatrick if (m_state == eStateLaunching)
156061da546Spatrick return Status();
157061da546Spatrick Status error = RemoveWatchpoint(addr);
158061da546Spatrick if (error.Fail())
159061da546Spatrick return error;
160061da546Spatrick uint32_t wp_index =
161061da546Spatrick m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags);
162061da546Spatrick if (wp_index == LLDB_INVALID_INDEX32)
163061da546Spatrick return Status("Setting hardware watchpoint failed.");
164061da546Spatrick m_watchpoint_index_map.insert({addr, wp_index});
165061da546Spatrick return Status();
166061da546Spatrick }
167061da546Spatrick
RemoveWatchpoint(lldb::addr_t addr)168061da546Spatrick Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) {
169061da546Spatrick auto wp = m_watchpoint_index_map.find(addr);
170061da546Spatrick if (wp == m_watchpoint_index_map.end())
171061da546Spatrick return Status();
172061da546Spatrick uint32_t wp_index = wp->second;
173061da546Spatrick m_watchpoint_index_map.erase(wp);
174061da546Spatrick if (m_reg_context_up->ClearHardwareWatchpoint(wp_index))
175061da546Spatrick return Status();
176061da546Spatrick return Status("Clearing hardware watchpoint failed.");
177061da546Spatrick }
178061da546Spatrick
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)179061da546Spatrick Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
180061da546Spatrick size_t size) {
181061da546Spatrick return Status("unimplemented.");
182061da546Spatrick }
183061da546Spatrick
RemoveHardwareBreakpoint(lldb::addr_t addr)184061da546Spatrick Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
185061da546Spatrick return Status("unimplemented.");
186061da546Spatrick }
187