Refactor LLDB's Windows process plugin (NFC)

The Windows process plugin was broken up into multiple pieces a while back in
order to share code between debugging live processes and minidumps
(postmortem) debugging. The minidump portion was replaced by a cross-platform
solution. This left the plugin split into a formerly "common" base classes and
the derived classes for live debugging. This extra layer made the code harder
to understand and work with.

This patch simplifies these class hierarchies by rolling the live debugging
concrete classes up to the base classes. Last week I posted my intent to make
this change to lldb-dev, and I didn't hear any objections.

This involved moving code and changing references to classes like
ProcessWindowsLive to ProcessWindows. It still builds for both 32- and 64-bit,
and the tests still pass on 32-bit. (Tests on 64-bit weren't passing before
this refactor for unrelated reasons.)

llvm-svn: 287770
This commit is contained in:
Adrian McCarthy 2016-11-23 16:26:37 +00:00
parent 5abf14ba51
commit 4ad5def9b0
25 changed files with 1230 additions and 1764 deletions

View File

@ -90,7 +90,6 @@ set( LLDB_USED_LIBS
# Windows-only libraries
if ( CMAKE_SYSTEM_NAME MATCHES "Windows" )
list(APPEND LLDB_USED_LIBS
lldbPluginProcessWindows
lldbPluginProcessWindowsCommon
Ws2_32
Rpcrt4

View File

@ -108,7 +108,7 @@
#endif
#if defined(_MSC_VER)
#include "Plugins/Process/Windows/Live/ProcessWindowsLive.h"
#include "Plugins/Process/Windows/Common/ProcessWindows.h"
#include "lldb/Host/windows/windows.h"
#endif
@ -333,7 +333,7 @@ void SystemInitializerFull::Initialize() {
OCamlLanguage::Initialize();
#if defined(_MSC_VER)
ProcessWindowsLive::Initialize();
ProcessWindows::Initialize();
#endif
#if defined(__FreeBSD__)
ProcessFreeBSD::Initialize();

View File

@ -7,7 +7,6 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
add_subdirectory(POSIX)
elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
add_subdirectory(Windows/Live)
add_subdirectory(Windows/Common)
elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX-Kernel)

View File

@ -2,9 +2,11 @@ include_directories(.)
include_directories(../../Utility)
set(PROC_WINDOWS_COMMON_SOURCES
RegisterContextWindows.cpp
DebuggerThread.cpp
LocalDebugDelegate.cpp
ProcessWindows.cpp
ProcessWindowsLog.cpp
RegisterContextWindows.cpp
TargetThreadWindows.cpp
)

View File

@ -1,5 +1,5 @@
//===-- DebuggerThread.DebuggerThread --------------------------------------*-
//C++ -*-===//
// C++ -*-===//
//
// The LLVM Compiler Infrastructure
//

View File

@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "LocalDebugDelegate.h"
#include "ProcessWindowsLive.h"
#include "ProcessWindows.h"
using namespace lldb;
using namespace lldb_private;
@ -17,57 +17,57 @@ LocalDebugDelegate::LocalDebugDelegate(ProcessWP process)
: m_process(process) {}
void LocalDebugDelegate::OnExitProcess(uint32_t exit_code) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnExitProcess(exit_code);
}
void LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnDebuggerConnected(image_base);
}
ExceptionResult
LocalDebugDelegate::OnDebugException(bool first_chance,
const ExceptionRecord &record) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
return process->OnDebugException(first_chance, record);
else
return ExceptionResult::MaskException;
}
void LocalDebugDelegate::OnCreateThread(const HostThread &thread) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnCreateThread(thread);
}
void LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id,
uint32_t exit_code) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnExitThread(thread_id, exit_code);
}
void LocalDebugDelegate::OnLoadDll(const lldb_private::ModuleSpec &module_spec,
lldb::addr_t module_addr) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnLoadDll(module_spec, module_addr);
}
void LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnUnloadDll(module_addr);
}
void LocalDebugDelegate::OnDebugString(const std::string &string) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnDebugString(string);
}
void LocalDebugDelegate::OnDebuggerError(const Error &error, uint32_t type) {
if (ProcessWindowsLiveSP process = GetProcessPointer())
if (ProcessWindowsSP process = GetProcessPointer())
process->OnDebuggerError(error, type);
}
ProcessWindowsLiveSP LocalDebugDelegate::GetProcessPointer() {
ProcessWindowsSP LocalDebugDelegate::GetProcessPointer() {
ProcessSP process = m_process.lock();
return std::static_pointer_cast<ProcessWindowsLive>(process);
return std::static_pointer_cast<ProcessWindows>(process);
}

View File

@ -18,19 +18,17 @@
namespace lldb_private {
class ProcessWindowsLive;
typedef std::shared_ptr<ProcessWindowsLive> ProcessWindowsLiveSP;
class ProcessWindows;
typedef std::shared_ptr<ProcessWindows> ProcessWindowsSP;
//----------------------------------------------------------------------
// LocalDebugDelegate
//
// LocalDebugDelegate creates a connection between a ProcessWindowsLive and the
// debug driver. This serves to decouple ProcessWindowsLive from the debug
// driver.
// It would be possible to get a similar decoupling by just having
// ProcessWindowsLive implement this interface directly. There are two reasons
// why
// we don't do this:
// LocalDebugDelegate creates a connection between a ProcessWindows and the
// debug driver. This serves to decouple ProcessWindows from the debug
// driver. It would be possible to get a similar decoupling by just having
// ProcessWindows implement this interface directly. There are two reasons
// why we don't do this:
//
// 1) In the future when we add support for local debugging through LLGS, and we
// go through the Native*Protocol interface, it is likely we will need the
@ -60,7 +58,7 @@ public:
void OnDebuggerError(const Error &error, uint32_t type) override;
private:
ProcessWindowsLiveSP GetProcessPointer();
ProcessWindowsSP GetProcessPointer();
lldb::ProcessWP m_process;
};

File diff suppressed because it is too large Load Diff

View File

@ -15,10 +15,32 @@
#include "lldb/Target/Process.h"
#include "lldb/lldb-forward.h"
#include "llvm/Support/Mutex.h"
#include "IDebugDelegate.h"
namespace lldb_private {
class ProcessWindows : public lldb_private::Process {
class HostProcess;
class ProcessWindowsData;
class ProcessWindows : public Process, public IDebugDelegate {
public:
//------------------------------------------------------------------
// Static functions.
//------------------------------------------------------------------
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
lldb::ListenerSP listener_sp,
const FileSpec *);
static void Initialize();
static void Terminate();
static lldb_private::ConstString GetPluginNameStatic();
static const char *GetPluginDescriptionStatic();
//------------------------------------------------------------------
// Constructors and destructors
//------------------------------------------------------------------
@ -26,22 +48,71 @@ public:
~ProcessWindows();
size_t GetSTDOUT(char *buf, size_t buf_size,
lldb_private::Error &error) override;
size_t GetSTDERR(char *buf, size_t buf_size,
lldb_private::Error &error) override;
size_t PutSTDIN(const char *buf, size_t buf_size,
lldb_private::Error &error) override;
size_t GetSTDOUT(char *buf, size_t buf_size, Error &error) override;
size_t GetSTDERR(char *buf, size_t buf_size, Error &error) override;
size_t PutSTDIN(const char *buf, size_t buf_size, Error &error) override;
// lldb_private::Process overrides
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
Error EnableBreakpointSite(BreakpointSite *bp_site) override;
Error DisableBreakpointSite(BreakpointSite *bp_site) override;
Error DoDetach(bool keep_stopped) override;
Error DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override;
Error DoAttachToProcessWithID(
lldb::pid_t pid,
const lldb_private::ProcessAttachInfo &attach_info) override;
Error DoResume() override;
Error DoDestroy() override;
Error DoHalt(bool &caused_stop) override;
void DidLaunch() override;
void DidAttach(lldb_private::ArchSpec &arch_spec) override;
void RefreshStateAfterStop() override;
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
bool DestroyRequiresHalt() override { return false; }
bool UpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) override;
bool IsAlive() override;
size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
Error &error) override;
size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
Error &error) override;
Error GetMemoryRegionInfo(lldb::addr_t vm_addr,
MemoryRegionInfo &info) override;
lldb::addr_t GetImageInfoAddress() override;
protected:
// IDebugDelegate overrides.
void OnExitProcess(uint32_t exit_code) override;
void OnDebuggerConnected(lldb::addr_t image_base) override;
ExceptionResult OnDebugException(bool first_chance,
const ExceptionRecord &record) override;
void OnCreateThread(const HostThread &thread) override;
void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override;
void OnLoadDll(const ModuleSpec &module_spec,
lldb::addr_t module_addr) override;
void OnUnloadDll(lldb::addr_t module_addr) override;
void OnDebugString(const std::string &string) override;
void OnDebuggerError(const Error &error, uint32_t type) override;
private:
Error WaitForDebuggerConnection(DebuggerThreadSP debugger,
HostProcess &process);
// These decode the page protection bits.
static bool IsPageReadable(uint32_t protect);
static bool IsPageWritable(uint32_t protect);
static bool IsPageExecutable(uint32_t protect);
llvm::sys::Mutex m_mutex;
std::unique_ptr<ProcessWindowsData> m_session_data;
};
}

