118a9135dSAdrian McCarthy //===-- TargetThreadWindows.cpp----------------------------------*- C++ -*-===// 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 23842f55f3SSaleem Abdulrasool // TODO support _M_ARM and _M_ARM64 24*2e25c44dSMartin Storsjo #if defined(__x86_64__) || defined(_M_AMD64) 2565abfb11SHafiz Abid Qadeer #include "x64/RegisterContextWindows_x64.h" 26*2e25c44dSMartin Storsjo #elif defined(__i386__) || defined(_M_IX86) 274ad5def9SAdrian McCarthy #include "x86/RegisterContextWindows_x86.h" 284ad5def9SAdrian McCarthy #endif 294ad5def9SAdrian McCarthy 3018a9135dSAdrian McCarthy using namespace lldb; 3118a9135dSAdrian McCarthy using namespace lldb_private; 3218a9135dSAdrian McCarthy 33b9c1b51eSKate Stone TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, 34b9c1b51eSKate Stone const HostThread &thread) 35b9c1b51eSKate Stone : Thread(process, thread.GetNativeThread().GetThreadId()), 3645d8134cSStella Stamenova m_thread_reg_ctx_sp(), m_host_thread(thread) {} 3718a9135dSAdrian McCarthy 38b9c1b51eSKate Stone TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } 3918a9135dSAdrian McCarthy 40b9c1b51eSKate Stone void TargetThreadWindows::RefreshStateAfterStop() { 4118a9135dSAdrian McCarthy ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); 4218a9135dSAdrian McCarthy SetState(eStateStopped); 4318a9135dSAdrian McCarthy GetRegisterContext()->InvalidateIfNeeded(false); 4418a9135dSAdrian McCarthy } 4518a9135dSAdrian McCarthy 46b9c1b51eSKate Stone void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} 4718a9135dSAdrian McCarthy 48b9c1b51eSKate Stone void TargetThreadWindows::DidStop() {} 4918a9135dSAdrian McCarthy 504ad5def9SAdrian McCarthy RegisterContextSP TargetThreadWindows::GetRegisterContext() { 514ad5def9SAdrian McCarthy if (!m_reg_context_sp) 5245d8134cSStella Stamenova m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 534ad5def9SAdrian McCarthy 544ad5def9SAdrian McCarthy return m_reg_context_sp; 554ad5def9SAdrian McCarthy } 564ad5def9SAdrian McCarthy 574ad5def9SAdrian McCarthy RegisterContextSP 584ad5def9SAdrian McCarthy TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { 5945d8134cSStella Stamenova RegisterContextSP reg_ctx_sp; 6045d8134cSStella Stamenova uint32_t concrete_frame_idx = 0; 6145d8134cSStella Stamenova Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 624ad5def9SAdrian McCarthy 6345d8134cSStella Stamenova if (frame) 6445d8134cSStella Stamenova concrete_frame_idx = frame->GetConcreteFrameIndex(); 6545d8134cSStella Stamenova 6645d8134cSStella Stamenova if (concrete_frame_idx == 0) { 6745d8134cSStella Stamenova if (!m_thread_reg_ctx_sp) { 684ad5def9SAdrian McCarthy ArchSpec arch = HostInfo::GetArchitecture(); 694ad5def9SAdrian McCarthy switch (arch.GetMachine()) { 70842f55f3SSaleem Abdulrasool case llvm::Triple::arm: 71842f55f3SSaleem Abdulrasool case llvm::Triple::thumb: 72842f55f3SSaleem Abdulrasool LLDB_LOG(log, "debugging ARM (NT) targets is currently unsupported"); 73842f55f3SSaleem Abdulrasool break; 74842f55f3SSaleem Abdulrasool 75842f55f3SSaleem Abdulrasool case llvm::Triple::aarch64: 76842f55f3SSaleem Abdulrasool LLDB_LOG(log, "debugging ARM64 targets is currently unsupported"); 77842f55f3SSaleem Abdulrasool break; 78842f55f3SSaleem Abdulrasool 794ad5def9SAdrian McCarthy case llvm::Triple::x86: 80*2e25c44dSMartin Storsjo #if defined(__i386__) || defined(_M_IX86) 8145d8134cSStella Stamenova m_thread_reg_ctx_sp.reset( 8245d8134cSStella Stamenova new RegisterContextWindows_x86(*this, concrete_frame_idx)); 83842f55f3SSaleem Abdulrasool #else 84842f55f3SSaleem Abdulrasool LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 854ad5def9SAdrian McCarthy #endif 864ad5def9SAdrian McCarthy break; 87842f55f3SSaleem Abdulrasool 884ad5def9SAdrian McCarthy case llvm::Triple::x86_64: 89*2e25c44dSMartin Storsjo #if defined(__x86_64__) || defined(_M_AMD64) 9045d8134cSStella Stamenova m_thread_reg_ctx_sp.reset( 9145d8134cSStella Stamenova new RegisterContextWindows_x64(*this, concrete_frame_idx)); 924ad5def9SAdrian McCarthy #else 93842f55f3SSaleem Abdulrasool LLDB_LOG(log, "debugging foreign targets is currently unsupported"); 944ad5def9SAdrian McCarthy #endif 95842f55f3SSaleem Abdulrasool break; 96842f55f3SSaleem Abdulrasool 974ad5def9SAdrian McCarthy default: 984ad5def9SAdrian McCarthy break; 994ad5def9SAdrian McCarthy } 1004ad5def9SAdrian McCarthy } 10145d8134cSStella Stamenova reg_ctx_sp = m_thread_reg_ctx_sp; 10245d8134cSStella Stamenova } else { 10345d8134cSStella Stamenova Unwind *unwinder = GetUnwinder(); 10445d8134cSStella Stamenova if (unwinder != nullptr) 10545d8134cSStella Stamenova reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); 10645d8134cSStella Stamenova } 10745d8134cSStella Stamenova 10845d8134cSStella Stamenova return reg_ctx_sp; 1094ad5def9SAdrian McCarthy } 1104ad5def9SAdrian McCarthy 111b9c1b51eSKate Stone bool TargetThreadWindows::CalculateStopInfo() { 11218a9135dSAdrian McCarthy SetStopInfo(m_stop_info_sp); 11318a9135dSAdrian McCarthy return true; 11418a9135dSAdrian McCarthy } 11518a9135dSAdrian McCarthy 116b9c1b51eSKate Stone Unwind *TargetThreadWindows::GetUnwinder() { 117b9c1b51eSKate Stone // FIXME: Implement an unwinder based on the Windows unwinder exposed through 118b9c1b51eSKate Stone // DIA SDK. 119d5b44036SJonas Devlieghere if (!m_unwinder_up) 120d5b44036SJonas Devlieghere m_unwinder_up.reset(new UnwindLLDB(*this)); 121d5b44036SJonas Devlieghere return m_unwinder_up.get(); 12218a9135dSAdrian McCarthy } 12318a9135dSAdrian McCarthy 1240fd67b53SStella Stamenova Status TargetThreadWindows::DoResume() { 12518a9135dSAdrian McCarthy StateType resume_state = GetTemporaryResumeState(); 12618a9135dSAdrian McCarthy StateType current_state = GetState(); 12718a9135dSAdrian McCarthy if (resume_state == current_state) 1280fd67b53SStella Stamenova return Status(); 12918a9135dSAdrian McCarthy 130b9c1b51eSKate Stone if (resume_state == eStateStepping) { 131b9c1b51eSKate Stone uint32_t flags_index = 132b9c1b51eSKate Stone GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 133b9c1b51eSKate Stone eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 134b9c1b51eSKate Stone uint64_t flags_value = 135b9c1b51eSKate Stone GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); 13618a9135dSAdrian McCarthy flags_value |= 0x100; // Set the trap flag on the CPU 13718a9135dSAdrian McCarthy GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); 13818a9135dSAdrian McCarthy } 13918a9135dSAdrian McCarthy 140b9c1b51eSKate Stone if (resume_state == eStateStepping || resume_state == eStateRunning) { 14118a9135dSAdrian McCarthy DWORD previous_suspend_count = 0; 14218a9135dSAdrian McCarthy HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 143b9c1b51eSKate Stone do { 14445d8134cSStella Stamenova // ResumeThread returns -1 on error, or the thread's *previous* suspend 14545d8134cSStella Stamenova // count on success. This means that the return value is 1 when the thread 14645d8134cSStella Stamenova // was restarted. Note that DWORD is an unsigned int, so we need to 14745d8134cSStella Stamenova // explicitly compare with -1. 14818a9135dSAdrian McCarthy previous_suspend_count = ::ResumeThread(thread_handle); 1490fd67b53SStella Stamenova 1500fd67b53SStella Stamenova if (previous_suspend_count == (DWORD)-1) 1510fd67b53SStella Stamenova return Status(::GetLastError(), eErrorTypeWin32); 1520fd67b53SStella Stamenova 1530fd67b53SStella Stamenova } while (previous_suspend_count > 1); 15418a9135dSAdrian McCarthy } 1550fd67b53SStella Stamenova 1560fd67b53SStella Stamenova return Status(); 15718a9135dSAdrian McCarthy } 158