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 234ad5def9SAdrian McCarthy #if defined(_WIN64) 2465abfb11SHafiz Abid Qadeer #include "x64/RegisterContextWindows_x64.h" 254ad5def9SAdrian McCarthy #else 264ad5def9SAdrian McCarthy #include "x86/RegisterContextWindows_x86.h" 274ad5def9SAdrian McCarthy #endif 284ad5def9SAdrian McCarthy 2918a9135dSAdrian McCarthy using namespace lldb; 3018a9135dSAdrian McCarthy using namespace lldb_private; 3118a9135dSAdrian McCarthy 32b9c1b51eSKate Stone TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, 33b9c1b51eSKate Stone const HostThread &thread) 34b9c1b51eSKate Stone : Thread(process, thread.GetNativeThread().GetThreadId()), 3545d8134cSStella Stamenova m_thread_reg_ctx_sp(), m_host_thread(thread) {} 3618a9135dSAdrian McCarthy 37b9c1b51eSKate Stone TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } 3818a9135dSAdrian McCarthy 39b9c1b51eSKate Stone void TargetThreadWindows::RefreshStateAfterStop() { 4018a9135dSAdrian McCarthy ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); 4118a9135dSAdrian McCarthy SetState(eStateStopped); 4218a9135dSAdrian McCarthy GetRegisterContext()->InvalidateIfNeeded(false); 4318a9135dSAdrian McCarthy } 4418a9135dSAdrian McCarthy 45b9c1b51eSKate Stone void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} 4618a9135dSAdrian McCarthy 47b9c1b51eSKate Stone void TargetThreadWindows::DidStop() {} 4818a9135dSAdrian McCarthy 494ad5def9SAdrian McCarthy RegisterContextSP TargetThreadWindows::GetRegisterContext() { 504ad5def9SAdrian McCarthy if (!m_reg_context_sp) 5145d8134cSStella Stamenova m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 524ad5def9SAdrian McCarthy 534ad5def9SAdrian McCarthy return m_reg_context_sp; 544ad5def9SAdrian McCarthy } 554ad5def9SAdrian McCarthy 564ad5def9SAdrian McCarthy RegisterContextSP 574ad5def9SAdrian McCarthy TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { 5845d8134cSStella Stamenova RegisterContextSP reg_ctx_sp; 5945d8134cSStella Stamenova uint32_t concrete_frame_idx = 0; 6045d8134cSStella Stamenova Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 614ad5def9SAdrian McCarthy 6245d8134cSStella Stamenova if (frame) 6345d8134cSStella Stamenova concrete_frame_idx = frame->GetConcreteFrameIndex(); 6445d8134cSStella Stamenova 6545d8134cSStella Stamenova if (concrete_frame_idx == 0) { 6645d8134cSStella Stamenova if (!m_thread_reg_ctx_sp) { 674ad5def9SAdrian McCarthy ArchSpec arch = HostInfo::GetArchitecture(); 684ad5def9SAdrian McCarthy switch (arch.GetMachine()) { 694ad5def9SAdrian McCarthy case llvm::Triple::x86: 704ad5def9SAdrian McCarthy #if defined(_WIN64) 714ad5def9SAdrian McCarthy // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 7245d8134cSStella Stamenova LLDB_LOG(log, "This is a Wow64 process, we should create a " 7345d8134cSStella Stamenova "RegisterContextWindows_Wow64, but we don't."); 744ad5def9SAdrian McCarthy #else 7545d8134cSStella Stamenova m_thread_reg_ctx_sp.reset( 7645d8134cSStella Stamenova new RegisterContextWindows_x86(*this, concrete_frame_idx)); 774ad5def9SAdrian McCarthy #endif 784ad5def9SAdrian McCarthy break; 794ad5def9SAdrian McCarthy case llvm::Triple::x86_64: 804ad5def9SAdrian McCarthy #if defined(_WIN64) 8145d8134cSStella Stamenova m_thread_reg_ctx_sp.reset( 8245d8134cSStella Stamenova new RegisterContextWindows_x64(*this, concrete_frame_idx)); 834ad5def9SAdrian McCarthy #else 8445d8134cSStella Stamenova LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit."); 854ad5def9SAdrian McCarthy #endif 864ad5def9SAdrian McCarthy default: 874ad5def9SAdrian McCarthy break; 884ad5def9SAdrian McCarthy } 894ad5def9SAdrian McCarthy } 9045d8134cSStella Stamenova reg_ctx_sp = m_thread_reg_ctx_sp; 9145d8134cSStella Stamenova } else { 9245d8134cSStella Stamenova Unwind *unwinder = GetUnwinder(); 9345d8134cSStella Stamenova if (unwinder != nullptr) 9445d8134cSStella Stamenova reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); 9545d8134cSStella Stamenova } 9645d8134cSStella Stamenova 9745d8134cSStella Stamenova return reg_ctx_sp; 984ad5def9SAdrian McCarthy } 994ad5def9SAdrian McCarthy 100b9c1b51eSKate Stone bool TargetThreadWindows::CalculateStopInfo() { 10118a9135dSAdrian McCarthy SetStopInfo(m_stop_info_sp); 10218a9135dSAdrian McCarthy return true; 10318a9135dSAdrian McCarthy } 10418a9135dSAdrian McCarthy 105b9c1b51eSKate Stone Unwind *TargetThreadWindows::GetUnwinder() { 106b9c1b51eSKate Stone // FIXME: Implement an unwinder based on the Windows unwinder exposed through 107b9c1b51eSKate Stone // DIA SDK. 108*d5b44036SJonas Devlieghere if (!m_unwinder_up) 109*d5b44036SJonas Devlieghere m_unwinder_up.reset(new UnwindLLDB(*this)); 110*d5b44036SJonas Devlieghere return m_unwinder_up.get(); 11118a9135dSAdrian McCarthy } 11218a9135dSAdrian McCarthy 1130fd67b53SStella Stamenova Status TargetThreadWindows::DoResume() { 11418a9135dSAdrian McCarthy StateType resume_state = GetTemporaryResumeState(); 11518a9135dSAdrian McCarthy StateType current_state = GetState(); 11618a9135dSAdrian McCarthy if (resume_state == current_state) 1170fd67b53SStella Stamenova return Status(); 11818a9135dSAdrian McCarthy 119b9c1b51eSKate Stone if (resume_state == eStateStepping) { 120b9c1b51eSKate Stone uint32_t flags_index = 121b9c1b51eSKate Stone GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 122b9c1b51eSKate Stone eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 123b9c1b51eSKate Stone uint64_t flags_value = 124b9c1b51eSKate Stone GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); 12518a9135dSAdrian McCarthy flags_value |= 0x100; // Set the trap flag on the CPU 12618a9135dSAdrian McCarthy GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); 12718a9135dSAdrian McCarthy } 12818a9135dSAdrian McCarthy 129b9c1b51eSKate Stone if (resume_state == eStateStepping || resume_state == eStateRunning) { 13018a9135dSAdrian McCarthy DWORD previous_suspend_count = 0; 13118a9135dSAdrian McCarthy HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 132b9c1b51eSKate Stone do { 13345d8134cSStella Stamenova // ResumeThread returns -1 on error, or the thread's *previous* suspend 13445d8134cSStella Stamenova // count on success. This means that the return value is 1 when the thread 13545d8134cSStella Stamenova // was restarted. Note that DWORD is an unsigned int, so we need to 13645d8134cSStella Stamenova // explicitly compare with -1. 13718a9135dSAdrian McCarthy previous_suspend_count = ::ResumeThread(thread_handle); 1380fd67b53SStella Stamenova 1390fd67b53SStella Stamenova if (previous_suspend_count == (DWORD)-1) 1400fd67b53SStella Stamenova return Status(::GetLastError(), eErrorTypeWin32); 1410fd67b53SStella Stamenova 1420fd67b53SStella Stamenova } while (previous_suspend_count > 1); 14318a9135dSAdrian McCarthy } 1440fd67b53SStella Stamenova 1450fd67b53SStella Stamenova return Status(); 14618a9135dSAdrian McCarthy } 147