View File

@ -21,6 +21,12 @@
#include "TargetThreadWindows.h"
#include "UnwindLLDB.h"
#if defined(_WIN64)
#include "x86/RegisterContextWindows_x64.h"
#else
#include "x86/RegisterContextWindows_x86.h"
#endif
using namespace lldb;
using namespace lldb_private;
@ -41,6 +47,44 @@ void TargetThreadWindows::WillResume(lldb::StateType 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)
m_reg_context_sp.reset(new RegisterContextWindows_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 TargetThreadWindows::CalculateStopInfo() {
SetStopInfo(m_stop_info_sp);
return true;

View File

@ -15,6 +15,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/lldb-forward.h"
#include "RegisterContextWindows.h"
namespace lldb_private {
class ProcessWindows;
class HostThread;
@ -29,6 +31,9 @@ public:
void RefreshStateAfterStop() override;
void WillResume(lldb::StateType resume_state) override;
void DidStop() override;
lldb::RegisterContextSP GetRegisterContext() override;
lldb::RegisterContextSP
CreateRegisterContextForFrame(StackFrame *frame) override;
bool CalculateStopInfo() override;
Unwind *GetUnwinder() override;
@ -37,6 +42,8 @@ public:
HostThread GetHostThread() const { return m_host_thread; }
private:
lldb::RegisterContextSP CreateRegisterContextForFrameIndex(uint32_t idx);
HostThread m_host_thread;
};
}

View File

@ -16,6 +16,7 @@
#include "ProcessWindowsLog.h"
#include "RegisterContextWindows_x86.h"
#include "RegisterContext_x86.h"
#include "TargetThreadWindows.h"
#include "lldb-x86-register-enums.h"
#include "llvm/ADT/STLExtras.h"
@ -208,6 +209,80 @@ bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
return false;
}
bool RegisterContextWindows_x86::WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) {
// Since we cannot only write a single register value to the inferior, we need
// to make sure
// our cached copy of the register values are fresh. Otherwise when writing
// EAX, for example,
// we may also overwrite some other register with a stale value.
if (!CacheAllRegisterValues())
return false;
uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
switch (reg) {
case lldb_eax_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EAX",
reg_value.GetAsUInt32());
m_context.Eax = reg_value.GetAsUInt32();
break;
case lldb_ebx_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBX",
reg_value.GetAsUInt32());
m_context.Ebx = reg_value.GetAsUInt32();
break;
case lldb_ecx_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ECX",
reg_value.GetAsUInt32());
m_context.Ecx = reg_value.GetAsUInt32();
break;
case lldb_edx_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDX",
reg_value.GetAsUInt32());
m_context.Edx = reg_value.GetAsUInt32();
break;
case lldb_edi_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDI",
reg_value.GetAsUInt32());
m_context.Edi = reg_value.GetAsUInt32();
break;
case lldb_esi_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESI",
reg_value.GetAsUInt32());
m_context.Esi = reg_value.GetAsUInt32();
break;
case lldb_ebp_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBP",
reg_value.GetAsUInt32());
m_context.Ebp = reg_value.GetAsUInt32();
break;
case lldb_esp_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESP",
reg_value.GetAsUInt32());
m_context.Esp = reg_value.GetAsUInt32();
break;
case lldb_eip_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EIP",
reg_value.GetAsUInt32());
m_context.Eip = reg_value.GetAsUInt32();
break;
case lldb_eflags_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EFLAGS",
reg_value.GetAsUInt32());
m_context.EFlags = reg_value.GetAsUInt32();
break;
default:
WINWARN_IFALL(WINDOWS_LOG_REGISTERS,
"Write value 0x%x to unknown register %u",
reg_value.GetAsUInt32(), reg);
}
// Physically update the registers in the target process.
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
return ::SetThreadContext(
wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
}
bool RegisterContextWindows_x86::ReadRegisterHelper(
DWORD flags_required, const char *reg_name, DWORD value,
RegisterValue &reg_value) const {

View File

@ -40,6 +40,9 @@ public:
bool ReadRegister(const RegisterInfo *reg_info,
RegisterValue &reg_value) override;
bool WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) override;
private:
bool ReadRegisterHelper(DWORD flags_required, const char *reg_name,
DWORD value, RegisterValue &reg_value) const;

