180814287SRaphael Isemann //===-- TargetThreadWindows.cpp--------------------------------------------===//
218a9135dSAdrian McCarthy //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
618a9135dSAdrian McCarthy //
718a9135dSAdrian McCarthy //===----------------------------------------------------------------------===//
818a9135dSAdrian McCarthy 
918a9135dSAdrian McCarthy #include "lldb/Host/HostInfo.h"
1018a9135dSAdrian McCarthy #include "lldb/Host/HostNativeThreadBase.h"
1118a9135dSAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h"
1218a9135dSAdrian McCarthy #include "lldb/Host/windows/windows.h"
1318a9135dSAdrian McCarthy #include "lldb/Target/RegisterContext.h"
1434d7143bSPavel Labath #include "lldb/Target/Unwind.h"
15*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
166f9e6901SZachary Turner #include "lldb/Utility/Log.h"
17d821c997SPavel Labath #include "lldb/Utility/State.h"
1818a9135dSAdrian McCarthy 
1918a9135dSAdrian McCarthy #include "ProcessWindows.h"
2018a9135dSAdrian McCarthy #include "ProcessWindowsLog.h"
21b9c1b51eSKate Stone #include "TargetThreadWindows.h"
2218a9135dSAdrian McCarthy 
232e25c44dSMartin Storsjo #if defined(__x86_64__) || defined(_M_AMD64)
2465abfb11SHafiz Abid Qadeer #include "x64/RegisterContextWindows_x64.h"
252e25c44dSMartin Storsjo #elif defined(__i386__) || defined(_M_IX86)
264ad5def9SAdrian McCarthy #include "x86/RegisterContextWindows_x86.h"
27b1f6ba2aSMartin Storsjo #elif defined(__aarch64__) || defined(_M_ARM64)
28b1f6ba2aSMartin Storsjo #include "arm64/RegisterContextWindows_arm64.h"
29a59444a3SMartin Storsjo #elif defined(__arm__) || defined(_M_ARM)
30a59444a3SMartin Storsjo #include "arm/RegisterContextWindows_arm.h"
314ad5def9SAdrian McCarthy #endif
324ad5def9SAdrian McCarthy 
3318a9135dSAdrian McCarthy using namespace lldb;
3418a9135dSAdrian McCarthy using namespace lldb_private;
3518a9135dSAdrian McCarthy 
TargetThreadWindows(ProcessWindows & process,const HostThread & thread)36b9c1b51eSKate Stone TargetThreadWindows::TargetThreadWindows(ProcessWindows &process,
37b9c1b51eSKate Stone                                          const HostThread &thread)
38b9c1b51eSKate Stone     : Thread(process, thread.GetNativeThread().GetThreadId()),
3945d8134cSStella Stamenova       m_thread_reg_ctx_sp(), m_host_thread(thread) {}
4018a9135dSAdrian McCarthy 
~TargetThreadWindows()41b9c1b51eSKate Stone TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); }
4218a9135dSAdrian McCarthy 
RefreshStateAfterStop()43b9c1b51eSKate Stone void TargetThreadWindows::RefreshStateAfterStop() {
4418a9135dSAdrian McCarthy   ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
4518a9135dSAdrian McCarthy   SetState(eStateStopped);
4618a9135dSAdrian McCarthy   GetRegisterContext()->InvalidateIfNeeded(false);
4718a9135dSAdrian McCarthy }
4818a9135dSAdrian McCarthy 
WillResume(lldb::StateType resume_state)49b9c1b51eSKate Stone void TargetThreadWindows::WillResume(lldb::StateType resume_state) {}
5018a9135dSAdrian McCarthy 
DidStop()51b9c1b51eSKate Stone void TargetThreadWindows::DidStop() {}
5218a9135dSAdrian McCarthy 
GetRegisterContext()534ad5def9SAdrian McCarthy RegisterContextSP TargetThreadWindows::GetRegisterContext() {
544ad5def9SAdrian McCarthy   if (!m_reg_context_sp)
5545d8134cSStella Stamenova     m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
564ad5def9SAdrian McCarthy 
574ad5def9SAdrian McCarthy   return m_reg_context_sp;
584ad5def9SAdrian McCarthy }
594ad5def9SAdrian McCarthy 
604ad5def9SAdrian McCarthy RegisterContextSP
CreateRegisterContextForFrame(StackFrame * frame)614ad5def9SAdrian McCarthy TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) {
6245d8134cSStella Stamenova   RegisterContextSP reg_ctx_sp;
6345d8134cSStella Stamenova   uint32_t concrete_frame_idx = 0;
64a007a6d8SPavel Labath   Log *log = GetLog(LLDBLog::Thread);
654ad5def9SAdrian McCarthy 
6645d8134cSStella Stamenova   if (frame)
6745d8134cSStella Stamenova     concrete_frame_idx = frame->GetConcreteFrameIndex();
6845d8134cSStella Stamenova 
6945d8134cSStella Stamenova   if (concrete_frame_idx == 0) {
7045d8134cSStella Stamenova     if (!m_thread_reg_ctx_sp) {
714ad5def9SAdrian McCarthy       ArchSpec arch = HostInfo::GetArchitecture();
724ad5def9SAdrian McCarthy       switch (arch.GetMachine()) {
73842f55f3SSaleem Abdulrasool       case llvm::Triple::arm:
74842f55f3SSaleem Abdulrasool       case llvm::Triple::thumb:
75a59444a3SMartin Storsjo #if defined(__arm__) || defined(_M_ARM)
76a59444a3SMartin Storsjo         m_thread_reg_ctx_sp.reset(
77a59444a3SMartin Storsjo             new RegisterContextWindows_arm(*this, concrete_frame_idx));
78a59444a3SMartin Storsjo #else
79a59444a3SMartin Storsjo         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
80a59444a3SMartin Storsjo #endif
81842f55f3SSaleem Abdulrasool         break;
82842f55f3SSaleem Abdulrasool 
83842f55f3SSaleem Abdulrasool       case llvm::Triple::aarch64:
84b1f6ba2aSMartin Storsjo #if defined(__aarch64__) || defined(_M_ARM64)
85b1f6ba2aSMartin Storsjo         m_thread_reg_ctx_sp.reset(
86b1f6ba2aSMartin Storsjo             new RegisterContextWindows_arm64(*this, concrete_frame_idx));
87b1f6ba2aSMartin Storsjo #else
88b1f6ba2aSMartin Storsjo         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
89b1f6ba2aSMartin Storsjo #endif
90842f55f3SSaleem Abdulrasool         break;
91842f55f3SSaleem Abdulrasool 
924ad5def9SAdrian McCarthy       case llvm::Triple::x86:
932e25c44dSMartin Storsjo #if defined(__i386__) || defined(_M_IX86)
9445d8134cSStella Stamenova         m_thread_reg_ctx_sp.reset(
9545d8134cSStella Stamenova             new RegisterContextWindows_x86(*this, concrete_frame_idx));
96842f55f3SSaleem Abdulrasool #else
97842f55f3SSaleem Abdulrasool         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
984ad5def9SAdrian McCarthy #endif
994ad5def9SAdrian McCarthy         break;
100842f55f3SSaleem Abdulrasool 
1014ad5def9SAdrian McCarthy       case llvm::Triple::x86_64:
1022e25c44dSMartin Storsjo #if defined(__x86_64__) || defined(_M_AMD64)
10345d8134cSStella Stamenova         m_thread_reg_ctx_sp.reset(
10445d8134cSStella Stamenova             new RegisterContextWindows_x64(*this, concrete_frame_idx));
1054ad5def9SAdrian McCarthy #else
106842f55f3SSaleem Abdulrasool         LLDB_LOG(log, "debugging foreign targets is currently unsupported");
1074ad5def9SAdrian McCarthy #endif
108842f55f3SSaleem Abdulrasool         break;
109842f55f3SSaleem Abdulrasool 
1104ad5def9SAdrian McCarthy       default:
1114ad5def9SAdrian McCarthy         break;
1124ad5def9SAdrian McCarthy       }
1134ad5def9SAdrian McCarthy     }
11445d8134cSStella Stamenova     reg_ctx_sp = m_thread_reg_ctx_sp;
11545d8134cSStella Stamenova   } else {
11624b1831eSPavel Labath     reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame);
11745d8134cSStella Stamenova   }
11845d8134cSStella Stamenova 
11945d8134cSStella Stamenova   return reg_ctx_sp;
1204ad5def9SAdrian McCarthy }
1214ad5def9SAdrian McCarthy 
CalculateStopInfo()122b9c1b51eSKate Stone bool TargetThreadWindows::CalculateStopInfo() {
12318a9135dSAdrian McCarthy   SetStopInfo(m_stop_info_sp);
12418a9135dSAdrian McCarthy   return true;
12518a9135dSAdrian McCarthy }
12618a9135dSAdrian McCarthy 
DoResume()1270fd67b53SStella Stamenova Status TargetThreadWindows::DoResume() {
12818a9135dSAdrian McCarthy   StateType resume_state = GetTemporaryResumeState();
12918a9135dSAdrian McCarthy   StateType current_state = GetState();
13018a9135dSAdrian McCarthy   if (resume_state == current_state)
1310fd67b53SStella Stamenova     return Status();
13218a9135dSAdrian McCarthy 
133b9c1b51eSKate Stone   if (resume_state == eStateStepping) {
134a007a6d8SPavel Labath     Log *log = GetLog(LLDBLog::Thread);
1359f34f75fSMartin Storsjö 
136b9c1b51eSKate Stone     uint32_t flags_index =
137b9c1b51eSKate Stone         GetRegisterContext()->ConvertRegisterKindToRegisterNumber(
138b9c1b51eSKate Stone             eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
139b9c1b51eSKate Stone     uint64_t flags_value =
140b9c1b51eSKate Stone         GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
1419f34f75fSMartin Storsjö     ProcessSP process = GetProcess();
1429f34f75fSMartin Storsjö     const ArchSpec &arch = process->GetTarget().GetArchitecture();
1439f34f75fSMartin Storsjö     switch (arch.GetMachine()) {
1449f34f75fSMartin Storsjö     case llvm::Triple::x86:
1459f34f75fSMartin Storsjö     case llvm::Triple::x86_64:
14618a9135dSAdrian McCarthy       flags_value |= 0x100; // Set the trap flag on the CPU
1479f34f75fSMartin Storsjö       break;
1489f34f75fSMartin Storsjö     case llvm::Triple::aarch64:
1499f34f75fSMartin Storsjö     case llvm::Triple::arm:
1509f34f75fSMartin Storsjö     case llvm::Triple::thumb:
1519f34f75fSMartin Storsjö       flags_value |= 0x200000; // The SS bit in PState
1529f34f75fSMartin Storsjö       break;
1539f34f75fSMartin Storsjö     default:
1549f34f75fSMartin Storsjö       LLDB_LOG(log, "single stepping unsupported on this architecture");
1559f34f75fSMartin Storsjö       break;
1569f34f75fSMartin Storsjö     }
15718a9135dSAdrian McCarthy     GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
15818a9135dSAdrian McCarthy   }
15918a9135dSAdrian McCarthy 
160b9c1b51eSKate Stone   if (resume_state == eStateStepping || resume_state == eStateRunning) {
16118a9135dSAdrian McCarthy     DWORD previous_suspend_count = 0;
16218a9135dSAdrian McCarthy     HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
163b9c1b51eSKate Stone     do {
16445d8134cSStella Stamenova       // ResumeThread returns -1 on error, or the thread's *previous* suspend
16545d8134cSStella Stamenova       // count on success. This means that the return value is 1 when the thread
16645d8134cSStella Stamenova       // was restarted. Note that DWORD is an unsigned int, so we need to
16745d8134cSStella Stamenova       // explicitly compare with -1.
16818a9135dSAdrian McCarthy       previous_suspend_count = ::ResumeThread(thread_handle);
1690fd67b53SStella Stamenova 
1700fd67b53SStella Stamenova       if (previous_suspend_count == (DWORD)-1)
1710fd67b53SStella Stamenova         return Status(::GetLastError(), eErrorTypeWin32);
1720fd67b53SStella Stamenova 
1730fd67b53SStella Stamenova     } while (previous_suspend_count > 1);
17418a9135dSAdrian McCarthy   }
1750fd67b53SStella Stamenova 
1760fd67b53SStella Stamenova   return Status();
17718a9135dSAdrian McCarthy }
178