Files
clang-p2996/lldb/source/Plugins/Process/Windows/TargetThreadWindows.cpp
Zachary Turner f194c50fc3 Some fixes for thread stepping on Windows.
This hooks up the changes necessary to set the trap flag on the
CPU and properly manage the process and thread's resume state
and private state so that the ThreadPlan does its thing.

Stepping still doesn't work as of this change, because there are
some issues with stack frames where it doesn't update the thread's
frame list correctly when it breaks inside of a function, but
I will try to fix that separately.

llvm-svn: 226221
2015-01-15 22:54:08 +00:00

143 lines
3.8 KiB
C++

//===-- TargetThreadWindows.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/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 "TargetThreadWindows.h"
#include "ProcessWindows.h"
#include "UnwindLLDB.h"
#if !defined(_WIN64)
#include "x86/RegisterContextWindows_x86.h"
#endif
using namespace lldb;
using namespace lldb_private;
TargetThreadWindows::TargetThreadWindows(ProcessWindows &process, const HostThread &thread)
: Thread(process, thread.GetNativeThread().GetThreadId())
, m_host_thread(thread)
{
}
TargetThreadWindows::~TargetThreadWindows()
{
DestroyThread();
}
void
TargetThreadWindows::RefreshStateAfterStop()
{
DWORD old_suspend_count = ::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
GetRegisterContext()->InvalidateIfNeeded(false);
}
void
TargetThreadWindows::WillResume(lldb::StateType resume_state)
{
SetResumeState(resume_state);
}
void
TargetThreadWindows::DidStop()
{
}
RegisterContextSP
TargetThreadWindows::GetRegisterContext()
{
if (!m_reg_context_sp)
m_reg_context_sp = CreateRegisterContextForFrameIndex(0);
return m_reg_context_sp;
}
RegisterContextSP
TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame)
{
return CreateRegisterContextForFrameIndex(frame->GetConcreteFrameIndex());
}
RegisterContextSP
TargetThreadWindows::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 RegisterContextWindows_x86(*this, idx));
#endif
break;
case llvm::Triple::x86_64:
#if defined(_WIN64)
// FIXME: This is a 64-bit process, create a RegisterContextWindows_x86_64
#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
TargetThreadWindows::CalculateStopInfo()
{
SetStopInfo(m_stop_info_sp);
return true;
}
Unwind *
TargetThreadWindows::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
TargetThreadWindows::DoResume()
{
StateType resume_state = GetResumeState();
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;
}