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
11#include "lldb/Target/Unwind.h"
13#include "lldb/Utility/Log.h"
14
15#include "ProcessWindows.h"
16#include "TargetThreadWindows.h"
18#include <llvm/Support/ConvertUTF.h>
19
20#if defined(__x86_64__) || defined(_M_AMD64)
22#elif defined(__i386__) || defined(_M_IX86)
24#elif defined(__aarch64__) || defined(_M_ARM64)
26#elif defined(__arm__) || defined(_M_ARM)
28#endif
29
30using namespace lldb;
31using namespace lldb_private;
32
34 const HostThread &thread)
35 : Thread(process, thread.GetNativeThread().GetThreadId()),
36 m_host_thread(thread) {}
37
39
41 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
42 GetRegisterContext()->InvalidateIfNeeded(false);
43}
44
46
48 return m_host_thread.GetNativeThread().GetExtendedInfo();
49}
50
52
59
62 RegisterContextSP reg_ctx_sp;
63 uint32_t concrete_frame_idx = 0;
65
66 if (frame)
67 concrete_frame_idx = frame->GetConcreteFrameIndex();
68
69 if (concrete_frame_idx == 0) {
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)
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)
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)
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)
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
126
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 Log *log = GetLog(LLDBLog::Thread);
135
136 uint32_t flags_index =
137 GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
139 uint64_t flags_value =
140 GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
141 ProcessSP process = GetProcess();
142 const ArchSpec &arch = process->GetTarget().GetArchitecture();
143 switch (arch.GetMachine()) {
144 case llvm::Triple::x86:
145 case llvm::Triple::x86_64:
146 flags_value |= 0x100; // Set the trap flag on the CPU
147 break;
148 case llvm::Triple::aarch64:
149 case llvm::Triple::arm:
150 case llvm::Triple::thumb:
151 flags_value |= 0x200000; // The SS bit in PState
152 break;
153 default:
154 LLDB_LOG(log, "single stepping unsupported on this architecture");
155 break;
156 }
157 GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
158 }
159
160 if (resume_state == eStateStepping || resume_state == eStateRunning) {
161 DWORD previous_suspend_count = 0;
162 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
163 do {
164 // ResumeThread returns -1 on error, or the thread's *previous* suspend
165 // count on success. This means that the return value is 1 when the thread
166 // was restarted. Note that DWORD is an unsigned int, so we need to
167 // explicitly compare with -1.
168 previous_suspend_count = ::ResumeThread(thread_handle);
169
170 if (previous_suspend_count == static_cast<DWORD>(-1))
171 return Status(::GetLastError(), eErrorTypeWin32);
172
173 } while (previous_suspend_count > 1);
174 }
175
176 return Status();
177}
178
180 Log *log = GetLog(LLDBLog::Thread);
181 static LazyImport<HRESULT(WINAPI *)(HANDLE, PWSTR *)>
182 s_get_thread_description{L"Kernel32.dll", "GetThreadDescription"};
183 if (!s_get_thread_description)
184 return m_name.c_str();
185 auto GetThreadDescription = *s_get_thread_description;
186
187 PWSTR pszThreadName;
188 if (SUCCEEDED(GetThreadDescription(
189 m_host_thread.GetNativeThread().GetSystemHandle(), &pszThreadName))) {
190 LLDB_LOGF(log, "GetThreadDescription: %ls", pszThreadName);
191 m_name.clear();
192 llvm::convertUTF16ToUTF8String(
193 llvm::ArrayRef(reinterpret_cast<char *>(pszThreadName),
194 wcslen(pszThreadName) * sizeof(wchar_t)),
195 m_name);
196 ::LocalFree(pszThreadName);
197 }
198
199 return m_name.c_str();
200}
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOGF(log,...)
Definition Log.h:389
void * HANDLE
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition ArchSpec.cpp:883
virtual uint32_t GetConcreteFrameIndex()
Query this frame to find what frame it is in this Thread's StackFrameList, not counting inlined frame...
Definition StackFrame.h:492
An error handling class.
Definition Status.h:118
std::shared_ptr< Object > ObjectSP
bool CalculateStopInfo() override
Ask the thread subclass to set its stop info.
TargetThreadWindows(ProcessWindows &process, const HostThread &thread)
lldb_private::StructuredData::ObjectSP FetchThreadExtendedInfo() override
Exposes this thread's TEB address under the "teb_address" key, so that language runtimes can resolve ...
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:479
virtual void DestroyThread()
Definition Thread.cpp:259
virtual Unwind & GetUnwinder()
Definition Thread.cpp:2259
Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id=false)
Constructor.
Definition Thread.cpp:226
lldb::StateType GetTemporaryResumeState() const
Definition Thread.h:1269
lldb::ProcessSP GetProcess() const
Definition Thread.h:162
friend class StackFrame
Definition Thread.h:1371
lldb::StopInfoSP m_stop_info_sp
The private stop reason for this thread.
Definition Thread.h:1420
lldb::StateType GetState() const
Definition Thread.cpp:583
lldb::RegisterContextSP m_reg_context_sp
The register context for this thread's current register state.
Definition Thread.h:1436
lldb::RegisterContextSP CreateRegisterContextForFrame(StackFrame *frame)
Definition Unwind.h:56
#define LLDB_REGNUM_GENERIC_FLAGS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
StateType
Process and Thread States.
@ 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
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target