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" 156f9e6901SZachary Turner #include "lldb/Utility/Log.h" 166f9e6901SZachary Turner #include "lldb/Utility/Logging.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 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 41b9c1b51eSKate Stone TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } 4218a9135dSAdrian McCarthy 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 49b9c1b51eSKate Stone void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} 5018a9135dSAdrian McCarthy 51b9c1b51eSKate Stone void TargetThreadWindows::DidStop() {} 5218a9135dSAdrian McCarthy 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 614ad5def9SAdrian McCarthy TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { 6245d8134cSStella Stamenova RegisterContextSP reg_ctx_sp; 6345d8134cSStella Stamenova uint32_t concrete_frame_idx = 0; 64*a007a6d8SPavel 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 122b9c1b51eSKate Stone bool TargetThreadWindows::CalculateStopInfo() { 12318a9135dSAdrian McCarthy SetStopInfo(m_stop_info_sp); 12418a9135dSAdrian McCarthy return true; 12518a9135dSAdrian McCarthy } 12618a9135dSAdrian McCarthy 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) { 134*a007a6d8SPavel 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