xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- TargetThreadWindows.cpp--------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Host/HostInfo.h"
10061da546Spatrick #include "lldb/Host/HostNativeThreadBase.h"
11061da546Spatrick #include "lldb/Host/windows/HostThreadWindows.h"
12061da546Spatrick #include "lldb/Host/windows/windows.h"
13061da546Spatrick #include "lldb/Target/RegisterContext.h"
14dda28197Spatrick #include "lldb/Target/Unwind.h"
15*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
16061da546Spatrick #include "lldb/Utility/Log.h"
17061da546Spatrick #include "lldb/Utility/State.h"
18061da546Spatrick 
19061da546Spatrick #include "ProcessWindows.h"
20061da546Spatrick #include "ProcessWindowsLog.h"
21061da546Spatrick #include "TargetThreadWindows.h"
22061da546Spatrick 
23061da546Spatrick #if defined(__x86_64__) || defined(_M_AMD64)
24061da546Spatrick #include "x64/RegisterContextWindows_x64.h"
25061da546Spatrick #elif defined(__i386__) || defined(_M_IX86)
26061da546Spatrick #include "x86/RegisterContextWindows_x86.h"
27061da546Spatrick #elif defined(__aarch64__) || defined(_M_ARM64)
28061da546Spatrick #include "arm64/RegisterContextWindows_arm64.h"
29061da546Spatrick #elif defined(__arm__) || defined(_M_ARM)
30061da546Spatrick #include "arm/RegisterContextWindows_arm.h"
31061da546Spatrick #endif
32061da546Spatrick 
33061da546Spatrick using namespace lldb;
34061da546Spatrick using namespace lldb_private;
35061da546Spatrick 
TargetThreadWindows(ProcessWindows & process,const HostThread & thread)36061da546Spatrick TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
37061da546Spatrick                                          const HostThread &thread)
38061da546Spatrick     : Thread(process, thread.GetNativeThread().GetThreadId()),
39061da546Spatrick       m_thread_reg_ctx_sp(), m_host_thread(thread) {}
40061da546Spatrick 
~TargetThreadWindows()41061da546Spatrick TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
42061da546Spatrick 
RefreshStateAfterStop()43061da546Spatrick void TargetThreadWindows::RefreshStateAfterStop() {
44061da546Spatrick   ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
45061da546Spatrick   SetState(eStateStopped);
46061da546Spatrick   GetRegisterContext()->InvalidateIfNeeded(false);
47061da546Spatrick }
48061da546Spatrick 
WillResume(lldb::StateType resume_state)49061da546Spatrick void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
50061da546Spatrick 
DidStop()51061da546Spatrick void TargetThreadWindows::DidStop() {}
52061da546Spatrick 
GetRegisterContext()53061da546Spatrick RegisterContextSP TargetThreadWindows::GetRegisterContext() {
54061da546Spatrick   if (!m_reg_context_sp)
55061da546Spatrick     m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
56061da546Spatrick 
57061da546Spatrick   return m_reg_context_sp;
58061da546Spatrick }
59061da546Spatrick 
60061da546Spatrick RegisterContextSP
CreateRegisterContextForFrame(StackFrame * frame)61061da546Spatrick TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
62061da546Spatrick   RegisterContextSP reg_ctx_sp;
63061da546Spatrick   uint32_t concrete_frame_idx = 0;
64*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Thread);
65061da546Spatrick 
66061da546Spatrick   if (frame)
67061da546Spatrick     concrete_frame_idx = frame->GetConcreteFrameIndex();
68061da546Spatrick 
69061da546Spatrick   if (concrete_frame_idx == 0) {
70061da546Spatrick     if (!m_thread_reg_ctx_sp) {
71061da546Spatrick       ArchSpec arch = HostInfo::GetArchitecture();
72061da546Spatrick       switch (arch.GetMachine()) {
73061da546Spatrick       case llvm::Triple::arm:
74061da546Spatrick       case llvm::Triple::thumb:
75061da546Spatrick #if defined(__arm__) || defined(_M_ARM)
76061da546Spatrick         m_thread_reg_ctx_sp.reset(
77061da546Spatrick             new RegisterContextWindows_arm(*this, concrete_frame_idx));
78061da546Spatrick #else
79061da546Spatrick         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
80061da546Spatrick #endif
81061da546Spatrick         break;
82061da546Spatrick 
83061da546Spatrick       case llvm::Triple::aarch64:
84061da546Spatrick #if defined(__aarch64__) || defined(_M_ARM64)
85061da546Spatrick         m_thread_reg_ctx_sp.reset(
86061da546Spatrick             new RegisterContextWindows_arm64(*this, concrete_frame_idx));
87061da546Spatrick #else
88061da546Spatrick         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
89061da546Spatrick #endif
90061da546Spatrick         break;
91061da546Spatrick 
92061da546Spatrick       case llvm::Triple::x86:
93061da546Spatrick #if defined(__i386__) || defined(_M_IX86)
94061da546Spatrick         m_thread_reg_ctx_sp.reset(
95061da546Spatrick             new RegisterContextWindows_x86(*this, concrete_frame_idx));
96061da546Spatrick #else
97061da546Spatrick         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
98061da546Spatrick #endif
99061da546Spatrick         break;
100061da546Spatrick 
101061da546Spatrick       case llvm::Triple::x86_64:
102061da546Spatrick #if defined(__x86_64__) || defined(_M_AMD64)
103061da546Spatrick         m_thread_reg_ctx_sp.reset(
104061da546Spatrick             new RegisterContextWindows_x64(*this, concrete_frame_idx));
105061da546Spatrick #else
106061da546Spatrick         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
107061da546Spatrick #endif
108061da546Spatrick         break;
109061da546Spatrick 
110061da546Spatrick       default:
111061da546Spatrick         break;
112061da546Spatrick       }
113061da546Spatrick     }
114061da546Spatrick     reg_ctx_sp = m_thread_reg_ctx_sp;
115061da546Spatrick   } else {
116dda28197Spatrick     reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
117061da546Spatrick   }
118061da546Spatrick 
119061da546Spatrick   return reg_ctx_sp;
120061da546Spatrick }
121061da546Spatrick 
CalculateStopInfo()122061da546Spatrick bool TargetThreadWindows::CalculateStopInfo() {
123061da546Spatrick   SetStopInfo(m_stop_info_sp);
124061da546Spatrick   return true;
125061da546Spatrick }
126061da546Spatrick 
DoResume()127061da546Spatrick Status TargetThreadWindows::DoResume() {
128061da546Spatrick   StateType resume_state = GetTemporaryResumeState();
129061da546Spatrick   StateType current_state = GetState();
130061da546Spatrick   if (resume_state == current_state)
131061da546Spatrick     return Status();
132061da546Spatrick 
133061da546Spatrick   if (resume_state == eStateStepping) {
134*f6aab3d8Srobert     Log *log = GetLog(LLDBLog::Thread);
135*f6aab3d8Srobert 
136061da546Spatrick     uint32_t flags_index =
137061da546Spatrick         GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
138061da546Spatrick             eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
139061da546Spatrick     uint64_t flags_value =
140061da546Spatrick         GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
141*f6aab3d8Srobert     ProcessSP process = GetProcess();
142*f6aab3d8Srobert     const ArchSpec &arch = process->GetTarget().GetArchitecture();
143*f6aab3d8Srobert     switch (arch.GetMachine()) {
144*f6aab3d8Srobert     case llvm::Triple::x86:
145*f6aab3d8Srobert     case llvm::Triple::x86_64:
146061da546Spatrick       flags_value |= 0x100; // Set the trap flag on the CPU
147*f6aab3d8Srobert       break;
148*f6aab3d8Srobert     case llvm::Triple::aarch64:
149*f6aab3d8Srobert     case llvm::Triple::arm:
150*f6aab3d8Srobert     case llvm::Triple::thumb:
151*f6aab3d8Srobert       flags_value |= 0x200000; // The SS bit in PState
152*f6aab3d8Srobert       break;
153*f6aab3d8Srobert     default:
154*f6aab3d8Srobert       LLDB_LOG(log, "single stepping unsupported on this architecture");
155*f6aab3d8Srobert       break;
156*f6aab3d8Srobert     }
157061da546Spatrick     GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
158061da546Spatrick   }
159061da546Spatrick 
160061da546Spatrick   if (resume_state == eStateStepping || resume_state == eStateRunning) {
161061da546Spatrick     DWORD previous_suspend_count = 0;
162061da546Spatrick     HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
163061da546Spatrick     do {
164061da546Spatrick       // ResumeThread returns -1 on error, or the thread's *previous* suspend
165061da546Spatrick       // count on success. This means that the return value is 1 when the thread
166061da546Spatrick       // was restarted. Note that DWORD is an unsigned int, so we need to
167061da546Spatrick       // explicitly compare with -1.
168061da546Spatrick       previous_suspend_count = ::ResumeThread(thread_handle);
169061da546Spatrick 
170061da546Spatrick       if (previous_suspend_count == (DWORD)-1)
171061da546Spatrick         return Status(::GetLastError(), eErrorTypeWin32);
172061da546Spatrick 
173061da546Spatrick     } while (previous_suspend_count > 1);
174061da546Spatrick   }
175061da546Spatrick 
176061da546Spatrick   return Status();
177061da546Spatrick }
178