Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@@ -0,0 +1,36 @@
include_directories(.)
include_directories(../../Utility)
set(PROC_WINDOWS_COMMON_SOURCES
DebuggerThread.cpp
LocalDebugDelegate.cpp
ProcessWindows.cpp
ProcessWindowsLog.cpp
RegisterContextWindows.cpp
TargetThreadWindows.cpp
)
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set(PROC_WINDOWS_COMMON_SOURCES ${PROC_WINDOWS_COMMON_SOURCES}
x86/RegisterContextWindows_x86.cpp
)
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
set(PROC_WINDOWS_COMMON_SOURCES ${PROC_WINDOWS_COMMON_SOURCES}
x64/RegisterContextWindows_x64.cpp
)
endif()
add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN
${PROC_WINDOWS_COMMON_SOURCES}
LINK_LIBS
lldbCore
lldbHost
lldbInterpreter
lldbSymbol
lldbTarget
ws2_32
rpcrt4
LINK_COMPONENTS
Support
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
//===-- DebuggerThread.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_DebuggerThread_H_
#define liblldb_Plugins_Process_Windows_DebuggerThread_H_
#include <atomic>
#include <memory>
#include "ForwardDecl.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Predicate.h"
#include "lldb/Host/windows/windows.h"
namespace lldb_private {
//----------------------------------------------------------------------
// DebuggerThread
//
// Debugs a single process, notifying listeners as appropriate when interesting
// things occur.
//----------------------------------------------------------------------
class DebuggerThread : public std::enable_shared_from_this<DebuggerThread> {
public:
DebuggerThread(DebugDelegateSP debug_delegate);
virtual ~DebuggerThread();
Status DebugLaunch(const ProcessLaunchInfo &launch_info);
Status DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info);
HostProcess GetProcess() const { return m_process; }
HostThread GetMainThread() const { return m_main_thread; }
std::weak_ptr<ExceptionRecord> GetActiveException() {
return m_active_exception;
}
Status StopDebugging(bool terminate);
void ContinueAsyncException(ExceptionResult result);
private:
void FreeProcessHandles();
void DebugLoop();
ExceptionResult HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
DWORD thread_id);
DWORD HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info,
DWORD thread_id);
DWORD HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info,
DWORD thread_id);
DWORD HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info,
DWORD thread_id);
DWORD HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info,
DWORD thread_id);
DWORD HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id);
DWORD HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info,
DWORD thread_id);
DWORD HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id);
DWORD HandleRipEvent(const RIP_INFO &info, DWORD thread_id);
DebugDelegateSP m_debug_delegate;
HostProcess m_process; // The process being debugged.
HostThread m_main_thread; // The main thread of the inferior.
// The image file of the process being debugged.
HANDLE m_image_file = nullptr;
// The current exception waiting to be handled
ExceptionRecordSP m_active_exception;
// A predicate which gets signalled when an exception is finished processing
// and the debug loop can be continued.
Predicate<ExceptionResult> m_exception_pred;
// An event which gets signalled by the debugger thread when it exits the
// debugger loop and is detached from the inferior.
HANDLE m_debugging_ended_event = nullptr;
// Signals the loop to detach from the process (specified by pid).
std::atomic<DWORD> m_pid_to_detach;
// Signals the debug loop to stop processing certain types of events that
// block shutdown.
std::atomic<bool> m_is_shutting_down;
// Indicates we've detached from the inferior process and the debug loop can
// exit.
bool m_detached = false;
static lldb::thread_result_t DebuggerThreadLaunchRoutine(void *data);
lldb::thread_result_t
DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info);
static lldb::thread_result_t DebuggerThreadAttachRoutine(void *data);
lldb::thread_result_t
DebuggerThreadAttachRoutine(lldb::pid_t pid,
const ProcessAttachInfo &launch_info);
};
}
#endif

View File

