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