View File

@ -1,24 +0,0 @@
include_directories(.)
include_directories(../../Utility)
include_directories(../Common)
set(PROC_WINDOWS_SOURCES
DebuggerThread.cpp
LocalDebugDelegate.cpp
ProcessWindowsLive.cpp
TargetThreadWindowsLive.cpp
)
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set(PROC_WINDOWS_SOURCES ${PROC_WINDOWS_SOURCES}
x86/RegisterContextWindowsLive_x86.cpp
)
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(PROC_WINDOWS_SOURCES ${PROC_WINDOWS_SOURCES}
x64/RegisterContextWindowsLive_x64.cpp
)
endif()
add_lldb_library(lldbPluginProcessWindows
${PROC_WINDOWS_SOURCES}
)

File diff suppressed because it is too large Load Diff

View File

@ -1,129 +0,0 @@
//===-- ProcessWindowsLive.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_Plugins_Process_Windows_Live_ProcessWindowsLive_H_
#define liblldb_Plugins_Process_Windows_Live_ProcessWindowsLive_H_
// C Includes
// C++ Includes
#include <memory>
#include <queue>
// Other libraries and framework includes
#include "ForwardDecl.h"
#include "IDebugDelegate.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Target/Process.h"
#include "lldb/lldb-forward.h"
#include "llvm/Support/Mutex.h"
#include "Plugins/Process/Windows/Common/ProcessWindows.h"
class ProcessMonitor;
namespace lldb_private {
class HostProcess;
class ProcessWindowsData;
class ProcessWindowsLive : public lldb_private::ProcessWindows,
public lldb_private::IDebugDelegate {
public:
//------------------------------------------------------------------
// Static functions.
//------------------------------------------------------------------
static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
lldb::ListenerSP listener_sp,
const lldb_private::FileSpec *);
static void Initialize();
static void Terminate();
static lldb_private::ConstString GetPluginNameStatic();
static const char *GetPluginDescriptionStatic();
//------------------------------------------------------------------
// Constructors and destructors
//------------------------------------------------------------------
ProcessWindowsLive(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
~ProcessWindowsLive();
// lldb_private::Process overrides
lldb_private::ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
lldb_private::Error
EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
lldb_private::Error
DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
lldb_private::Error DoDetach(bool keep_stopped) override;
lldb_private::Error
DoLaunch(lldb_private::Module *exe_module,
lldb_private::ProcessLaunchInfo &launch_info) override;
lldb_private::Error DoAttachToProcessWithID(
lldb::pid_t pid,
const lldb_private::ProcessAttachInfo &attach_info) override;
lldb_private::Error DoResume() override;
lldb_private::Error DoDestroy() override;
lldb_private::Error DoHalt(bool &caused_stop) override;
void DidLaunch() override;
void DidAttach(lldb_private::ArchSpec &arch_spec) override;
void RefreshStateAfterStop() override;
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
bool DestroyRequiresHalt() override { return false; }
bool UpdateThreadList(lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list) override;
bool IsAlive() override;
size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
lldb_private::Error &error) override;
size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
lldb_private::Error &error) override;
lldb_private::Error
GetMemoryRegionInfo(lldb::addr_t vm_addr,
lldb_private::MemoryRegionInfo &info) override;
// IDebugDelegate overrides.
void OnExitProcess(uint32_t exit_code) override;
void OnDebuggerConnected(lldb::addr_t image_base) override;
ExceptionResult
OnDebugException(bool first_chance,
const lldb_private::ExceptionRecord &record) override;
void OnCreateThread(const lldb_private::HostThread &thread) override;
void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) override;
void OnLoadDll(const lldb_private::ModuleSpec &module_spec,
lldb::addr_t module_addr) override;
void OnUnloadDll(lldb::addr_t module_addr) override;
void OnDebugString(const std::string &string) override;
void OnDebuggerError(const lldb_private::Error &error,
uint32_t type) override;
private:
lldb_private::Error
WaitForDebuggerConnection(lldb_private::DebuggerThreadSP debugger,
lldb_private::HostProcess &process);
llvm::sys::Mutex m_mutex;
// Data for the active debugging session.
std::unique_ptr<lldb_private::ProcessWindowsData> m_session_data;
};
}
#endif // liblldb_Plugins_Process_Windows_Live_ProcessWindowsLive_H_

