1 //===-- TargetThreadWindows.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 "lldb/Host/HostInfo.h"
10 #include "lldb/Host/HostNativeThreadBase.h"
11 #include "lldb/Host/windows/HostThreadWindows.h"
12 #include "lldb/Host/windows/windows.h"
13 #include "lldb/Target/RegisterContext.h"
14 #include "lldb/Target/Unwind.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/Logging.h"
17 #include "lldb/Utility/State.h"
18
19 #include "ProcessWindows.h"
20 #include "ProcessWindowsLog.h"
21 #include "TargetThreadWindows.h"
22
23 #if defined(__x86_64__) || defined(_M_AMD64)
24 #include "x64/RegisterContextWindows_x64.h"
25 #elif defined(__i386__) || defined(_M_IX86)
26 #include "x86/RegisterContextWindows_x86.h"
27 #elif defined(__aarch64__) || defined(_M_ARM64)
28 #include "arm64/RegisterContextWindows_arm64.h"
29 #elif defined(__arm__) || defined(_M_ARM)
30 #include "arm/RegisterContextWindows_arm.h"
31 #endif
32
33 using namespace lldb;
34 using namespace lldb_private;
35
TargetThreadWindows(ProcessWindows & process,const HostThread & thread)36 TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
37 const HostThread &thread)
38 : Thread(process, thread.GetNativeThread().GetThreadId()),
39 m_thread_reg_ctx_sp(), m_host_thread(thread) {}
40
~TargetThreadWindows()41 TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
42
RefreshStateAfterStop()43 void TargetThreadWindows::RefreshStateAfterStop() {
44 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
45 SetState(eStateStopped);
46 GetRegisterContext()->InvalidateIfNeeded(false);
47 }
48
WillResume(lldb::StateType resume_state)49 void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
50
DidStop()51 void TargetThreadWindows::DidStop() {}
52
GetRegisterContext()53 RegisterContextSP TargetThreadWindows::GetRegisterContext() {
54 if (!m_reg_context_sp)
55 m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
56
57 return m_reg_context_sp;
58 }
59
60 RegisterContextSP
CreateRegisterContextForFrame(StackFrame * frame)61 TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
62 RegisterContextSP reg_ctx_sp;
63 uint32_t concrete_frame_idx = 0;
64 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
65
66 if (frame)
67 concrete_frame_idx = frame->GetConcreteFrameIndex();
68
69 if (concrete_frame_idx == 0) {
70 if (!m_thread_reg_ctx_sp) {
71 ArchSpec arch = HostInfo::GetArchitecture();
72 switch (arch.GetMachine()) {
73 case llvm::Triple::arm:
74 case llvm::Triple::thumb:
75 #if defined(__arm__) || defined(_M_ARM)
76 m_thread_reg_ctx_sp.reset(
77 new RegisterContextWindows_arm(*this, concrete_frame_idx));
78 #else
79 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
80 #endif
81 break;
82
83 case llvm::Triple::aarch64:
84 #if defined(__aarch64__) || defined(_M_ARM64)
85 m_thread_reg_ctx_sp.reset(
86 new RegisterContextWindows_arm64(*this, concrete_frame_idx));
87 #else
88 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
89 #endif
90 break;
91
92 case llvm::Triple::x86:
93 #if defined(__i386__) || defined(_M_IX86)
94 m_thread_reg_ctx_sp.reset(
95 new RegisterContextWindows_x86(*this, concrete_frame_idx));
96 #else
97 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
98 #endif
99 break;
100
101 case llvm::Triple::x86_64:
102 #if defined(__x86_64__) || defined(_M_AMD64)
103 m_thread_reg_ctx_sp.reset(
104 new RegisterContextWindows_x64(*this, concrete_frame_idx));
105 #else
106 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
107 #endif
108 break;
109
110 default:
111 break;
112 }
113 }
114 reg_ctx_sp = m_thread_reg_ctx_sp;
115 } else {
116 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
117 }
118
119 return reg_ctx_sp;
120 }
121
CalculateStopInfo()122 bool TargetThreadWindows::CalculateStopInfo() {
123 SetStopInfo(m_stop_info_sp);
124 return true;
125 }
126
DoResume()127 Status TargetThreadWindows::DoResume() {
128 StateType resume_state = GetTemporaryResumeState();
129 StateType current_state = GetState();
130 if (resume_state == current_state)
131 return Status();
132
133 if (resume_state == eStateStepping) {
134 uint32_t flags_index =
135 GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
136 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
137 uint64_t flags_value =
138 GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
139 flags_value |= 0x100; // Set the trap flag on the CPU
140 GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
141 }
142
143 if (resume_state == eStateStepping || resume_state == eStateRunning) {
144 DWORD previous_suspend_count = 0;
145 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
146 do {
147 // ResumeThread returns -1 on error, or the thread's *previous* suspend
148 // count on success. This means that the return value is 1 when the thread
149 // was restarted. Note that DWORD is an unsigned int, so we need to
150 // explicitly compare with -1.
151 previous_suspend_count = ::ResumeThread(thread_handle);
152
153 if (previous_suspend_count == (DWORD)-1)
154 return Status(::GetLastError(), eErrorTypeWin32);
155
156 } while (previous_suspend_count > 1);
157 }
158
159 return Status();
160 }
161