1 //===-- TargetThreadWindows.cpp----------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/Core/State.h" 11 #include "lldb/Host/HostInfo.h" 12 #include "lldb/Host/HostNativeThreadBase.h" 13 #include "lldb/Host/windows/HostThreadWindows.h" 14 #include "lldb/Host/windows/windows.h" 15 #include "lldb/Target/RegisterContext.h" 16 #include "lldb/Utility/Log.h" 17 #include "lldb/Utility/Logging.h" 18 19 #include "Plugins/Process/Utility/UnwindLLDB.h" 20 #include "ProcessWindows.h" 21 #include "ProcessWindowsLog.h" 22 #include "TargetThreadWindows.h" 23 24 #if defined(_WIN64) 25 #include "x64/RegisterContextWindows_x64.h" 26 #else 27 #include "x86/RegisterContextWindows_x86.h" 28 #endif 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, 34 const HostThread &thread) 35 : Thread(process, thread.GetNativeThread().GetThreadId()), 36 m_thread_reg_ctx_sp(), m_host_thread(thread) {} 37 38 TargetThreadWindows::~TargetThreadWindows() { DestroyThread(); } 39 40 void TargetThreadWindows::RefreshStateAfterStop() { 41 ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle()); 42 SetState(eStateStopped); 43 GetRegisterContext()->InvalidateIfNeeded(false); 44 } 45 46 void TargetThreadWindows::WillResume(lldb::StateType resume_state) {} 47 48 void TargetThreadWindows::DidStop() {} 49 50 RegisterContextSP TargetThreadWindows::GetRegisterContext() { 51 if (!m_reg_context_sp) 52 m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 53 54 return m_reg_context_sp; 55 } 56 57 RegisterContextSP 58 TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { 59 RegisterContextSP reg_ctx_sp; 60 uint32_t concrete_frame_idx = 0; 61 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); 62 63 if (frame) 64 concrete_frame_idx = frame->GetConcreteFrameIndex(); 65 66 if (concrete_frame_idx == 0) { 67 if (!m_thread_reg_ctx_sp) { 68 ArchSpec arch = HostInfo::GetArchitecture(); 69 switch (arch.GetMachine()) { 70 case llvm::Triple::x86: 71 #if defined(_WIN64) 72 // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64 73 LLDB_LOG(log, "This is a Wow64 process, we should create a " 74 "RegisterContextWindows_Wow64, but we don't."); 75 #else 76 m_thread_reg_ctx_sp.reset( 77 new RegisterContextWindows_x86(*this, concrete_frame_idx)); 78 #endif 79 break; 80 case llvm::Triple::x86_64: 81 #if defined(_WIN64) 82 m_thread_reg_ctx_sp.reset( 83 new RegisterContextWindows_x64(*this, concrete_frame_idx)); 84 #else 85 LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit."); 86 #endif 87 default: 88 break; 89 } 90 } 91 reg_ctx_sp = m_thread_reg_ctx_sp; 92 } else { 93 Unwind *unwinder = GetUnwinder(); 94 if (unwinder != nullptr) 95 reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); 96 } 97 98 return reg_ctx_sp; 99 } 100 101 bool TargetThreadWindows::CalculateStopInfo() { 102 SetStopInfo(m_stop_info_sp); 103 return true; 104 } 105 106 Unwind *TargetThreadWindows::GetUnwinder() { 107 // FIXME: Implement an unwinder based on the Windows unwinder exposed through 108 // DIA SDK. 109 if (!m_unwinder_ap) 110 m_unwinder_ap.reset(new UnwindLLDB(*this)); 111 return m_unwinder_ap.get(); 112 } 113 114 Status TargetThreadWindows::DoResume() { 115 StateType resume_state = GetTemporaryResumeState(); 116 StateType current_state = GetState(); 117 if (resume_state == current_state) 118 return Status(); 119 120 if (resume_state == eStateStepping) { 121 uint32_t flags_index = 122 GetRegisterContext()->ConvertRegisterKindToRegisterNumber( 123 eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS); 124 uint64_t flags_value = 125 GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0); 126 flags_value |= 0x100; // Set the trap flag on the CPU 127 GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value); 128 } 129 130 if (resume_state == eStateStepping || resume_state == eStateRunning) { 131 DWORD previous_suspend_count = 0; 132 HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle(); 133 do { 134 // ResumeThread returns -1 on error, or the thread's *previous* suspend 135 // count on success. This means that the return value is 1 when the thread 136 // was restarted. Note that DWORD is an unsigned int, so we need to 137 // explicitly compare with -1. 138 previous_suspend_count = ::ResumeThread(thread_handle); 139 140 if (previous_suspend_count == (DWORD)-1) 141 return Status(::GetLastError(), eErrorTypeWin32); 142 143 } while (previous_suspend_count > 1); 144 } 145 146 return Status(); 147 } 148