@@ -0,0 +1,80 @@
//===-- ExceptionRecord.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_ExceptionRecord_H_
#define liblldb_Plugins_Process_Windows_ExceptionRecord_H_
#include "lldb/Host/windows/windows.h"
#include "lldb/lldb-forward.h"
#include <dbghelp.h>
#include <memory>
#include <vector>
namespace lldb_private {
//----------------------------------------------------------------------
// ExceptionRecord
//
// ExceptionRecord defines an interface which allows implementors to receive
// notification of events that happen in a debugged process.
//----------------------------------------------------------------------
class ExceptionRecord {
public:
ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id) {
m_code = record.ExceptionCode;
m_continuable = (record.ExceptionFlags == 0);
if (record.ExceptionRecord)
m_next_exception.reset(
new ExceptionRecord(*record.ExceptionRecord, thread_id));
m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress);
m_thread_id = thread_id;
m_arguments.assign(record.ExceptionInformation,
record.ExceptionInformation + record.NumberParameters);
}
// MINIDUMP_EXCEPTIONs are almost identical to EXCEPTION_RECORDs.
ExceptionRecord(const MINIDUMP_EXCEPTION &record, lldb::tid_t thread_id)
: m_code(record.ExceptionCode), m_continuable(record.ExceptionFlags == 0),
m_next_exception(nullptr),
m_exception_addr(static_cast<lldb::addr_t>(record.ExceptionAddress)),
m_thread_id(thread_id),
m_arguments(record.ExceptionInformation,
record.ExceptionInformation + record.NumberParameters) {
// Set up link to nested exception.
if (record.ExceptionRecord) {
m_next_exception.reset(new ExceptionRecord(
*reinterpret_cast<const MINIDUMP_EXCEPTION *>(record.ExceptionRecord),
thread_id));
}
}
virtual ~ExceptionRecord() {}
DWORD
GetExceptionCode() const { return m_code; }
bool IsContinuable() const { return m_continuable; }
const ExceptionRecord *GetNextException() const {
return m_next_exception.get();
}
lldb::addr_t GetExceptionAddress() const { return m_exception_addr; }
lldb::tid_t GetThreadID() const { return m_thread_id; }
private:
DWORD m_code;
bool m_continuable;
std::shared_ptr<ExceptionRecord> m_next_exception;
lldb::addr_t m_exception_addr;
lldb::tid_t m_thread_id;
std::vector<ULONG_PTR> m_arguments;
};
}
#endif

View File

@@ -0,0 +1,42 @@
//===-- ForwardDecl.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_ForwardDecl_H_
#define liblldb_Plugins_Process_Windows_ForwardDecl_H_
#include <memory>
// ExceptionResult is returned by the debug delegate to specify how it processed
// the exception.
enum class ExceptionResult {
BreakInDebugger, // Break in the debugger and give the user a chance to
// interact with
// the program before continuing.
MaskException, // Eat the exception and don't let the application know it
// occurred.
SendToApplication // Send the exception to the application to be handled as if
// there were
// no debugger attached.
};
namespace lldb_private {
class ProcessWindows;
class IDebugDelegate;
class DebuggerThread;
class ExceptionRecord;
typedef std::shared_ptr<IDebugDelegate> DebugDelegateSP;
typedef std::shared_ptr<DebuggerThread> DebuggerThreadSP;
typedef std::shared_ptr<ExceptionRecord> ExceptionRecordSP;
typedef std::unique_ptr<ExceptionRecord> ExceptionRecordUP;
}
#endif

View File

@@ -0,0 +1,46 @@
//===-- IDebugDelegate.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_IDebugDelegate_H_
#define liblldb_Plugins_Process_Windows_IDebugDelegate_H_
#include "ForwardDecl.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"
#include <string>
namespace lldb_private {
class Status;
class HostThread;
//----------------------------------------------------------------------
// IDebugDelegate
//
// IDebugDelegate defines an interface which allows implementors to receive
// notification of events that happen in a debugged process.
//----------------------------------------------------------------------
class IDebugDelegate {
public:
virtual ~IDebugDelegate() {}
virtual void OnExitProcess(uint32_t exit_code) = 0;
virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0;
virtual ExceptionResult OnDebugException(bool first_chance,
const ExceptionRecord &record) = 0;
virtual void OnCreateThread(const HostThread &thread) = 0;
virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0;
virtual void OnLoadDll(const ModuleSpec &module_spec,
lldb::addr_t module_addr) = 0;
virtual void OnUnloadDll(lldb::addr_t module_addr) = 0;
virtual void OnDebugString(const std::string &string) = 0;
virtual void OnDebuggerError(const Status &error, uint32_t type) = 0;
};
}
#endif

View File