View File

@ -1,124 +0,0 @@
//===-- 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 "ProcessWindows.h"
#include "ProcessWindowsLog.h"
#include "TargetThreadWindowsLive.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;
}

View File

@ -1,50 +0,0 @@
//===-- TargetThreadWindowsLive.h -------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_Plugins_Process_Windows_TargetThreadWindowsLive_H_
#define liblldb_Plugins_Process_Windows_TargetThreadWindowsLive_H_
#include "lldb/Host/HostThread.h"
#include "lldb/Target/Thread.h"
#include "lldb/lldb-forward.h"
#include "Plugins/Process/Windows/Common/TargetThreadWindows.h"
namespace lldb_private {
class ProcessWindows;
class HostThread;
class StackFrame;
class TargetThreadWindowsLive : public lldb_private::TargetThreadWindows {
public:
TargetThreadWindowsLive(ProcessWindows &process, const HostThread &thread);
virtual ~TargetThreadWindowsLive();
// lldb_private::Thread overrides
void RefreshStateAfterStop() override;
void WillResume(lldb::StateType resume_state) override;
void DidStop() override;
lldb::RegisterContextSP GetRegisterContext() override;
lldb::RegisterContextSP
CreateRegisterContextForFrame(StackFrame *frame) override;
bool CalculateStopInfo() override;
Unwind *GetUnwinder() override;
bool DoResume();
HostThread GetHostThread() const { return m_host_thread; }
private:
lldb::RegisterContextSP CreateRegisterContextForFrameIndex(uint32_t idx);
HostThread m_host_thread;
};
}
#endif

