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/Log.h"
17 #include "lldb/Utility/State.h"
18
19 #include "lldb/lldb-forward.h"
20
21 using namespace lldb;
22 using namespace lldb_private;
23
24 NativeThreadWindows::NativeThreadWindows(NativeProcessWindows &process,
25 const HostThread &thread)
26 : NativeThreadProtocol(process, thread.GetNativeThread().GetThreadId()),
27 m_stop_info(), m_stop_description(), m_host_thread(thread) {
28 m_reg_context_up =
29 (NativeRegisterContextWindows::CreateHostNativeRegisterContextWindows(
30 process.GetArchitecture(), *this));
31 }
32
33 Status NativeThreadWindows::DoStop() {
34 if (m_state != eStateStopped) {
35 DWORD previous_suspend_count =
36 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
37 if (previous_suspend_count == (DWORD)-1)
38 return Status(::GetLastError(), eErrorTypeWin32);
39
40 m_state = eStateStopped;
41 }
42 return Status();
43 }
44
45 Status NativeThreadWindows::DoResume(lldb::StateType resume_state) {
46 StateType current_state = GetState();
47 if (resume_state == current_state)
48 return Status();
49
50 if (resume_state == eStateStepping) {
51 uint32_t flags_index =
52 GetRegisterContext().ConvertRegisterKindToRegisterNumber(
53 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
54 uint64_t flags_value =
55 GetRegisterContext().ReadRegisterAsUnsigned(flags_index, 0);
56 flags_value |= 0x100; // Set the trap flag on the CPU
57 GetRegisterContext().WriteRegisterFromUnsigned(flags_index, flags_value);
58 }
59
60 if (resume_state == eStateStepping || resume_state == eStateRunning) {
CreateRegisterInfoInterface(const ArchSpec & target_arch)61 DWORD previous_suspend_count = 0;
62 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
63 do {
64 // ResumeThread returns -1 on error, or the thread's *previous* suspend
65 // count on success. This means that the return value is 1 when the thread
66 // was restarted. Note that DWORD is an unsigned int, so we need to
GetThreadContextHelper(lldb::thread_t thread_handle,PCONTEXT context_ptr,const DWORD control_flag)67 // explicitly compare with -1.
68 previous_suspend_count = ::ResumeThread(thread_handle);
69
70 if (previous_suspend_count == (DWORD)-1)
71 return Status(::GetLastError(), eErrorTypeWin32);
72
73 } while (previous_suspend_count > 1);
74 m_state = eStateRunning;
75 }
76
77 return Status();
78 }
79
80 std::string NativeThreadWindows::GetName() {
81 if (!m_name.empty())
82 return m_name;
83
SetThreadContextHelper(lldb::thread_t thread_handle,PCONTEXT context_ptr)84 // Name is not a property of the Windows thread. Create one with the
85 // process's.
86 NativeProcessProtocol &process = GetProcess();
87 ProcessInstanceInfo process_info;
88 if (Host::GetProcessInfo(process.GetID(), process_info)) {
89 std::string process_name(process_info.GetName());
90 m_name = process_name;
91 }
92 return m_name;
93 }
94
95 void NativeThreadWindows::SetStopReason(ThreadStopInfo stop_info,
96 std::string description) {
97 m_state = eStateStopped;
98 m_stop_info = stop_info;
CreateHostNativeRegisterContextWindows(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)99 m_stop_description = description;
100 }
101
102 bool NativeThreadWindows::GetStopReason(ThreadStopInfo &stop_info,
103 std::string &description) {
104 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
105
106 switch (m_state) {
107 case eStateStopped:
108 case eStateCrashed:
109 case eStateExited:
110 case eStateSuspended:
NativeRegisterContextWindows_x86_64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)111 case eStateUnloaded:
112 stop_info = m_stop_info;
113 description = m_stop_description;
114 return true;
115
IsGPR(uint32_t reg_index) const116 case eStateInvalid:
117 case eStateConnected:
118 case eStateAttaching:
119 case eStateLaunching:
120 case eStateRunning:
121 case eStateStepping:
122 case eStateDetached:
123 if (log) {
124 log->Printf("NativeThreadWindows::%s tid %" PRIu64
125 " in state %s cannot answer stop reason",
126 __FUNCTION__, GetID(), StateAsCString(m_state));
127 }
GetRegisterSetCount() const128 return false;
129 }
130 llvm_unreachable("unhandled StateType!");
131 }
132
GetRegisterSet(uint32_t set_index) const133 Status NativeThreadWindows::SetWatchpoint(lldb::addr_t addr, size_t size,
134 uint32_t watch_flags, bool hardware) {
135 if (!hardware)
136 return Status("not implemented");
137 if (m_state == eStateLaunching)
138 return Status();
139 Status error = RemoveWatchpoint(addr);
140 if (error.Fail())
141 return error;
142 uint32_t wp_index =
143 m_reg_context_up->SetHardwareWatchpoint(addr, size, watch_flags);
144 if (wp_index == LLDB_INVALID_INDEX32)
145 return Status("Setting hardware watchpoint failed.");
146 m_watchpoint_index_map.insert({addr, wp_index});
147 return Status();
148 }
149
150 Status NativeThreadWindows::RemoveWatchpoint(lldb::addr_t addr) {
151 auto wp = m_watchpoint_index_map.find(addr);
152 if (wp == m_watchpoint_index_map.end())
153 return Status();
154 uint32_t wp_index = wp->second;
155 m_watchpoint_index_map.erase(wp);
156 if (m_reg_context_up->ClearHardwareWatchpoint(wp_index))
157 return Status();
158 return Status("Clearing hardware watchpoint failed.");
159 }
160
161 Status NativeThreadWindows::SetHardwareBreakpoint(lldb::addr_t addr,
162 size_t size) {
163 return Status("unimplemented.");
164 }
165
166 Status NativeThreadWindows::RemoveHardwareBreakpoint(lldb::addr_t addr) {
167 return Status("unimplemented.");
168 }
169