@@ -0,0 +1,73 @@
//===-- LocalDebugDelegate.cpp ----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "LocalDebugDelegate.h"
#include "ProcessWindows.h"
using namespace lldb;
using namespace lldb_private;
LocalDebugDelegate::LocalDebugDelegate(ProcessWP process)
: m_process(process) {}
void LocalDebugDelegate::OnExitProcess(uint32_t exit_code) {
if (ProcessWindowsSP process = GetProcessPointer())
process->OnExitProcess(exit_code);
}
void LocalDebugDelegate::OnDebuggerConnected(lldb::addr_t image_base) {
if (ProcessWindowsSP process = GetProcessPointer())
process->OnDebuggerConnected(image_base);
}
ExceptionResult
LocalDebugDelegate::OnDebugException(bool first_chance,
const ExceptionRecord &record) {
if (ProcessWindowsSP process = GetProcessPointer())
return process->OnDebugException(first_chance, record);
else
return ExceptionResult::MaskException;
}
void LocalDebugDelegate::OnCreateThread(const HostThread &thread) {
if (ProcessWindowsSP process = GetProcessPointer())
process->OnCreateThread(thread);
}
void LocalDebugDelegate::OnExitThread(lldb::tid_t thread_id,
uint32_t exit_code) {
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 (ProcessWindowsSP process = GetProcessPointer())
process->OnLoadDll(module_spec, module_addr);
}
void LocalDebugDelegate::OnUnloadDll(lldb::addr_t module_addr) {
if (ProcessWindowsSP process = GetProcessPointer())
process->OnUnloadDll(module_addr);
}
void LocalDebugDelegate::OnDebugString(const std::string &string) {
if (ProcessWindowsSP process = GetProcessPointer())
process->OnDebugString(string);
}
void LocalDebugDelegate::OnDebuggerError(const Status &error, uint32_t type) {
if (ProcessWindowsSP process = GetProcessPointer())
process->OnDebuggerError(error, type);
}
ProcessWindowsSP LocalDebugDelegate::GetProcessPointer() {
ProcessSP process = m_process.lock();
return std::static_pointer_cast<ProcessWindows>(process);
}

View File

@@ -0,0 +1,67 @@
//===-- LocalDebugDelegate.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_LocalDebugDelegate_H_
#define liblldb_Plugins_Process_Windows_LocalDebugDelegate_H_
#include <memory>
#include "IDebugDelegate.h"
#include "lldb/lldb-forward.h"
namespace lldb_private {
class ProcessWindows;
typedef std::shared_ptr<ProcessWindows> ProcessWindowsSP;
//----------------------------------------------------------------------
// LocalDebugDelegate
//
// 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
// additional flexibility provided by this sort of adapter pattern.
// 2) LLDB holds a shared_ptr to the ProcessWindows, and our driver thread
// needs access to it as well. To avoid a race condition, we want to make
// sure that we're also holding onto a shared_ptr.
// lldb_private::Process supports enable_shared_from_this, but that gives us
// a ProcessSP (which is exactly what we are trying to decouple from the
// driver), so this adapter serves as a way to transparently hold the
// ProcessSP while still keeping it decoupled from the driver.
//----------------------------------------------------------------------
class LocalDebugDelegate : public IDebugDelegate {
public:
explicit LocalDebugDelegate(lldb::ProcessWP process);
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 lldb_private::ModuleSpec &module_spec,
lldb::addr_t module_addr) override;
void OnUnloadDll(lldb::addr_t module_addr) override;
void OnDebugString(const std::string &message) override;
void OnDebuggerError(const Status &error, uint32_t type) override;
private:
ProcessWindowsSP GetProcessPointer();
lldb::ProcessWP m_process;
};
}
#endif

View File

@@ -0,0 +1,31 @@
//===-- NtStructures.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_Common_NtStructures_h_
#define liblldb_Plugins_Process_Windows_Common_NtStructures_h_
#include "lldb/Host/windows/windows.h"
// This describes the layout of a TEB (Thread Environment Block) for a 64-bit
// process. It's adapted from the 32-bit TEB in winternl.h. Currently, we care
// only about the position of the TlsSlots.
struct TEB64 {
ULONG64 Reserved1[12];
ULONG64 ProcessEnvironmentBlock;
ULONG64 Reserved2[399];
BYTE Reserved3[1952];
ULONG64 TlsSlots[64];
BYTE Reserved4[8];
ULONG64 Reserved5[26];
ULONG64 ReservedForOle; // Windows 2000 only
ULONG64 Reserved6[4];
ULONG64 TlsExpansionSlots;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,119 @@
//===-- ProcessWindows.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_Common_ProcessWindows_H_
#define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_
// Other libraries and framework includes
#include "lldb/Target/Process.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-forward.h"
#include "llvm/Support/Mutex.h"
#include "IDebugDelegate.h"
namespace lldb_private {
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
//------------------------------------------------------------------
ProcessWindows(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
~ProcessWindows();
size_t GetSTDOUT(char *buf, size_t buf_size, Status &error) override;
size_t GetSTDERR(char *buf, size_t buf_size, Status &error) override;
size_t PutSTDIN(const char *buf, size_t buf_size, Status &error) override;
// lldb_private::Process overrides
ConstString GetPluginName() override;
uint32_t GetPluginVersion() override;
Status EnableBreakpointSite(BreakpointSite *bp_site) override;
Status DisableBreakpointSite(BreakpointSite *bp_site) override;
Status DoDetach(bool keep_stopped) override;
Status DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override;
Status DoAttachToProcessWithID(
lldb::pid_t pid,
const lldb_private::ProcessAttachInfo &attach_info) override;
Status DoResume() override;
Status DoDestroy() override;
Status 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,
Status &error) override;
size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
Status &error) override;
Status GetMemoryRegionInfo(lldb::addr_t vm_addr,
MemoryRegionInfo &info) override;
lldb::addr_t GetImageInfoAddress() override;
// 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 Status &error, uint32_t type) override;
private:
Status 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;
};
}
#endif // liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_