View File

@ -1,166 +0,0 @@
//===-- RegisterContextWindowsLive_x64.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/Error.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/lldb-private-types.h"
#include "RegisterContextWindowsLive_x64.h"
#include "TargetThreadWindows.h"
#include "lldb-x86-register-enums.h"
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
RegisterContextWindowsLive_x64::RegisterContextWindowsLive_x64(
Thread &thread, uint32_t concrete_frame_idx)
: RegisterContextWindows_x64(thread, concrete_frame_idx) {}
RegisterContextWindowsLive_x64::~RegisterContextWindowsLive_x64() {}
bool RegisterContextWindowsLive_x64::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &reg_value) {
if (!CacheAllRegisterValues())
return false;
switch (reg_info->kinds[eRegisterKindLLDB]) {
case lldb_rax_x86_64:
reg_value.SetUInt64(m_context.Rax);
break;
case lldb_rbx_x86_64:
reg_value.SetUInt64(m_context.Rbx);
break;
case lldb_rcx_x86_64:
reg_value.SetUInt64(m_context.Rcx);
break;
case lldb_rdx_x86_64:
reg_value.SetUInt64(m_context.Rdx);
break;
case lldb_rdi_x86_64:
reg_value.SetUInt64(m_context.Rdi);
break;
case lldb_rsi_x86_64:
reg_value.SetUInt64(m_context.Rsi);
break;
case lldb_r8_x86_64:
reg_value.SetUInt64(m_context.R8);
break;
case lldb_r9_x86_64:
reg_value.SetUInt64(m_context.R9);
break;
case lldb_r10_x86_64:
reg_value.SetUInt64(m_context.R10);
break;
case lldb_r11_x86_64:
reg_value.SetUInt64(m_context.R11);
break;
case lldb_r12_x86_64:
reg_value.SetUInt64(m_context.R12);
break;
case lldb_r13_x86_64:
reg_value.SetUInt64(m_context.R13);
break;
case lldb_r14_x86_64:
reg_value.SetUInt64(m_context.R14);
break;
case lldb_r15_x86_64:
reg_value.SetUInt64(m_context.R15);
break;
case lldb_rbp_x86_64:
reg_value.SetUInt64(m_context.Rbp);
break;
case lldb_rsp_x86_64:
reg_value.SetUInt64(m_context.Rsp);
break;
case lldb_rip_x86_64:
reg_value.SetUInt64(m_context.Rip);
break;
case lldb_rflags_x86_64:
reg_value.SetUInt64(m_context.EFlags);
break;
}
return true;
}
bool RegisterContextWindowsLive_x64::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &reg_value) {
// Since we cannot only write a single register value to the inferior, we need
// to make sure
// our cached copy of the register values are fresh. Otherwise when writing
// EAX, for example,
// we may also overwrite some other register with a stale value.
if (!CacheAllRegisterValues())
return false;
switch (reg_info->kinds[eRegisterKindLLDB]) {
case lldb_rax_x86_64:
m_context.Rax = reg_value.GetAsUInt64();
break;
case lldb_rbx_x86_64:
m_context.Rbx = reg_value.GetAsUInt64();
break;
case lldb_rcx_x86_64:
m_context.Rcx = reg_value.GetAsUInt64();
break;
case lldb_rdx_x86_64:
m_context.Rdx = reg_value.GetAsUInt64();
break;
case lldb_rdi_x86_64:
m_context.Rdi = reg_value.GetAsUInt64();
break;
case lldb_rsi_x86_64:
m_context.Rsi = reg_value.GetAsUInt64();
break;
case lldb_r8_x86_64:
m_context.R8 = reg_value.GetAsUInt64();
break;
case lldb_r9_x86_64:
m_context.R9 = reg_value.GetAsUInt64();
break;
case lldb_r10_x86_64:
m_context.R10 = reg_value.GetAsUInt64();
break;
case lldb_r11_x86_64:
m_context.R11 = reg_value.GetAsUInt64();
break;
case lldb_r12_x86_64:
m_context.R12 = reg_value.GetAsUInt64();
break;
case lldb_r13_x86_64:
m_context.R13 = reg_value.GetAsUInt64();
break;
case lldb_r14_x86_64:
m_context.R14 = reg_value.GetAsUInt64();
break;
case lldb_r15_x86_64:
m_context.R15 = reg_value.GetAsUInt64();
break;
case lldb_rbp_x86_64:
m_context.Rbp = reg_value.GetAsUInt64();
break;
case lldb_rsp_x86_64:
m_context.Rsp = reg_value.GetAsUInt64();
break;
case lldb_rip_x86_64:
m_context.Rip = reg_value.GetAsUInt64();
break;
case lldb_rflags_x86_64:
m_context.EFlags = reg_value.GetAsUInt64();
break;
}
// Physically update the registers in the target process.
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
return ::SetThreadContext(
wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
}

View File

@ -1,40 +0,0 @@
//===-- RegisterContextWindowsLive_x64.h ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextWindowsLive_x64_H_
#define liblldb_RegisterContextWindowsLive_x64_H_
#include "../../Common/x64/RegisterContextWindows_x64.h"
#include "lldb/lldb-forward.h"
namespace lldb_private {
class Thread;
class RegisterContextWindowsLive_x64 : public RegisterContextWindows_x64 {
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindowsLive_x64(Thread &thread, uint32_t concrete_frame_idx);
virtual ~RegisterContextWindowsLive_x64();
//------------------------------------------------------------------
// Subclasses must override these functions
//------------------------------------------------------------------
bool ReadRegister(const RegisterInfo *reg_info,
RegisterValue &reg_value) override;
bool WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) override;
};
}
#endif // #ifndef liblldb_RegisterContextWindowsLive_x64_H_

