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" 146f9e6901SZachary Turner #include "lldb/Utility/Log.h" 156f9e6901SZachary Turner #include "lldb/Utility/Logging.h" 16d821c997SPavel Labath #include "lldb/Utility/State.h" 1718a9135dSAdrian McCarthy 1818a9135dSAdrian McCarthy #include "ProcessWindows.h" 1918a9135dSAdrian McCarthy #include "ProcessWindowsLog.h" 20b9c1b51eSKate Stone #include "TargetThreadWindows.h" 2118a9135dSAdrian McCarthy 222e25c44dSMartin Storsjo #if defined(__x86_64__) || defined(_M_AMD64) 2365abfb11SHafiz Abid Qadeer #include "x64/RegisterContextWindows_x64.h" 242e25c44dSMartin Storsjo #elif defined(__i386__) || defined(_M_IX86) 254ad5def9SAdrian McCarthy #include "x86/RegisterContextWindows_x86.h" 26b1f6ba2aSMartin Storsjo #elif defined(__aarch64__) || defined(_M_ARM64) 27b1f6ba2aSMartin Storsjo #include "arm64/RegisterContextWindows_arm64.h" 28a59444a3SMartin Storsjo #elif defined(__arm__) || defined(_M_ARM) 29a59444a3SMartin Storsjo #include "arm/RegisterContextWindows_arm.h" 304ad5def9SAdrian McCarthy #endif 314ad5def9SAdrian McCarthy 3218a9135dSAdrian McCarthy using namespace lldb; 3318a9135dSAdrian McCarthy using namespace lldb_private; 3418a9135dSAdrian McCarthy 35b9c1b51eSKate Stone TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, 36b9c1b51eSKate Stone const HostThread &thread) 37b9c1b51eSKate Stone : Thread(process, thread.GetNativeThread().GetThreadId()), 3845d8134cSStella Stamenova m_thread_reg_ctx_sp(), m_host_thread(thread) {} 3918a9135dSAdrian McCarthy 40b9c1b51eSKate Stone TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } 4118a9135dSAdrian McCarthy 42b9c1b51eSKate Stone void TargetThreadWindows::RefreshStateAfterStop() { 4318a9135dSAdrian McCarthy ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); 4418a9135dSAdrian McCarthy SetState(eStateStopped); 4518a9135dSAdrian McCarthy GetRegisterContext()->InvalidateIfNeeded(false); 4618a9135dSAdrian McCarthy } 4718a9135dSAdrian McCarthy 48b9c1b51eSKate Stone void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} 4918a9135dSAdrian McCarthy 50b9c1b51eSKate Stone void TargetThreadWindows::DidStop() {} 5118a9135dSAdrian McCarthy 524ad5def9SAdrian McCarthy RegisterContextSP TargetThreadWindows::GetRegisterContext() { 534ad5def9SAdrian McCarthy if (!m_reg_context_sp) 5445d8134cSStella Stamenova m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 554ad5def9SAdrian McCarthy 564ad5def9SAdrian McCarthy return m_reg_context_sp; 574ad5def9SAdrian McCarthy } 584ad5def9SAdrian McCarthy 594ad5def9SAdrian McCarthy RegisterContextSP 604ad5def9SAdrian McCarthy TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { 6145d8134cSStella Stamenova RegisterContextSP reg_ctx_sp; 6245d8134cSStella Stamenova uint32_t concrete_frame_idx = 0; 6345d8134cSStella Stamenova Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 644ad5def9SAdrian McCarthy 6545d8134cSStella Stamenova if (frame) 6645d8134cSStella Stamenova concrete_frame_idx = frame->GetConcreteFrameIndex(); 6745d8134cSStella Stamenova 6845d8134cSStella Stamenova if (concrete_frame_idx == 0) { 6945d8134cSStella Stamenova if (!m_thread_reg_ctx_sp) { 704ad5def9SAdrian McCarthy ArchSpec arch = HostInfo::GetArchitecture(); 714ad5def9SAdrian McCarthy switch (arch.GetMachine()) { 72842f55f3SSaleem Abdulrasool case llvm::Triple::arm: 73842f55f3SSaleem Abdulrasool case llvm::Triple::thumb: 74a59444a3SMartin Storsjo #if defined(__arm__) || defined(_M_ARM) 75a59444a3SMartin Storsjo m_thread_reg_ctx_sp.reset( 76a59444a3SMartin Storsjo new RegisterContextWindows_arm(*this, concrete_frame_idx)); 77a59444a3SMartin Storsjo #else 78a59444a3SMartin Storsjo LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 79a59444a3SMartin Storsjo #endif 80842f55f3SSaleem Abdulrasool break; 81842f55f3SSaleem Abdulrasool 82842f55f3SSaleem Abdulrasool case llvm::Triple::aarch64: 83b1f6ba2aSMartin Storsjo #if defined(__aarch64__) || defined(_M_ARM64) 84b1f6ba2aSMartin Storsjo m_thread_reg_ctx_sp.reset( 85b1f6ba2aSMartin Storsjo new RegisterContextWindows_arm64(*this, concrete_frame_idx)); 86b1f6ba2aSMartin Storsjo #else 87b1f6ba2aSMartin Storsjo LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 88b1f6ba2aSMartin Storsjo #endif 89842f55f3SSaleem Abdulrasool break; 90842f55f3SSaleem Abdulrasool 914ad5def9SAdrian McCarthy case llvm::Triple::x86: 922e25c44dSMartin Storsjo #if defined(__i386__) || defined(_M_IX86) 9345d8134cSStella Stamenova m_thread_reg_ctx_sp.reset( 9445d8134cSStella Stamenova new RegisterContextWindows_x86(*this, concrete_frame_idx)); 95842f55f3SSaleem Abdulrasool #else 96842f55f3SSaleem Abdulrasool LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 974ad5def9SAdrian McCarthy #endif 984ad5def9SAdrian McCarthy break; 99842f55f3SSaleem Abdulrasool 1004ad5def9SAdrian McCarthy case llvm::Triple::x86_64: 1012e25c44dSMartin Storsjo #if defined(__x86_64__) || defined(_M_AMD64) 10245d8134cSStella Stamenova m_thread_reg_ctx_sp.reset( 10345d8134cSStella Stamenova new RegisterContextWindows_x64(*this, concrete_frame_idx)); 1044ad5def9SAdrian McCarthy #else 105842f55f3SSaleem Abdulrasool LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 1064ad5def9SAdrian McCarthy #endif 107842f55f3SSaleem Abdulrasool break; 108842f55f3SSaleem Abdulrasool 1094ad5def9SAdrian McCarthy default: 1104ad5def9SAdrian McCarthy break; 1114ad5def9SAdrian McCarthy } 1124ad5def9SAdrian McCarthy } 11345d8134cSStella Stamenova reg_ctx_sp = m_thread_reg_ctx_sp; 11445d8134cSStella Stamenova } else { 115*24b1831eSPavel Labath reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); 11645d8134cSStella Stamenova } 11745d8134cSStella Stamenova 11845d8134cSStella Stamenova return reg_ctx_sp; 1194ad5def9SAdrian McCarthy } 1204ad5def9SAdrian McCarthy 121b9c1b51eSKate Stone bool TargetThreadWindows::CalculateStopInfo() { 12218a9135dSAdrian McCarthy SetStopInfo(m_stop_info_sp); 12318a9135dSAdrian McCarthy return true; 12418a9135dSAdrian McCarthy } 12518a9135dSAdrian McCarthy 1260fd67b53SStella Stamenova Status TargetThreadWindows::DoResume() { 12718a9135dSAdrian McCarthy StateType resume_state = GetTemporaryResumeState(); 12818a9135dSAdrian McCarthy StateType current_state = GetState(); 12918a9135dSAdrian McCarthy if (resume_state == current_state) 1300fd67b53SStella Stamenova return Status(); 13118a9135dSAdrian McCarthy 132b9c1b51eSKate Stone if (resume_state == eStateStepping) { 133b9c1b51eSKate Stone uint32_t flags_index = 134b9c1b51eSKate Stone GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 135b9c1b51eSKate Stone eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 136b9c1b51eSKate Stone uint64_t flags_value = 137b9c1b51eSKate Stone GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); 13818a9135dSAdrian McCarthy flags_value |= 0x100; // Set the trap flag on the CPU 13918a9135dSAdrian McCarthy GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); 14018a9135dSAdrian McCarthy } 14118a9135dSAdrian McCarthy 142b9c1b51eSKate Stone if (resume_state == eStateStepping || resume_state == eStateRunning) { 14318a9135dSAdrian McCarthy DWORD previous_suspend_count = 0; 14418a9135dSAdrian McCarthy HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 145b9c1b51eSKate Stone do { 14645d8134cSStella Stamenova // ResumeThread returns -1 on error, or the thread's *previous* suspend 14745d8134cSStella Stamenova // count on success. This means that the return value is 1 when the thread 14845d8134cSStella Stamenova // was restarted. Note that DWORD is an unsigned int, so we need to 14945d8134cSStella Stamenova // explicitly compare with -1. 15018a9135dSAdrian McCarthy previous_suspend_count = ::ResumeThread(thread_handle); 1510fd67b53SStella Stamenova 1520fd67b53SStella Stamenova if (previous_suspend_count == (DWORD)-1) 1530fd67b53SStella Stamenova return Status(::GetLastError(), eErrorTypeWin32); 1540fd67b53SStella Stamenova 1550fd67b53SStella Stamenova } while (previous_suspend_count > 1); 15618a9135dSAdrian McCarthy } 1570fd67b53SStella Stamenova 1580fd67b53SStella Stamenova return Status(); 15918a9135dSAdrian McCarthy } 160