View File

@@ -0,0 +1,41 @@
//===-- ProcessWindowsLog.cpp -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ProcessWindowsLog.h"
using namespace lldb_private;
static constexpr Log::Category g_categories[] = {
{{"break"}, {"log breakpoints"}, WINDOWS_LOG_BREAKPOINTS},
{{"event"}, {"log low level debugger events"}, WINDOWS_LOG_EVENT},
{{"exception"}, {"log exception information"}, WINDOWS_LOG_EXCEPTION},
{{"memory"}, {"log memory reads and writes"}, WINDOWS_LOG_MEMORY},
{{"process"}, {"log process events and activities"}, WINDOWS_LOG_PROCESS},
{{"registers"}, {"log register read/writes"}, WINDOWS_LOG_REGISTERS},
{{"step"}, {"log step related activities"}, WINDOWS_LOG_STEP},
{{"thread"}, {"log thread events and activities"}, WINDOWS_LOG_THREAD},
};
Log::Channel ProcessWindowsLog::g_channel(g_categories, WINDOWS_LOG_PROCESS);
void ProcessWindowsLog::Initialize() {
static llvm::once_flag g_once_flag;
llvm::call_once(g_once_flag, []() { Log::Register("windows", g_channel); });
}
void ProcessWindowsLog::Terminate() {}

View File

@@ -0,0 +1,36 @@
//===-- ProcessWindowsLog.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_ProcessWindowsLog_h_
#define liblldb_ProcessWindowsLog_h_
#include "lldb/Utility/Log.h"
#define WINDOWS_LOG_PROCESS (1u << 1) // Log process operations
#define WINDOWS_LOG_EXCEPTION (1u << 1) // Log exceptions
#define WINDOWS_LOG_THREAD (1u << 2) // Log thread operations
#define WINDOWS_LOG_MEMORY (1u << 3) // Log memory reads/writes calls
#define WINDOWS_LOG_BREAKPOINTS (1u << 4) // Log breakpoint operations
#define WINDOWS_LOG_STEP (1u << 5) // Log step operations
#define WINDOWS_LOG_REGISTERS (1u << 6) // Log register operations
#define WINDOWS_LOG_EVENT (1u << 7) // Low level debug events
namespace lldb_private {
class ProcessWindowsLog {
static Log::Channel g_channel;
public:
static void Initialize();
static void Terminate();
static Log *GetLogIfAny(uint32_t mask) { return g_channel.GetLogIfAny(mask); }
};
}
#endif // liblldb_ProcessWindowsLog_h_

View File

@@ -0,0 +1,135 @@
//===-- RegisterContextWindows.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/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-types.h"
#include "ProcessWindowsLog.h"
#include "RegisterContextWindows.h"
#include "TargetThreadWindows.h"
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
const DWORD kWinContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindows::RegisterContextWindows(Thread &thread,
uint32_t concrete_frame_idx)
: RegisterContext(thread, concrete_frame_idx), m_context(),
m_context_stale(true) {}
RegisterContextWindows::~RegisterContextWindows() {}
void RegisterContextWindows::InvalidateAllRegisters() {
m_context_stale = true;
}
bool RegisterContextWindows::ReadAllRegisterValues(
lldb::DataBufferSP &data_sp) {
if (!CacheAllRegisterValues())
return false;
if (data_sp->GetByteSize() < sizeof(m_context)) {
data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
}
memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));
return true;
}
bool RegisterContextWindows::WriteAllRegisterValues(
const lldb::DataBufferSP &data_sp) {
assert(data_sp->GetByteSize() >= sizeof(m_context));
memcpy(&m_context, data_sp->GetBytes(), sizeof(m_context));
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
if (!::SetThreadContext(
wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
&m_context))
return false;
return true;
}
uint32_t RegisterContextWindows::ConvertRegisterKindToRegisterNumber(
lldb::RegisterKind kind, uint32_t num) {
const uint32_t num_regs = GetRegisterCount();
assert(kind < kNumRegisterKinds);
for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
if (reg_info->kinds[kind] == num)
return reg_idx;
}
return LLDB_INVALID_REGNUM;
}
//------------------------------------------------------------------
// Subclasses can these functions if desired
//------------------------------------------------------------------
uint32_t RegisterContextWindows::NumSupportedHardwareBreakpoints() {
// Support for hardware breakpoints not yet implemented.
return 0;
}
uint32_t RegisterContextWindows::SetHardwareBreakpoint(lldb::addr_t addr,
size_t size) {
return 0;
}
bool RegisterContextWindows::ClearHardwareBreakpoint(uint32_t hw_idx) {
return false;
}
uint32_t RegisterContextWindows::NumSupportedHardwareWatchpoints() {
// Support for hardware watchpoints not yet implemented.
return 0;
}
uint32_t RegisterContextWindows::SetHardwareWatchpoint(lldb::addr_t addr,
size_t size, bool read,
bool write) {
return 0;
}
bool RegisterContextWindows::ClearHardwareWatchpoint(uint32_t hw_index) {
return false;
}
bool RegisterContextWindows::HardwareSingleStep(bool enable) { return false; }
bool RegisterContextWindows::CacheAllRegisterValues() {
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
if (!m_context_stale)
return true;
TargetThreadWindows &wthread = static_cast<TargetThreadWindows &>(m_thread);
memset(&m_context, 0, sizeof(m_context));
m_context.ContextFlags = kWinContextFlags;
if (!::GetThreadContext(
wthread.GetHostThread().GetNativeThread().GetSystemHandle(),
&m_context)) {
LLDB_LOG(
log,
"GetThreadContext failed with error {0} while caching register values.",
::GetLastError());
return false;
}
LLDB_LOG(log, "successfully updated the register values.");
m_context_stale = false;
return true;
}

