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-exception
6 //
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
22 using namespace lldb;
23 using namespace lldb_private;
24
NativeThreadWindows(NativeProcessWindows & process,const HostThread & thread)25 NativeThreadWindows::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
DoStop()34 Status 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
DoResume(lldb::StateType resume_state)46 Status 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 CPU
65 break;
66 case llvm::Triple::aarch64:
67 case llvm::Triple::arm:
68 case llvm::Triple::thumb:
69 flags_value |= 0x200000; // The SS bit in PState
70 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* suspend
83 // count on success. This means that the return value is 1 when the thread
84 // was restarted. Note that DWORD is an unsigned int, so we need to
85 // 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
GetName()98 std::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 the
103 // 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
SetStopReason(ThreadStopInfo stop_info,std::string description)113 void 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
GetStopReason(ThreadStopInfo & stop_info,std::string & description)120 bool 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 %" PRIu64
143 " 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
SetWatchpoint(lldb::addr_t addr,size_t size,uint32_t watch_flags,bool hardware)151 Status NativeThreadWindows::SetWatchpoint(lldb::addr_t addr, size_t size,
152 uint32_t watch_flags, bool hardware) {
153 if (!hardware)
154 return Status("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("Setting hardware watchpoint failed.");
164 m_watchpoint_index_map.insert({addr, wp_index});
165 return Status();
166 }
167
RemoveWatchpoint(lldb::addr_t addr)168 Status 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("Clearing hardware watchpoint failed.");
177 }
178
SetHardwareBreakpoint(lldb::addr_t addr,size_t size)179 Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
180 size_t size) {
181 return Status("unimplemented.");
182 }
183
RemoveHardwareBreakpoint(lldb::addr_t addr)184 Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
185 return Status("unimplemented.");
186 }
187