1*80814287SRaphael 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 1845d8134cSStella Stamenova #include "Plugins/Process/Utility/UnwindLLDB.h" 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; 6445d8134cSStella Stamenova Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_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 { 11645d8134cSStella Stamenova Unwind *unwinder = GetUnwinder(); 11745d8134cSStella Stamenova if (unwinder != nullptr) 11845d8134cSStella Stamenova reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); 11945d8134cSStella Stamenova } 12045d8134cSStella Stamenova 12145d8134cSStella Stamenova return reg_ctx_sp; 1224ad5def9SAdrian McCarthy } 1234ad5def9SAdrian McCarthy 124b9c1b51eSKate Stone bool TargetThreadWindows::CalculateStopInfo() { 12518a9135dSAdrian McCarthy SetStopInfo(m_stop_info_sp); 12618a9135dSAdrian McCarthy return true; 12718a9135dSAdrian McCarthy } 12818a9135dSAdrian McCarthy 129b9c1b51eSKate Stone Unwind *TargetThreadWindows::GetUnwinder() { 130b9c1b51eSKate Stone // FIXME: Implement an unwinder based on the Windows unwinder exposed through 131b9c1b51eSKate Stone // DIA SDK. 132d5b44036SJonas Devlieghere if (!m_unwinder_up) 133d5b44036SJonas Devlieghere m_unwinder_up.reset(new UnwindLLDB(*this)); 134d5b44036SJonas Devlieghere return m_unwinder_up.get(); 13518a9135dSAdrian McCarthy } 13618a9135dSAdrian McCarthy 1370fd67b53SStella Stamenova Status TargetThreadWindows::DoResume() { 13818a9135dSAdrian McCarthy StateType resume_state = GetTemporaryResumeState(); 13918a9135dSAdrian McCarthy StateType current_state = GetState(); 14018a9135dSAdrian McCarthy if (resume_state == current_state) 1410fd67b53SStella Stamenova return Status(); 14218a9135dSAdrian McCarthy 143b9c1b51eSKate Stone if (resume_state == eStateStepping) { 144b9c1b51eSKate Stone uint32_t flags_index = 145b9c1b51eSKate Stone GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 146b9c1b51eSKate Stone eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 147b9c1b51eSKate Stone uint64_t flags_value = 148b9c1b51eSKate Stone GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); 14918a9135dSAdrian McCarthy flags_value |= 0x100; // Set the trap flag on the CPU 15018a9135dSAdrian McCarthy GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); 15118a9135dSAdrian McCarthy } 15218a9135dSAdrian McCarthy 153b9c1b51eSKate Stone if (resume_state == eStateStepping || resume_state == eStateRunning) { 15418a9135dSAdrian McCarthy DWORD previous_suspend_count = 0; 15518a9135dSAdrian McCarthy HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 156b9c1b51eSKate Stone do { 15745d8134cSStella Stamenova // ResumeThread returns -1 on error, or the thread's *previous* suspend 15845d8134cSStella Stamenova // count on success. This means that the return value is 1 when the thread 15945d8134cSStella Stamenova // was restarted. Note that DWORD is an unsigned int, so we need to 16045d8134cSStella Stamenova // explicitly compare with -1. 16118a9135dSAdrian McCarthy previous_suspend_count = ::ResumeThread(thread_handle); 1620fd67b53SStella Stamenova 1630fd67b53SStella Stamenova if (previous_suspend_count == (DWORD)-1) 1640fd67b53SStella Stamenova return Status(::GetLastError(), eErrorTypeWin32); 1650fd67b53SStella Stamenova 1660fd67b53SStella Stamenova } while (previous_suspend_count > 1); 16718a9135dSAdrian McCarthy } 1680fd67b53SStella Stamenova 1690fd67b53SStella Stamenova return Status(); 17018a9135dSAdrian McCarthy } 171