View File

@@ -0,0 +1,67 @@
//===-- RegisterContextWindows.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_RegisterContextWindows_H_
#define liblldb_RegisterContextWindows_H_
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-forward.h"
namespace lldb_private {
class Thread;
class RegisterContextWindows : public lldb_private::RegisterContext {
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindows(Thread &thread, uint32_t concrete_frame_idx);
virtual ~RegisterContextWindows();
//------------------------------------------------------------------
// Subclasses must override these functions
//------------------------------------------------------------------
void InvalidateAllRegisters() override;
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
uint32_t num) override;
//------------------------------------------------------------------
// Subclasses can override these functions if desired
//------------------------------------------------------------------
uint32_t NumSupportedHardwareBreakpoints() override;
uint32_t SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override;
bool ClearHardwareBreakpoint(uint32_t hw_idx) override;
uint32_t NumSupportedHardwareWatchpoints() override;
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
bool write) override;
bool ClearHardwareWatchpoint(uint32_t hw_index) override;
bool HardwareSingleStep(bool enable) override;
protected:
virtual bool CacheAllRegisterValues();
CONTEXT m_context;
bool m_context_stale;
};
}
#endif // #ifndef liblldb_RegisterContextWindows_H_

View File

@@ -0,0 +1,125 @@
//===-- 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/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 "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
#include "ProcessWindows.h"
#include "ProcessWindowsLog.h"
#include "TargetThreadWindows.h"
#include "UnwindLLDB.h"
#if defined(_WIN64)
#include "x64/RegisterContextWindows_x64.h"
#else
#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() {
::SuspendThread(m_host_thread.GetNativeThread().GetSystemHandle());
SetState(eStateStopped);
GetRegisterContext()->InvalidateIfNeeded(false);
}
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;
}
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 = 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

