148 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			148 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- TargetThreadWindowsLive.cpp------------------------------*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "lldb/Core/Log.h"
 | |
| #include "lldb/Core/Logging.h"
 | |
| #include "lldb/Core/State.h"
 | |
| #include "lldb/Host/HostInfo.h"
 | |
| #include "lldb/Host/HostNativeThreadBase.h"
 | |
| #include "lldb/Host/windows/HostThreadWindows.h"
 | |
| #include "lldb/Host/windows/windows.h"
 | |
| #include "lldb/Target/RegisterContext.h"
 | |
| 
 | |
| #include "TargetThreadWindowsLive.h"
 | |
| #include "ProcessWindows.h"
 | |
| #include "ProcessWindowsLog.h"
 | |
| #include "UnwindLLDB.h"
 | |
| 
 | |
| #if defined(_WIN64)
 | |
| #include "x64/RegisterContextWindowsLive_x64.h"
 | |
| #else
 | |
| #include "x86/RegisterContextWindowsLive_x86.h"
 | |
| #endif
 | |
| 
 | |
| using namespace lldb;
 | |
| using namespace lldb_private;
 | |
| 
 | |
| TargetThreadWindowsLive::TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread)
 | |
|     : TargetThreadWindows(process, thread)
 | |
|     , m_host_thread(thread)
 | |
| {
 | |
| }
 | |
| 
 | |
| TargetThreadWindowsLive::~TargetThreadWindowsLive()
 | |
| {
 | |
|     DestroyThread();
 | |
| }
 | |
| 
 | |
| void
 | |
| TargetThreadWindowsLive::RefreshStateAfterStop()
 | |
| {
 | |
|     ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
 | |
|     SetState(eStateStopped);
 | |
|     GetRegisterContext()->InvalidateIfNeeded(false);
 | |
| }
 | |
| 
 | |
| void
 | |
| TargetThreadWindowsLive::WillResume(lldb::StateType resume_state)
 | |
| {
 | |
| }
 | |
| 
 | |
| void
 | |
| TargetThreadWindowsLive::DidStop()
 | |
| {
 | |
| }
 | |
| 
 | |
| RegisterContextSP
 | |
| TargetThreadWindowsLive::GetRegisterContext()
 | |
| {
 | |
|     if (!m_reg_context_sp)
 | |
|         m_reg_context_sp = CreateRegisterContextForFrameIndex(0);
 | |
| 
 | |
|     return m_reg_context_sp;
 | |
| }
 | |
| 
 | |
| RegisterContextSP
 | |
| TargetThreadWindowsLive::CreateRegisterContextForFrame(StackFrame *frame)
 | |
| {
 | |
|     return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex());
 | |
| }
 | |
| 
 | |
| RegisterContextSP
 | |
| TargetThreadWindowsLive::CreateRegisterContextForFrameIndex(uint32_t idx)
 | |
| {
 | |
|     if (!m_reg_context_sp)
 | |
|     {
 | |
|         ArchSpec arch = HostInfo::GetArchitecture();
 | |
|         switch (arch.GetMachine())
 | |
|         {
 | |
|             case llvm::Triple::x86:
 | |
| #if defined(_WIN64)
 | |
|                 // FIXME: This is a Wow64 process, create a RegisterContextWindows_Wow64
 | |
| #else
 | |
|                 m_reg_context_sp.reset(new RegisterContextWindowsLive_x86(*this, idx));
 | |
| #endif
 | |
|                 break;
 | |
|             case llvm::Triple::x86_64:
 | |
| #if defined(_WIN64)
 | |
|                 m_reg_context_sp.reset(new RegisterContextWindowsLive_x64(*this, idx));
 | |
| #else
 | |
|                 // LLDB is 32-bit, but the target process is 64-bit.  We probably can't debug this.
 | |
| #endif
 | |
|             default:
 | |
|                 break;
 | |
|         }
 | |
|     }
 | |
|     return m_reg_context_sp;
 | |
| }
 | |
| 
 | |
| bool
 | |
| TargetThreadWindowsLive::CalculateStopInfo()
 | |
| {
 | |
|     SetStopInfo(m_stop_info_sp);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| Unwind *
 | |
| TargetThreadWindowsLive::GetUnwinder()
 | |
| {
 | |
|     // FIXME: Implement an unwinder based on the Windows unwinder exposed through DIA SDK.
 | |
|     if (m_unwinder_ap.get() == NULL)
 | |
|         m_unwinder_ap.reset(new UnwindLLDB(*this));
 | |
|     return m_unwinder_ap.get();
 | |
| }
 | |
| 
 | |
| bool
 | |
| TargetThreadWindowsLive::DoResume()
 | |
| {
 | |
|     StateType resume_state = GetTemporaryResumeState();
 | |
|     StateType current_state = GetState();
 | |
|     if (resume_state == current_state)
 | |
|         return true;
 | |
| 
 | |
|     if (resume_state == eStateStepping)
 | |
|     {
 | |
|         uint32_t flags_index = GetRegisterContext()->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
 | |
|         uint64_t flags_value = GetRegisterContext()->ReadRegisterAsUnsigned(flags_index, 0);
 | |
|         flags_value |= 0x100; // Set the trap flag on the CPU
 | |
|         GetRegisterContext()->WriteRegisterFromUnsigned(flags_index, flags_value);
 | |
|     }
 | |
| 
 | |
|     if (resume_state == eStateStepping || resume_state == eStateRunning)
 | |
|     {
 | |
|         DWORD previous_suspend_count = 0;
 | |
|         HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
 | |
|         do
 | |
|         {
 | |
|             previous_suspend_count = ::ResumeThread(thread_handle);
 | |
|         } while (previous_suspend_count > 0);
 | |
|     }
 | |
|     return true;
 | |
| }
 |