xref: /llvm-project/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
1 //===-- TargetThreadWindows.cpp----------------------------------*- C++ -*-===//
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/Utility/Log.h"
15 #include "lldb/Utility/Logging.h"
16 #include "lldb/Utility/State.h"
17 
18 #include "Plugins/Process/Utility/UnwindLLDB.h"
19 #include "ProcessWindows.h"
20 #include "ProcessWindowsLog.h"
21 #include "TargetThreadWindows.h"
22 
23 #if defined(_WIN64)
24 #include "x64/RegisterContextWindows_x64.h"
25 #else
26 #include "x86/RegisterContextWindows_x86.h"
27 #endif
28 
29 using namespace lldb;
30 using namespace lldb_private;
31 
32 TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
33                                          const HostThread &thread)
34     : Thread(process, thread.GetNativeThread().GetThreadId()),
35       m_thread_reg_ctx_sp(), m_host_thread(thread) {}
36 
37 TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
38 
39 void TargetThreadWindows::RefreshStateAfterStop() {
40   ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
41   SetState(eStateStopped);
42   GetRegisterContext()->InvalidateIfNeeded(false);
43 }
44 
45 void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
46 
47 void TargetThreadWindows::DidStop() {}
48 
49 RegisterContextSP TargetThreadWindows::GetRegisterContext() {
50   if (!m_reg_context_sp)
51     m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
52 
53   return m_reg_context_sp;
54 }
55 
56 RegisterContextSP
57 TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
58   RegisterContextSP reg_ctx_sp;
59   uint32_t concrete_frame_idx = 0;
60   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
61 
62   if (frame)
63     concrete_frame_idx = frame->GetConcreteFrameIndex();
64 
65   if (concrete_frame_idx == 0) {
66     if (!m_thread_reg_ctx_sp) {
67       ArchSpec arch = HostInfo::GetArchitecture();
68       switch (arch.GetMachine()) {
69       case llvm::Triple::x86:
70 #if defined(_WIN64)
71         // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
72         LLDB_LOG(log, "This is a Wow64 process, we should create a "
73                       "RegisterContextWindows_Wow64, but we don't.");
74 #else
75         m_thread_reg_ctx_sp.reset(
76             new RegisterContextWindows_x86(*this, concrete_frame_idx));
77 #endif
78         break;
79       case llvm::Triple::x86_64:
80 #if defined(_WIN64)
81         m_thread_reg_ctx_sp.reset(
82             new RegisterContextWindows_x64(*this, concrete_frame_idx));
83 #else
84         LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit.");
85 #endif
86       default:
87         break;
88       }
89     }
90     reg_ctx_sp = m_thread_reg_ctx_sp;
91   } else {
92     Unwind *unwinder = GetUnwinder();
93     if (unwinder != nullptr)
94       reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
95   }
96 
97   return reg_ctx_sp;
98 }
99 
100 bool TargetThreadWindows::CalculateStopInfo() {
101   SetStopInfo(m_stop_info_sp);
102   return true;
103 }
104 
105 Unwind *TargetThreadWindows::GetUnwinder() {
106   // FIXME: Implement an unwinder based on the Windows unwinder exposed through
107   // DIA SDK.
108   if (!m_unwinder_ap)
109     m_unwinder_ap.reset(new UnwindLLDB(*this));
110   return m_unwinder_ap.get();
111 }
112 
113 Status TargetThreadWindows::DoResume() {
114   StateType resume_state = GetTemporaryResumeState();
115   StateType current_state = GetState();
116   if (resume_state == current_state)
117     return Status();
118 
119   if (resume_state == eStateStepping) {
120     uint32_t flags_index =
121         GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
122             eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
123     uint64_t flags_value =
124         GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
125     flags_value |= 0x100; // Set the trap flag on the CPU
126     GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
127   }
128 
129   if (resume_state == eStateStepping || resume_state == eStateRunning) {
130     DWORD previous_suspend_count = 0;
131     HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
132     do {
133       // ResumeThread returns -1 on error, or the thread's *previous* suspend
134       // count on success. This means that the return value is 1 when the thread
135       // was restarted. Note that DWORD is an unsigned int, so we need to
136       // explicitly compare with -1.
137       previous_suspend_count = ::ResumeThread(thread_handle);
138 
139       if (previous_suspend_count == (DWORD)-1)
140         return Status(::GetLastError(), eErrorTypeWin32);
141 
142     } while (previous_suspend_count > 1);
143   }
144 
145   return Status();
146 }
147