View File

@ -1,108 +0,0 @@
//===-- RegisterContextWindowsLive_x86.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/Error.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/lldb-private-types.h"
#include "ProcessWindowsLog.h"
#include "RegisterContextWindowsLive_x86.h"
#include "TargetThreadWindows.h"
#include "lldb-x86-register-enums.h"
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
namespace lldb_private {
RegisterContextWindowsLive_x86::RegisterContextWindowsLive_x86(
Thread &thread, uint32_t concrete_frame_idx)
: RegisterContextWindows_x86(thread, concrete_frame_idx) {}
RegisterContextWindowsLive_x86::~RegisterContextWindowsLive_x86() {}
bool RegisterContextWindowsLive_x86::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &reg_value) {
// Since we cannot only write a single register value to the inferior, we need
// to make sure
// our cached copy of the register values are fresh. Otherwise when writing
// EAX, for example,
// we may also overwrite some other register with a stale value.
if (!CacheAllRegisterValues())
return false;
uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
switch (reg) {
case lldb_eax_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EAX",
reg_value.GetAsUInt32());
m_context.Eax = reg_value.GetAsUInt32();
break;
case lldb_ebx_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBX",
reg_value.GetAsUInt32());
m_context.Ebx = reg_value.GetAsUInt32();
break;
case lldb_ecx_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ECX",
reg_value.GetAsUInt32());
m_context.Ecx = reg_value.GetAsUInt32();
break;
case lldb_edx_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDX",
reg_value.GetAsUInt32());
m_context.Edx = reg_value.GetAsUInt32();
break;
case lldb_edi_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EDI",
reg_value.GetAsUInt32());
m_context.Edi = reg_value.GetAsUInt32();
break;
case lldb_esi_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESI",
reg_value.GetAsUInt32());
m_context.Esi = reg_value.GetAsUInt32();
break;
case lldb_ebp_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EBP",
reg_value.GetAsUInt32());
m_context.Ebp = reg_value.GetAsUInt32();
break;
case lldb_esp_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to ESP",
reg_value.GetAsUInt32());
m_context.Esp = reg_value.GetAsUInt32();
break;
case lldb_eip_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EIP",
reg_value.GetAsUInt32());
m_context.Eip = reg_value.GetAsUInt32();
break;
case lldb_eflags_i386:
WINLOG_IFALL(WINDOWS_LOG_REGISTERS, "Write value 0x%x to EFLAGS",
reg_value.GetAsUInt32());
m_context.EFlags = reg_value.GetAsUInt32();
break;
default:
WINWARN_IFALL(WINDOWS_LOG_REGISTERS,
"Write value 0x%x to unknown register %u",
reg_value.GetAsUInt32(), reg);
}
// Physically update the registers in the target process.
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
return ::SetThreadContext(
wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context);
}
} // namespace lldb_private

View File

@ -1,34 +0,0 @@
//===-- RegisterContextWindowsLive_x86.h ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextWindowsLive_x86_H_
#define liblldb_RegisterContextWindowsLive_x86_H_
#include "../../Common/x86/RegisterContextWindows_x86.h"
#include "lldb/lldb-forward.h"
namespace lldb_private {
class Thread;
class RegisterContextWindowsLive_x86 : public RegisterContextWindows_x86 {
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindowsLive_x86(Thread &thread, uint32_t concrete_frame_idx);
virtual ~RegisterContextWindowsLive_x86();
bool WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) override;
};
}
#endif // #ifndef liblldb_RegisterContextWindowsLive_x86_H_