@@ -0,0 +1,51 @@
//===-- TargetThreadWindows.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_TargetThreadWindows_H_
#define liblldb_Plugins_Process_Windows_TargetThreadWindows_H_
//#include "ForwardDecl.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Target/Thread.h"
#include "lldb/lldb-forward.h"
#include "RegisterContextWindows.h"
namespace lldb_private {
class ProcessWindows;
class HostThread;
class StackFrame;
class TargetThreadWindows : public lldb_private::Thread {
public:
TargetThreadWindows(ProcessWindows &process, const HostThread &thread);
virtual ~TargetThreadWindows();
// 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

@@ -0,0 +1,342 @@
//===-- RegisterContextWindows_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/RegisterValue.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-types.h"
#include "RegisterContextWindows_x64.h"
#include "RegisterContext_x86.h"
#include "TargetThreadWindows.h"
#include "lldb-x86-register-enums.h"
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
#define DEFINE_GPR(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatHexUppercase
#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 8, 0, eEncodingUint, eFormatBinary
namespace {
// This enum defines the layout of the global RegisterInfo array. This is
// necessary because
// lldb register sets are defined in terms of indices into the register array.
// As such, the
// order of RegisterInfos defined in global registers array must match the order
// defined here.
// When defining the register set layouts, these values can appear in an
// arbitrary order, and that
// determines the order that register values are displayed in a dump.
enum RegisterIndex {
eRegisterIndexRax,
eRegisterIndexRbx,
eRegisterIndexRcx,
eRegisterIndexRdx,
eRegisterIndexRdi,
eRegisterIndexRsi,
eRegisterIndexR8,
eRegisterIndexR9,
eRegisterIndexR10,
eRegisterIndexR11,
eRegisterIndexR12,
eRegisterIndexR13,
eRegisterIndexR14,
eRegisterIndexR15,
eRegisterIndexRbp,
eRegisterIndexRsp,
eRegisterIndexRip,
eRegisterIndexRflags
};
// Array of all register information supported by Windows x86
RegisterInfo g_register_infos[] = {
// Macro auto defines most stuff eh_frame DWARF
// GENERIC
// GDB LLDB VALUE REGS INVALIDATE REGS
// ================================ =========================
// ====================== =========================
// =================== ================= ========== ===============
{DEFINE_GPR(rax, nullptr),
{dwarf_rax_x86_64, dwarf_rax_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_rax_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rbx, nullptr),
{dwarf_rbx_x86_64, dwarf_rbx_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_rbx_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rcx, nullptr),
{dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_rcx_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rdx, nullptr),
{dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_rdx_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rdi, nullptr),
{dwarf_rdi_x86_64, dwarf_rdi_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_rdi_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rsi, nullptr),
{dwarf_rsi_x86_64, dwarf_rsi_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_rsi_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r8, nullptr),
{dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r8_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r9, nullptr),
{dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r9_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r10, nullptr),
{dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r10_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r11, nullptr),
{dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r11_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r12, nullptr),
{dwarf_r12_x86_64, dwarf_r12_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r12_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r13, nullptr),
{dwarf_r13_x86_64, dwarf_r13_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r13_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r14, nullptr),
{dwarf_r14_x86_64, dwarf_r14_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r14_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r15, nullptr),
{dwarf_r15_x86_64, dwarf_r15_x86_64, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_r15_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rbp, "fp"),
{dwarf_rbp_x86_64, dwarf_rbp_x86_64, LLDB_REGNUM_GENERIC_FP,
LLDB_INVALID_REGNUM, lldb_rbp_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rsp, "sp"),
{dwarf_rsp_x86_64, dwarf_rsp_x86_64, LLDB_REGNUM_GENERIC_SP,
LLDB_INVALID_REGNUM, lldb_rsp_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rip, "pc"),
{dwarf_rip_x86_64, dwarf_rip_x86_64, LLDB_REGNUM_GENERIC_PC,
LLDB_INVALID_REGNUM, lldb_rip_x86_64},
nullptr,
nullptr},
{DEFINE_GPR_BIN(eflags, "flags"),
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS,
LLDB_INVALID_REGNUM, lldb_rflags_x86_64},
nullptr,
nullptr},
};
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
// Array of lldb register numbers used to define the set of all General Purpose
// Registers
uint32_t g_gpr_reg_indices[] = {
eRegisterIndexRax, eRegisterIndexRbx, eRegisterIndexRcx,
eRegisterIndexRdx, eRegisterIndexRdi, eRegisterIndexRsi,
eRegisterIndexR8, eRegisterIndexR9, eRegisterIndexR10,
eRegisterIndexR11, eRegisterIndexR12, eRegisterIndexR13,
eRegisterIndexR14, eRegisterIndexR15, eRegisterIndexRbp,
eRegisterIndexRsp, eRegisterIndexRip, eRegisterIndexRflags};
RegisterSet g_register_sets[] = {
{"General Purpose Registers", "gpr",
llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
};
}
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindows_x64::RegisterContextWindows_x64(
Thread &thread, uint32_t concrete_frame_idx)
: RegisterContextWindows(thread, concrete_frame_idx) {}
RegisterContextWindows_x64::~RegisterContextWindows_x64() {}
size_t RegisterContextWindows_x64::GetRegisterCount() {
return llvm::array_lengthof(g_register_infos);
}
const RegisterInfo *
RegisterContextWindows_x64::GetRegisterInfoAtIndex(size_t reg) {
if (reg < k_num_register_infos)
return &g_register_infos[reg];
return NULL;
}
size_t RegisterContextWindows_x64::GetRegisterSetCount() {
return llvm::array_lengthof(g_register_sets);
}
const RegisterSet *RegisterContextWindows_x64::GetRegisterSet(size_t reg_set) {
return &g_register_sets[reg_set];
}
bool RegisterContextWindows_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 RegisterContextWindows_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

@@ -0,0 +1,48 @@
//===-- RegisterContextWindows_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_RegisterContextWindows_x64_H_
#define liblldb_RegisterContextWindows_x64_H_
#include "RegisterContextWindows.h"
#include "lldb/lldb-forward.h"
namespace lldb_private {
class Thread;
class RegisterContextWindows_x64 : public RegisterContextWindows {
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindows_x64(Thread &thread, uint32_t concrete_frame_idx);
virtual ~RegisterContextWindows_x64();
//------------------------------------------------------------------
// Subclasses must override these functions
//------------------------------------------------------------------
size_t GetRegisterCount() override;
const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
size_t GetRegisterSetCount() override;
const RegisterSet *GetRegisterSet(size_t reg_set) override;
bool ReadRegister(const RegisterInfo *reg_info,
RegisterValue &reg_value) override;
bool WriteRegister(const RegisterInfo *reg_info,
const RegisterValue &reg_value) override;
};
}
#endif // #ifndef liblldb_RegisterContextWindows_x64_H_

View File

@@ -0,0 +1,288 @@
//===-- RegisterContextWindows_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/RegisterValue.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-types.h"
#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"
using namespace lldb;
using namespace lldb_private;
#define DEFINE_GPR(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatHexUppercase
#define DEFINE_GPR_BIN(reg, alt) #reg, alt, 4, 0, eEncodingUint, eFormatBinary
namespace {
// This enum defines the layout of the global RegisterInfo array. This is
// necessary because
// lldb register sets are defined in terms of indices into the register array.
// As such, the
// order of RegisterInfos defined in global registers array must match the order
// defined here.
// When defining the register set layouts, these values can appear in an
// arbitrary order, and that
// determines the order that register values are displayed in a dump.
enum RegisterIndex {
eRegisterIndexEax,
eRegisterIndexEbx,
eRegisterIndexEcx,
eRegisterIndexEdx,
eRegisterIndexEdi,
eRegisterIndexEsi,
eRegisterIndexEbp,
eRegisterIndexEsp,
eRegisterIndexEip,
eRegisterIndexEflags
};
// Array of all register information supported by Windows x86
RegisterInfo g_register_infos[] = {
// Macro auto defines most stuff eh_frame DWARF
// GENERIC GDB LLDB
// VALUE REGS INVALIDATE REGS
// ============================== =======================
// =================== ========================= ===================
// ================= ========== ===============
{DEFINE_GPR(eax, nullptr),
{ehframe_eax_i386, dwarf_eax_i386, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_eax_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(ebx, nullptr),
{ehframe_ebx_i386, dwarf_ebx_i386, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_ebx_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(ecx, nullptr),
{ehframe_ecx_i386, dwarf_ecx_i386, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_ecx_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(edx, nullptr),
{ehframe_edx_i386, dwarf_edx_i386, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_edx_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(edi, nullptr),
{ehframe_edi_i386, dwarf_edi_i386, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_edi_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(esi, nullptr),
{ehframe_esi_i386, dwarf_esi_i386, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, lldb_esi_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(ebp, "fp"),
{ehframe_ebp_i386, dwarf_ebp_i386, LLDB_REGNUM_GENERIC_FP,
LLDB_INVALID_REGNUM, lldb_ebp_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(esp, "sp"),
{ehframe_esp_i386, dwarf_esp_i386, LLDB_REGNUM_GENERIC_SP,
LLDB_INVALID_REGNUM, lldb_esp_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR(eip, "pc"),
{ehframe_eip_i386, dwarf_eip_i386, LLDB_REGNUM_GENERIC_PC,
LLDB_INVALID_REGNUM, lldb_eip_i386},
nullptr,
nullptr,
nullptr,
0u},
{DEFINE_GPR_BIN(eflags, "flags"),
{ehframe_eflags_i386, dwarf_eflags_i386, LLDB_REGNUM_GENERIC_FLAGS,
LLDB_INVALID_REGNUM, lldb_eflags_i386},
nullptr,
nullptr,
nullptr,
0u},
};
static size_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
// Array of lldb register numbers used to define the set of all General Purpose
// Registers
uint32_t g_gpr_reg_indices[] = {eRegisterIndexEax, eRegisterIndexEbx,
eRegisterIndexEcx, eRegisterIndexEdx,
eRegisterIndexEdi, eRegisterIndexEsi,
eRegisterIndexEbp, eRegisterIndexEsp,
eRegisterIndexEip, eRegisterIndexEflags};
RegisterSet g_register_sets[] = {
{"General Purpose Registers", "gpr",
llvm::array_lengthof(g_gpr_reg_indices), g_gpr_reg_indices},
};
}
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
RegisterContextWindows_x86::RegisterContextWindows_x86(
Thread &thread, uint32_t concrete_frame_idx)
: RegisterContextWindows(thread, concrete_frame_idx) {}
RegisterContextWindows_x86::~RegisterContextWindows_x86() {}
size_t RegisterContextWindows_x86::GetRegisterCount() {
return llvm::array_lengthof(g_register_infos);
}
const RegisterInfo *
RegisterContextWindows_x86::GetRegisterInfoAtIndex(size_t reg) {
if (reg < k_num_register_infos)
return &g_register_infos[reg];
return NULL;
}
size_t RegisterContextWindows_x86::GetRegisterSetCount() {
return llvm::array_lengthof(g_register_sets);
}
const RegisterSet *RegisterContextWindows_x86::GetRegisterSet(size_t reg_set) {
return &g_register_sets[reg_set];
}
bool RegisterContextWindows_x86::ReadRegister(const RegisterInfo *reg_info,
RegisterValue &reg_value) {
if (!CacheAllRegisterValues())
return false;
uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
switch (reg) {
case lldb_eax_i386:
return ReadRegisterHelper(CONTEXT_INTEGER, "EAX", m_context.Eax, reg_value);
case lldb_ebx_i386:
return ReadRegisterHelper(CONTEXT_INTEGER, "EBX", m_context.Ebx, reg_value);
case lldb_ecx_i386:
return ReadRegisterHelper(CONTEXT_INTEGER, "ECX", m_context.Ecx, reg_value);
case lldb_edx_i386:
return ReadRegisterHelper(CONTEXT_INTEGER, "EDX", m_context.Edx, reg_value);
case lldb_edi_i386:
return ReadRegisterHelper(CONTEXT_INTEGER, "EDI", m_context.Edi, reg_value);
case lldb_esi_i386:
return ReadRegisterHelper(CONTEXT_INTEGER, "ESI", m_context.Esi, reg_value);
case lldb_ebp_i386:
return ReadRegisterHelper(CONTEXT_CONTROL, "EBP", m_context.Ebp, reg_value);
case lldb_esp_i386:
return ReadRegisterHelper(CONTEXT_CONTROL, "ESP", m_context.Esp, reg_value);
case lldb_eip_i386:
return ReadRegisterHelper(CONTEXT_CONTROL, "EIP", m_context.Eip, reg_value);
case lldb_eflags_i386:
return ReadRegisterHelper(CONTEXT_CONTROL, "EFLAGS", m_context.EFlags,
reg_value);
default:
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
LLDB_LOG(log, "Requested unknown register {0}", reg);
break;
}
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;
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
switch (reg) {
case lldb_eax_i386:
LLDB_LOG(log, "Write value {0:x} to EAX", reg_value.GetAsUInt32());
m_context.Eax = reg_value.GetAsUInt32();
break;
case lldb_ebx_i386:
LLDB_LOG(log, "Write value {0:x} to EBX", reg_value.GetAsUInt32());
m_context.Ebx = reg_value.GetAsUInt32();
break;
case lldb_ecx_i386:
LLDB_LOG(log, "Write value {0:x} to ECX", reg_value.GetAsUInt32());
m_context.Ecx = reg_value.GetAsUInt32();
break;
case lldb_edx_i386:
LLDB_LOG(log, "Write value {0:x} to EDX", reg_value.GetAsUInt32());
m_context.Edx = reg_value.GetAsUInt32();
break;
case lldb_edi_i386:
LLDB_LOG(log, "Write value {0:x} to EDI", reg_value.GetAsUInt32());
m_context.Edi = reg_value.GetAsUInt32();
break;
case lldb_esi_i386:
LLDB_LOG(log, "Write value {0:x} to ESI", reg_value.GetAsUInt32());
m_context.Esi = reg_value.GetAsUInt32();
break;
case lldb_ebp_i386:
LLDB_LOG(log, "Write value {0:x} to EBP", reg_value.GetAsUInt32());
m_context.Ebp = reg_value.GetAsUInt32();
break;
case lldb_esp_i386:
LLDB_LOG(log, "Write value {0:x} to ESP", reg_value.GetAsUInt32());
m_context.Esp = reg_value.GetAsUInt32();
break;
case lldb_eip_i386:
LLDB_LOG(log, "Write value {0:x} to EIP", reg_value.GetAsUInt32());
m_context.Eip = reg_value.GetAsUInt32();
break;
case lldb_eflags_i386:
LLDB_LOG(log, "Write value {0:x} to EFLAGS", reg_value.GetAsUInt32());
m_context.EFlags = reg_value.GetAsUInt32();
break;
default:
LLDB_LOG(log, "Write value {0:x} to unknown register {1}",
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 {
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_REGISTERS);
if ((m_context.ContextFlags & flags_required) != flags_required) {
LLDB_LOG(log, "Thread context doesn't have {0}", reg_name);
return false;
}
LLDB_LOG(log, "Read value {0:x} from {1}", value, reg_name);
reg_value.SetUInt32(value);
return true;
}

Some files were not shown because too many files have changed in this diff Show More