LLDB mainline
TargetThreadWindows.cpp
Go to the documentation of this file.
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
10#include "lldb/Target/Unwind.h"
12#include "lldb/Utility/Log.h"
13
14#include "ProcessWindows.h"
15#include "TargetThreadWindows.h"
17#include <llvm/Support/ConvertUTF.h>
18
19#if defined(__x86_64__) || defined(_M_AMD64)
21#elif defined(__i386__) || defined(_M_IX86)
23#elif defined(__aarch64__) || defined(_M_ARM64)
25#elif defined(__arm__) || defined(_M_ARM)
27#endif
28
29using namespace lldb;
30using namespace lldb_private;
31
33 HRESULT(WINAPI *)(HANDLE hThread, PWSTR *ppszThreadDescription);
34
36 const HostThread &thread)
37 : Thread(process, thread.GetNativeThread().GetThreadId()),
38 m_thread_reg_ctx_sp(), m_host_thread(thread) {}
39
41
45 GetRegisterContext()->InvalidateIfNeeded(false);
46}
47
49
51
55
56 return m_reg_context_sp;
57}
58
61 RegisterContextSP reg_ctx_sp;
62 uint32_t concrete_frame_idx = 0;
64
65 if (frame)
66 concrete_frame_idx = frame->GetConcreteFrameIndex();
67
68 if (concrete_frame_idx == 0) {
70 ArchSpec arch = HostInfo::GetArchitecture();
71 switch (arch.GetMachine()) {
72 case llvm::Triple::arm:
73 case llvm::Triple::thumb:
74#if defined(__arm__) || defined(_M_ARM)
76 new RegisterContextWindows_arm(*this, concrete_frame_idx));
77#else
78 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
79#endif
80 break;
81
82 case llvm::Triple::aarch64:
83#if defined(__aarch64__) || defined(_M_ARM64)
85 new RegisterContextWindows_arm64(*this, concrete_frame_idx));
86#else
87 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
88#endif
89 break;
90
91 case llvm::Triple::x86:
92#if defined(__i386__) || defined(_M_IX86)
94 new RegisterContextWindows_x86(*this, concrete_frame_idx));
95#else
96 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
97#endif
98 break;
99
100 case llvm::Triple::x86_64:
101#if defined(__x86_64__) || defined(_M_AMD64)
103 new RegisterContextWindows_x64(*this, concrete_frame_idx));
104#else
105 LLDB_LOG(log, "debugging foreign targets is currently unsupported");
106#endif
107 break;
108
109 default:
110 break;
111 }
112 }
113 reg_ctx_sp = m_thread_reg_ctx_sp;
114 } else {
115 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
116 }
117
118 return reg_ctx_sp;
119}
120
123 return true;
124}
125
127 StateType resume_state = GetTemporaryResumeState();
128 StateType current_state = GetState();
129 if (resume_state == current_state)
130 return Status();
131
132 if (resume_state == eStateStepping) {
133 Log *log = GetLog(LLDBLog::Thread);
134
135 uint32_t flags_index =
136 GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
138 uint64_t flags_value =
139 GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
140 ProcessSP process = GetProcess();
141 const ArchSpec &arch = process->GetTarget().GetArchitecture();
142 switch (arch.GetMachine()) {
143 case llvm::Triple::x86:
144 case llvm::Triple::x86_64:
145 flags_value |= 0x100; // Set the trap flag on the CPU
146 break;
147 case llvm::Triple::aarch64:
148 case llvm::Triple::arm:
149 case llvm::Triple::thumb:
150 flags_value |= 0x200000; // The SS bit in PState
151 break;
152 default:
153 LLDB_LOG(log, "single stepping unsupported on this architecture");
154 break;
155 }
156 GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
157 }
158
159 if (resume_state == eStateStepping || resume_state == eStateRunning) {
160 DWORD previous_suspend_count = 0;
161 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
162 do {
163 // ResumeThread returns -1 on error, or the thread's *previous* suspend
164 // count on success. This means that the return value is 1 when the thread
165 // was restarted. Note that DWORD is an unsigned int, so we need to
166 // explicitly compare with -1.
167 previous_suspend_count = ::ResumeThread(thread_handle);
168
169 if (previous_suspend_count == (DWORD)-1)
170 return Status(::GetLastError(), eErrorTypeWin32);
171
172 } while (previous_suspend_count > 1);
173 }
174
175 return Status();
176}
177
179 Log *log = GetLog(LLDBLog::Thread);
180 static GetThreadDescriptionFunctionPtr GetThreadDescription = []() {
181 HMODULE hModule = ::LoadLibraryW(L"Kernel32.dll");
182 return hModule ? reinterpret_cast<GetThreadDescriptionFunctionPtr>(
183 ::GetProcAddress(hModule, "GetThreadDescription"))
184 : nullptr;
185 }();
186 LLDB_LOGF(log, "GetProcAddress: %p",
187 reinterpret_cast<void *>(GetThreadDescription));
188 if (!GetThreadDescription)
189 return m_name.c_str();
190 PWSTR pszThreadName;
191 if (SUCCEEDED(GetThreadDescription(
192 m_host_thread.GetNativeThread().GetSystemHandle(), &pszThreadName))) {
193 LLDB_LOGF(log, "GetThreadDescription: %ls", pszThreadName);
194 llvm::convertUTF16ToUTF8String(
195 llvm::ArrayRef(reinterpret_cast<char *>(pszThreadName),
196 wcslen(pszThreadName) * sizeof(wchar_t)),
197 m_name);
198 ::LocalFree(pszThreadName);
199 }
200
201 return m_name.c_str();
202}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:342
#define LLDB_LOGF(log,...)
Definition: Log.h:349
HRESULT(WINAPI *)(HANDLE hThread, PWSTR *ppszThreadDescription) GetThreadDescriptionFunctionPtr
An architecture specification class.
Definition: ArchSpec.h:31
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition: ArchSpec.cpp:683
HostNativeThread & GetNativeThread()
Definition: HostThread.cpp:32
This base class provides an interface to stack frames.
Definition: StackFrame.h:42
uint32_t GetConcreteFrameIndex() const
Query this frame to find what frame it is in this Thread's StackFrameList, not counting inlined frame...
Definition: StackFrame.h:428
An error handling class.
Definition: Status.h:44
bool CalculateStopInfo() override
Ask the thread subclass to set its stop info.
TargetThreadWindows(ProcessWindows &process, const HostThread &thread)
lldb::RegisterContextSP GetRegisterContext() override
lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame) override
void WillResume(lldb::StateType resume_state) override
lldb::RegisterContextSP m_thread_reg_ctx_sp
void SetStopInfo(const lldb::StopInfoSP &stop_info_sp)
Definition: Thread.cpp:457
virtual void DestroyThread()
Definition: Thread.cpp:245
virtual Unwind & GetUnwinder()
Definition: Thread.cpp:1888
lldb::StateType GetTemporaryResumeState() const
Definition: Thread.h:1195
void SetState(lldb::StateType state)
Definition: Thread.cpp:565
lldb::ProcessSP GetProcess() const
Definition: Thread.h:154
lldb::StopInfoSP m_stop_info_sp
The private stop reason for this thread.
Definition: Thread.h:1303
lldb::StateType GetState() const
Definition: Thread.cpp:559
lldb::RegisterContextSP m_reg_context_sp
The register context for this thread's current register state.
Definition: Thread.h:1316
lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame)
Definition: Unwind.h:56
#define LLDB_REGNUM_GENERIC_FLAGS
Definition: lldb-defines.h:60
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:314
Definition: SBAddress.h:15
StateType
Process and Thread States.
@ eStateStopped
Process or thread is stopped and can be examined.
@ eStateRunning
Process or thread is running and can't be examined.
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
@ eErrorTypeWin32
Standard Win32 error codes.
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:381
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Definition: lldb-forward.h:386
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target