diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 18:01:57 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 18:01:57 +0000 |
commit | 88c643b6fec27eec436c8d138fee6346e92337d6 (patch) | |
tree | 82cd13b2f3cde1c9e5f79689ba4e6ba67694843f /source/Plugins/Process/Windows | |
parent | 94994d372d014ce4c8758b9605d63fae651bd8aa (diff) |
Notes
Diffstat (limited to 'source/Plugins/Process/Windows')
21 files changed, 0 insertions, 3443 deletions
diff --git a/source/Plugins/Process/Windows/Common/CMakeLists.txt b/source/Plugins/Process/Windows/Common/CMakeLists.txt deleted file mode 100644 index 0926290861833..0000000000000 --- a/source/Plugins/Process/Windows/Common/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -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 - ) diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp deleted file mode 100644 index 81ec25871c577..0000000000000 --- a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp +++ /dev/null @@ -1,520 +0,0 @@ -//===-- DebuggerThread.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DebuggerThread.h" -#include "ExceptionRecord.h" -#include "IDebugDelegate.h" - -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Host/ThreadLauncher.h" -#include "lldb/Host/windows/HostProcessWindows.h" -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/ProcessLauncherWindows.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/ProcessLaunchInfo.h" -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Predicate.h" -#include "lldb/Utility/Status.h" - -#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Threading.h" -#include "llvm/Support/raw_ostream.h" - -using namespace lldb; -using namespace lldb_private; - -namespace { -struct DebugLaunchContext { - DebugLaunchContext(DebuggerThread *thread, - const ProcessLaunchInfo &launch_info) - : m_thread(thread), m_launch_info(launch_info) {} - DebuggerThread *m_thread; - ProcessLaunchInfo m_launch_info; -}; - -struct DebugAttachContext { - DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, - const ProcessAttachInfo &attach_info) - : m_thread(thread), m_pid(pid), m_attach_info(attach_info) {} - DebuggerThread *m_thread; - lldb::pid_t m_pid; - ProcessAttachInfo m_attach_info; -}; -} // namespace - -DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) - : m_debug_delegate(debug_delegate), m_pid_to_detach(0), - m_is_shutting_down(false) { - m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); -} - -DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } - -Status DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath()); - - Status error; - DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); - HostThread slave_thread(ThreadLauncher::LaunchThread( - "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, - context, &error)); - - if (!error.Success()) - LLDB_LOG(log, "couldn't launch debugger thread. {0}", error); - - return error; -} - -Status DebuggerThread::DebugAttach(lldb::pid_t pid, - const ProcessAttachInfo &attach_info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "attaching to '{0}'", pid); - - Status error; - DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); - HostThread slave_thread(ThreadLauncher::LaunchThread( - "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, - context, &error)); - - if (!error.Success()) - LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, error); - - return error; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) { - DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); - lldb::thread_result_t result = - context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); - delete context; - return result; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) { - DebugAttachContext *context = static_cast<DebugAttachContext *>(data); - lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine( - context->m_pid, context->m_attach_info); - delete context; - return result; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( - const ProcessLaunchInfo &launch_info) { - // Grab a shared_ptr reference to this so that we know it won't get deleted - // until after the thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "preparing to launch '{0}' on background thread.", - launch_info.GetExecutableFile().GetPath()); - - Status error; - ProcessLauncherWindows launcher; - HostProcess process(launcher.LaunchProcess(launch_info, error)); - // If we couldn't create the process, notify waiters immediately. Otherwise - // enter the debug loop and wait until we get the create process debug - // notification. Note that if the process was created successfully, we can - // throw away the process handle we got from CreateProcess because Windows - // will give us another (potentially more useful?) handle when it sends us - // the CREATE_PROCESS_DEBUG_EVENT. - if (error.Success()) - DebugLoop(); - else - m_debug_delegate->OnDebuggerError(error, 0); - - return 0; -} - -lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( - lldb::pid_t pid, const ProcessAttachInfo &attach_info) { - // Grab a shared_ptr reference to this so that we know it won't get deleted - // until after the thread routine has exited. - std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "preparing to attach to process '{0}' on background thread.", - pid); - - if (!DebugActiveProcess((DWORD)pid)) { - Status error(::GetLastError(), eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, 0); - return 0; - } - - // The attach was successful, enter the debug loop. From here on out, this - // is no different than a create process operation, so all the same comments - // in DebugLaunch should apply from this point out. - DebugLoop(); - - return 0; -} - -Status DebuggerThread::StopDebugging(bool terminate) { - Status error; - - lldb::pid_t pid = m_process.GetProcessId(); - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "terminate = {0}, inferior={1}.", terminate, pid); - - // Set m_is_shutting_down to true if it was false. Return if it was already - // true. - bool expected = false; - if (!m_is_shutting_down.compare_exchange_strong(expected, true)) - return error; - - // Make a copy of the process, since the termination sequence will reset - // DebuggerThread's internal copy and it needs to remain open for the Wait - // operation. - HostProcess process_copy = m_process; - lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); - - if (terminate) { - if (handle != nullptr && handle != LLDB_INVALID_PROCESS) { - // Initiate the termination before continuing the exception, so that the - // next debug event we get is the exit process event, and not some other - // event. - BOOL terminate_suceeded = TerminateProcess(handle, 0); - LLDB_LOG(log, - "calling TerminateProcess({0}, 0) (inferior={1}), success={2}", - handle, pid, terminate_suceeded); - } else { - LLDB_LOG(log, - "NOT calling TerminateProcess because the inferior is not valid " - "({0}, 0) (inferior={1})", - handle, pid); - } - } - - // If we're stuck waiting for an exception to continue (e.g. the user is at a - // breakpoint messing around in the debugger), continue it now. But only - // AFTER calling TerminateProcess to make sure that the very next call to - // WaitForDebugEvent is an exit process event. - if (m_active_exception.get()) { - LLDB_LOG(log, "masking active exception"); - ContinueAsyncException(ExceptionResult::MaskException); - } - - if (!terminate) { - // Indicate that we want to detach. - m_pid_to_detach = GetProcess().GetProcessId(); - - // Force a fresh break so that the detach can happen from the debugger - // thread. - if (!::DebugBreakProcess( - GetProcess().GetNativeProcess().GetSystemHandle())) { - error.SetError(::GetLastError(), eErrorTypeWin32); - } - } - - LLDB_LOG(log, "waiting for detach from process {0} to complete.", pid); - - DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); - if (wait_result != WAIT_OBJECT_0) { - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "error: WaitForSingleObject({0}, 5000) returned {1}", - m_debugging_ended_event, wait_result); - } else - LLDB_LOG(log, "detach from process {0} completed successfully.", pid); - - if (!error.Success()) { - LLDB_LOG(log, "encountered an error while trying to stop process {0}. {1}", - pid, error); - } - return error; -} - -void DebuggerThread::ContinueAsyncException(ExceptionResult result) { - if (!m_active_exception.get()) - return; - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS | - WINDOWS_LOG_EXCEPTION); - LLDB_LOG(log, "broadcasting for inferior process {0}.", - m_process.GetProcessId()); - - m_active_exception.reset(); - m_exception_pred.SetValue(result, eBroadcastAlways); -} - -void DebuggerThread::FreeProcessHandles() { - m_process = HostProcess(); - m_main_thread = HostThread(); - if (m_image_file) { - ::CloseHandle(m_image_file); - m_image_file = nullptr; - } -} - -void DebuggerThread::DebugLoop() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - DEBUG_EVENT dbe = {}; - bool should_debug = true; - LLDB_LOGV(log, "Entering WaitForDebugEvent loop"); - while (should_debug) { - LLDB_LOGV(log, "Calling WaitForDebugEvent"); - BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); - if (wait_result) { - DWORD continue_status = DBG_CONTINUE; - switch (dbe.dwDebugEventCode) { - default: - llvm_unreachable("Unhandle debug event code!"); - case EXCEPTION_DEBUG_EVENT: { - ExceptionResult status = - HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); - - if (status == ExceptionResult::MaskException) - continue_status = DBG_CONTINUE; - else if (status == ExceptionResult::SendToApplication) - continue_status = DBG_EXCEPTION_NOT_HANDLED; - - break; - } - case CREATE_THREAD_DEBUG_EVENT: - continue_status = - HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); - break; - case CREATE_PROCESS_DEBUG_EVENT: - continue_status = - HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); - break; - case EXIT_THREAD_DEBUG_EVENT: - continue_status = - HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); - break; - case EXIT_PROCESS_DEBUG_EVENT: - continue_status = - HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); - should_debug = false; - break; - case LOAD_DLL_DEBUG_EVENT: - continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); - break; - case UNLOAD_DLL_DEBUG_EVENT: - continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); - break; - case OUTPUT_DEBUG_STRING_EVENT: - continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); - break; - case RIP_EVENT: - continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); - if (dbe.u.RipInfo.dwType == SLE_ERROR) - should_debug = false; - break; - } - - LLDB_LOGV(log, "calling ContinueDebugEvent({0}, {1}, {2}) on thread {3}.", - dbe.dwProcessId, dbe.dwThreadId, continue_status, - ::GetCurrentThreadId()); - - ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); - - if (m_detached) { - should_debug = false; - } - } else { - LLDB_LOG(log, "returned FALSE from WaitForDebugEvent. Error = {0}", - ::GetLastError()); - - should_debug = false; - } - } - FreeProcessHandles(); - - LLDB_LOG(log, "WaitForDebugEvent loop completed, exiting."); - ::SetEvent(m_debugging_ended_event); -} - -ExceptionResult -DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION); - if (m_is_shutting_down) { - // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic - // exception that - // we use simply to wake up the DebuggerThread so that we can close out the - // debug loop. - if (m_pid_to_detach != 0 && - info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { - LLDB_LOG(log, "Breakpoint exception is cue to detach from process {0:x}", - m_pid_to_detach.load()); - ::DebugActiveProcessStop(m_pid_to_detach); - m_detached = true; - } - - // Don't perform any blocking operations while we're shutting down. That - // will cause TerminateProcess -> WaitForSingleObject to time out. - return ExceptionResult::SendToApplication; - } - - bool first_chance = (info.dwFirstChance != 0); - - m_active_exception.reset( - new ExceptionRecord(info.ExceptionRecord, thread_id)); - LLDB_LOG(log, "encountered {0} chance exception {1:x} on thread {2:x}", - first_chance ? "first" : "second", - info.ExceptionRecord.ExceptionCode, thread_id); - - ExceptionResult result = - m_debug_delegate->OnDebugException(first_chance, *m_active_exception); - m_exception_pred.SetValue(result, eBroadcastNever); - - LLDB_LOG(log, "waiting for ExceptionPred != BreakInDebugger"); - result = *m_exception_pred.WaitForValueNotEqualTo( - ExceptionResult::BreakInDebugger); - - LLDB_LOG(log, "got ExceptionPred = {0}", (int)m_exception_pred.GetValue()); - return result; -} - -DWORD -DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); - LLDB_LOG(log, "Thread {0} spawned in process {1}", thread_id, - m_process.GetProcessId()); - HostThread thread(info.hThread); - thread.GetNativeThread().SetOwnsHandle(false); - m_debug_delegate->OnCreateThread(thread); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS); - uint32_t process_id = ::GetProcessId(info.hProcess); - - LLDB_LOG(log, "process {0} spawned", process_id); - - std::string thread_name; - llvm::raw_string_ostream name_stream(thread_name); - name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; - name_stream.flush(); - llvm::set_thread_name(thread_name); - - // info.hProcess and info.hThread are closed automatically by Windows when - // EXIT_PROCESS_DEBUG_EVENT is received. - m_process = HostProcess(info.hProcess); - ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); - m_main_thread = HostThread(info.hThread); - m_main_thread.GetNativeThread().SetOwnsHandle(false); - m_image_file = info.hFile; - - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); - m_debug_delegate->OnDebuggerConnected(load_addr); - - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); - LLDB_LOG(log, "Thread {0} exited with code {1} in process {2}", thread_id, - info.dwExitCode, m_process.GetProcessId()); - m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = - ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD); - LLDB_LOG(log, "process {0} exited with code {1}", m_process.GetProcessId(), - info.dwExitCode); - - m_debug_delegate->OnExitProcess(info.dwExitCode); - - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - if (info.hFile == nullptr) { - // Not sure what this is, so just ignore it. - LLDB_LOG(log, "Warning: Inferior {0} has a NULL file handle, returning...", - m_process.GetProcessId()); - return DBG_CONTINUE; - } - - std::vector<wchar_t> buffer(1); - DWORD required_size = - GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); - if (required_size > 0) { - buffer.resize(required_size + 1); - required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], - required_size, VOLUME_NAME_DOS); - std::string path_str_utf8; - llvm::convertWideToUTF8(buffer.data(), path_str_utf8); - llvm::StringRef path_str = path_str_utf8; - const char *path = path_str.data(); - if (path_str.startswith("\\\\?\\")) - path += 4; - - FileSpec file_spec(path); - ModuleSpec module_spec(file_spec); - lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); - - LLDB_LOG(log, "Inferior {0} - DLL '{1}' loaded at address {2:x}...", - m_process.GetProcessId(), path, info.lpBaseOfDll); - - m_debug_delegate->OnLoadDll(module_spec, load_addr); - } else { - LLDB_LOG( - log, - "Inferior {0} - Error {1} occurred calling GetFinalPathNameByHandle", - m_process.GetProcessId(), ::GetLastError()); - } - // Windows does not automatically close info.hFile, so we need to do it. - ::CloseHandle(info.hFile); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, - DWORD thread_id) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - LLDB_LOG(log, "process {0} unloading DLL at addr {1:x}.", - m_process.GetProcessId(), info.lpBaseOfDll); - - m_debug_delegate->OnUnloadDll( - reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, - DWORD thread_id) { - return DBG_CONTINUE; -} - -DWORD -DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT); - LLDB_LOG(log, "encountered error {0} (type={1}) in process {2} thread {3}", - info.dwError, info.dwType, m_process.GetProcessId(), thread_id); - - Status error(info.dwError, eErrorTypeWin32); - m_debug_delegate->OnDebuggerError(error, info.dwType); - - return DBG_CONTINUE; -} diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.h b/source/Plugins/Process/Windows/Common/DebuggerThread.h deleted file mode 100644 index 047d3ccb7296b..0000000000000 --- a/source/Plugins/Process/Windows/Common/DebuggerThread.h +++ /dev/null @@ -1,106 +0,0 @@ -//===-- 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/windows/windows.h" -#include "lldb/Utility/Predicate.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 diff --git a/source/Plugins/Process/Windows/Common/ExceptionRecord.h b/source/Plugins/Process/Windows/Common/ExceptionRecord.h deleted file mode 100644 index 1eec85d52c264..0000000000000 --- a/source/Plugins/Process/Windows/Common/ExceptionRecord.h +++ /dev/null @@ -1,80 +0,0 @@ -//===-- 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 diff --git a/source/Plugins/Process/Windows/Common/ForwardDecl.h b/source/Plugins/Process/Windows/Common/ForwardDecl.h deleted file mode 100644 index ce2af3ca4111a..0000000000000 --- a/source/Plugins/Process/Windows/Common/ForwardDecl.h +++ /dev/null @@ -1,42 +0,0 @@ -//===-- 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 diff --git a/source/Plugins/Process/Windows/Common/IDebugDelegate.h b/source/Plugins/Process/Windows/Common/IDebugDelegate.h deleted file mode 100644 index 73c285f1ecc79..0000000000000 --- a/source/Plugins/Process/Windows/Common/IDebugDelegate.h +++ /dev/null @@ -1,46 +0,0 @@ -//===-- 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 diff --git a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.cpp b/source/Plugins/Process/Windows/Common/LocalDebugDelegate.cpp deleted file mode 100644 index 92aa7e2678b95..0000000000000 --- a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.cpp +++ /dev/null @@ -1,73 +0,0 @@ -//===-- 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); -} diff --git a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.h b/source/Plugins/Process/Windows/Common/LocalDebugDelegate.h deleted file mode 100644 index 2cb479ccce8ab..0000000000000 --- a/source/Plugins/Process/Windows/Common/LocalDebugDelegate.h +++ /dev/null @@ -1,67 +0,0 @@ -//===-- 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 diff --git a/source/Plugins/Process/Windows/Common/NtStructures.h b/source/Plugins/Process/Windows/Common/NtStructures.h deleted file mode 100644 index 6826b98c769e7..0000000000000 --- a/source/Plugins/Process/Windows/Common/NtStructures.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- 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 diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp deleted file mode 100644 index 3fe5ab7804cba..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp +++ /dev/null @@ -1,1119 +0,0 @@ -//===-- ProcessWindows.cpp --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "ProcessWindows.h" - -// Windows includes -#include "lldb/Host/windows/windows.h" -#include <psapi.h> - -#include "lldb/Core/Module.h" -#include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/PluginManager.h" -#include "lldb/Core/Section.h" -#include "lldb/Host/FileSystem.h" -#include "lldb/Host/HostNativeProcessBase.h" -#include "lldb/Host/HostProcess.h" -#include "lldb/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Symbol/ObjectFile.h" -#include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Target/StopInfo.h" -#include "lldb/Target/Target.h" -#include "lldb/Utility/State.h" - -#include "llvm/Support/ConvertUTF.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Threading.h" -#include "llvm/Support/raw_ostream.h" - -#include "DebuggerThread.h" -#include "ExceptionRecord.h" -#include "ForwardDecl.h" -#include "LocalDebugDelegate.h" -#include "ProcessWindowsLog.h" -#include "TargetThreadWindows.h" - -using namespace lldb; -using namespace lldb_private; - -namespace { -std::string GetProcessExecutableName(HANDLE process_handle) { - std::vector<wchar_t> file_name; - DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit - DWORD copied = 0; - do { - file_name_size *= 2; - file_name.resize(file_name_size); - copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(), - file_name_size); - } while (copied >= file_name_size); - file_name.resize(copied); - std::string result; - llvm::convertWideToUTF8(file_name.data(), result); - return result; -} - -std::string GetProcessExecutableName(DWORD pid) { - std::string file_name; - HANDLE process_handle = - ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - if (process_handle != NULL) { - file_name = GetProcessExecutableName(process_handle); - ::CloseHandle(process_handle); - } - return file_name; -} - -DWORD ConvertLldbToWinApiProtect(uint32_t protect) { - // We also can process a read / write permissions here, but if the debugger - // will make later a write into the allocated memory, it will fail. To get - // around it is possible inside DoWriteMemory to remember memory permissions, - // allow write, write and restore permissions, but for now we process only - // the executable permission. - // - // TODO: Process permissions other than executable - if (protect & ePermissionsExecutable) - return PAGE_EXECUTE_READWRITE; - - return PAGE_READWRITE; -} - -} // anonymous namespace - -namespace lldb_private { - -// We store a pointer to this class in the ProcessWindows, so that we don't -// expose Windows-specific types and implementation details from a public -// header file. -class ProcessWindowsData { -public: - ProcessWindowsData(bool stop_at_entry) : m_stop_at_entry(stop_at_entry) { - m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - } - - ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); } - - Status m_launch_error; - DebuggerThreadSP m_debugger; - StopInfoSP m_pending_stop_info; - HANDLE m_initial_stop_event = nullptr; - bool m_initial_stop_received = false; - bool m_stop_at_entry; - std::map<lldb::tid_t, HostThread> m_new_threads; - std::set<lldb::tid_t> m_exited_threads; -}; - -ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp, - const FileSpec *) { - return ProcessSP(new ProcessWindows(target_sp, listener_sp)); -} - -void ProcessWindows::Initialize() { - static llvm::once_flag g_once_flag; - - llvm::call_once(g_once_flag, []() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance); - }); -} - -void ProcessWindows::Terminate() {} - -lldb_private::ConstString ProcessWindows::GetPluginNameStatic() { - static ConstString g_name("windows"); - return g_name; -} - -const char *ProcessWindows::GetPluginDescriptionStatic() { - return "Process plugin for Windows"; -} - -//------------------------------------------------------------------------------ -// Constructors and destructors. - -ProcessWindows::ProcessWindows(lldb::TargetSP target_sp, - lldb::ListenerSP listener_sp) - : lldb_private::Process(target_sp, listener_sp) {} - -ProcessWindows::~ProcessWindows() {} - -size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Status &error) { - error.SetErrorString("GetSTDOUT unsupported on Windows"); - return 0; -} - -size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Status &error) { - error.SetErrorString("GetSTDERR unsupported on Windows"); - return 0; -} - -size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, - Status &error) { - error.SetErrorString("PutSTDIN unsupported on Windows"); - return 0; -} - -//------------------------------------------------------------------------------ -// ProcessInterface protocol. - -lldb_private::ConstString ProcessWindows::GetPluginName() { - return GetPluginNameStatic(); -} - -uint32_t ProcessWindows::GetPluginVersion() { return 1; } - -Status ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS); - LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site, - bp_site->GetID(), bp_site->GetLoadAddress()); - - Status error = EnableSoftwareBreakpoint(bp_site); - if (!error.Success()) - LLDB_LOG(log, "error: {0}", error); - return error; -} - -Status ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS); - LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site, - bp_site->GetID(), bp_site->GetLoadAddress()); - - Status error = DisableSoftwareBreakpoint(bp_site); - - if (!error.Success()) - LLDB_LOG(log, "error: {0}", error); - return error; -} - -Status ProcessWindows::DoDetach(bool keep_stopped) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire the lock only long enough to get the DebuggerThread. - // StopDebugging() will trigger a call back into ProcessWindows which will - // also acquire the lock. Thus we have to release the lock before calling - // StopDebugging(). - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) { - LLDB_LOG(log, "state = {0}, but there is no active session.", - private_state); - return Status(); - } - - debugger_thread = m_session_data->m_debugger; - } - - Status error; - if (private_state != eStateExited && private_state != eStateDetached) { - LLDB_LOG(log, "detaching from process {0} while state = {1}.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - error = debugger_thread->StopDebugging(false); - if (error.Success()) { - SetPrivateState(eStateDetached); - } - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } else { - LLDB_LOG( - log, - "error: process {0} in state = {1}, but cannot destroy in this state.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - } - - return error; -} - -Status ProcessWindows::DoLaunch(Module *exe_module, - ProcessLaunchInfo &launch_info) { - // Even though m_session_data is accessed here, it is before a debugger - // thread has been kicked off. So there's no race conditions, and it - // shouldn't be necessary to acquire the mutex. - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - Status result; - - FileSpec working_dir = launch_info.GetWorkingDirectory(); - namespace fs = llvm::sys::fs; - if (working_dir) { - FileSystem::Instance().Resolve(working_dir); - if (!FileSystem::Instance().IsDirectory(working_dir)) { - result.SetErrorStringWithFormat("No such file or directory: %s", - working_dir.GetCString()); - return result; - } - } - - if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) { - StreamString stream; - stream.Printf("ProcessWindows unable to launch '%s'. ProcessWindows can " - "only be used for debug launches.", - launch_info.GetExecutableFile().GetPath().c_str()); - std::string message = stream.GetString(); - result.SetErrorString(message.c_str()); - - LLDB_LOG(log, "error: {0}", message); - return result; - } - - bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry); - m_session_data.reset(new ProcessWindowsData(stop_at_entry)); - - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - m_session_data->m_debugger.reset(new DebuggerThread(delegate)); - DebuggerThreadSP debugger = m_session_data->m_debugger; - - // Kick off the DebugLaunch asynchronously and wait for it to complete. - result = debugger->DebugLaunch(launch_info); - if (result.Fail()) { - LLDB_LOG(log, "failed launching '{0}'. {1}", - launch_info.GetExecutableFile().GetPath(), result); - return result; - } - - HostProcess process; - Status error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) { - LLDB_LOG(log, "failed launching '{0}'. {1}", - launch_info.GetExecutableFile().GetPath(), error); - return error; - } - - LLDB_LOG(log, "successfully launched '{0}'", - launch_info.GetExecutableFile().GetPath()); - - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the - // private state should already be set to eStateStopped as a result of - // hitting the initial breakpoint. If it was not set, the breakpoint should - // have already been resumed from and the private state should already be - // eStateRunning. - launch_info.SetProcessID(process.GetProcessId()); - SetID(process.GetProcessId()); - - return result; -} - -Status -ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid, - const ProcessAttachInfo &attach_info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - m_session_data.reset( - new ProcessWindowsData(!attach_info.GetContinueOnceAttached())); - - DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this())); - DebuggerThreadSP debugger(new DebuggerThread(delegate)); - - m_session_data->m_debugger = debugger; - - DWORD process_id = static_cast<DWORD>(pid); - Status error = debugger->DebugAttach(process_id, attach_info); - if (error.Fail()) { - LLDB_LOG( - log, - "encountered an error occurred initiating the asynchronous attach. {0}", - error); - return error; - } - - HostProcess process; - error = WaitForDebuggerConnection(debugger, process); - if (error.Fail()) { - LLDB_LOG(log, - "encountered an error waiting for the debugger to connect. {0}", - error); - return error; - } - - LLDB_LOG(log, "successfully attached to process with pid={0}", process_id); - - // We've hit the initial stop. If eLaunchFlagsStopAtEntry was specified, the - // private state should already be set to eStateStopped as a result of - // hitting the initial breakpoint. If it was not set, the breakpoint should - // have already been resumed from and the private state should already be - // eStateRunning. - SetID(process.GetProcessId()); - return error; -} - -Status ProcessWindows::DoResume() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - llvm::sys::ScopedLock lock(m_mutex); - Status error; - - StateType private_state = GetPrivateState(); - if (private_state == eStateStopped || private_state == eStateCrashed) { - LLDB_LOG(log, "process {0} is in state {1}. Resuming...", - m_session_data->m_debugger->GetProcess().GetProcessId(), - GetPrivateState()); - - ExceptionRecordSP active_exception = - m_session_data->m_debugger->GetActiveException().lock(); - if (active_exception) { - // Resume the process and continue processing debug events. Mask the - // exception so that from the process's view, there is no indication that - // anything happened. - m_session_data->m_debugger->ContinueAsyncException( - ExceptionResult::MaskException); - } - - LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize()); - - bool failed = false; - for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) { - auto thread = std::static_pointer_cast<TargetThreadWindows>( - m_thread_list.GetThreadAtIndex(i)); - Status result = thread->DoResume(); - if (result.Fail()) { - failed = true; - LLDB_LOG( - log, - "Trying to resume thread at index {0}, but failed with error {1}.", - i, result); - } - } - - if (failed) { - error.SetErrorString("ProcessWindows::DoResume failed"); - return error; - } else { - SetPrivateState(eStateRunning); - } - } else { - LLDB_LOG(log, "error: process {0} is in state {1}. Returning...", - m_session_data->m_debugger->GetProcess().GetProcessId(), - GetPrivateState()); - } - return error; -} - -Status ProcessWindows::DoDestroy() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - DebuggerThreadSP debugger_thread; - StateType private_state; - { - // Acquire this lock inside an inner scope, only long enough to get the - // DebuggerThread. StopDebugging() will trigger a call back into - // ProcessWindows which will acquire the lock again, so we need to not - // deadlock. - llvm::sys::ScopedLock lock(m_mutex); - - private_state = GetPrivateState(); - - if (!m_session_data) { - LLDB_LOG(log, "warning: state = {0}, but there is no active session.", - private_state); - return Status(); - } - - debugger_thread = m_session_data->m_debugger; - } - - Status error; - if (private_state != eStateExited && private_state != eStateDetached) { - LLDB_LOG(log, "Shutting down process {0} while state = {1}.", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - error = debugger_thread->StopDebugging(true); - - // By the time StopDebugging returns, there is no more debugger thread, so - // we can be assured that no other thread will race for the session data. - m_session_data.reset(); - } else { - LLDB_LOG(log, "cannot destroy process {0} while state = {1}", - debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(), - private_state); - } - - return error; -} - -Status ProcessWindows::DoHalt(bool &caused_stop) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - Status error; - StateType state = GetPrivateState(); - if (state == eStateStopped) - caused_stop = false; - else { - llvm::sys::ScopedLock lock(m_mutex); - caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess() - .GetNativeProcess() - .GetSystemHandle()); - if (!caused_stop) { - error.SetError(::GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "DebugBreakProcess failed with error {0}", error); - } - } - return error; -} - -void ProcessWindows::DidLaunch() { - ArchSpec arch_spec; - DidAttach(arch_spec); -} - -void ProcessWindows::DidAttach(ArchSpec &arch_spec) { - llvm::sys::ScopedLock lock(m_mutex); - - // The initial stop won't broadcast the state change event, so account for - // that here. - if (m_session_data && GetPrivateState() == eStateStopped && - m_session_data->m_stop_at_entry) - RefreshStateAfterStop(); -} - -void ProcessWindows::RefreshStateAfterStop() { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); - llvm::sys::ScopedLock lock(m_mutex); - - if (!m_session_data) { - LLDB_LOG(log, "no active session. Returning..."); - return; - } - - m_thread_list.RefreshStateAfterStop(); - - std::weak_ptr<ExceptionRecord> exception_record = - m_session_data->m_debugger->GetActiveException(); - ExceptionRecordSP active_exception = exception_record.lock(); - if (!active_exception) { - LLDB_LOG(log, - "there is no active exception in process {0}. Why is the " - "process stopped?", - m_session_data->m_debugger->GetProcess().GetProcessId()); - return; - } - - StopInfoSP stop_info; - m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID()); - ThreadSP stop_thread = m_thread_list.GetSelectedThread(); - if (!stop_thread) - return; - - switch (active_exception->GetExceptionCode()) { - case EXCEPTION_SINGLE_STEP: { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - const uint64_t pc = register_context->GetPC(); - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site && site->ValidForThisThread(stop_thread.get())) { - LLDB_LOG(log, - "Single-stepped onto a breakpoint in process {0} at " - "address {1:x} with breakpoint site {2}", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, - site->GetID()); - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, - site->GetID()); - stop_thread->SetStopInfo(stop_info); - } else { - LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID()); - stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread); - stop_thread->SetStopInfo(stop_info); - } - return; - } - - case EXCEPTION_BREAKPOINT: { - RegisterContextSP register_context = stop_thread->GetRegisterContext(); - - // The current EIP is AFTER the BP opcode, which is one byte. - uint64_t pc = register_context->GetPC() - 1; - - BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc)); - if (site) { - LLDB_LOG(log, - "detected breakpoint in process {0} at address {1:x} with " - "breakpoint site {2}", - m_session_data->m_debugger->GetProcess().GetProcessId(), pc, - site->GetID()); - - if (site->ValidForThisThread(stop_thread.get())) { - LLDB_LOG(log, - "Breakpoint site {0} is valid for this thread ({1:x}), " - "creating stop info.", - site->GetID(), stop_thread->GetID()); - - stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID( - *stop_thread, site->GetID()); - register_context->SetPC(pc); - } else { - LLDB_LOG(log, - "Breakpoint site {0} is not valid for this thread, " - "creating empty stop info.", - site->GetID()); - } - stop_thread->SetStopInfo(stop_info); - return; - } else { - // The thread hit a hard-coded breakpoint like an `int 3` or - // `__debugbreak()`. - LLDB_LOG(log, - "No breakpoint site matches for this thread. __debugbreak()? " - "Creating stop info with the exception."); - // FALLTHROUGH: We'll treat this as a generic exception record in the - // default case. - } - } - - default: { - std::string desc; - llvm::raw_string_ostream desc_stream(desc); - desc_stream << "Exception " - << llvm::format_hex(active_exception->GetExceptionCode(), 8) - << " encountered at address " - << llvm::format_hex(active_exception->GetExceptionAddress(), 8); - stop_info = StopInfo::CreateStopReasonWithException( - *stop_thread, desc_stream.str().c_str()); - stop_thread->SetStopInfo(stop_info); - LLDB_LOG(log, "{0}", desc_stream.str()); - return; - } - } -} - -bool ProcessWindows::CanDebug(lldb::TargetSP target_sp, - bool plugin_specified_by_name) { - if (plugin_specified_by_name) - return true; - - // For now we are just making sure the file exists for a given module - ModuleSP exe_module_sp(target_sp->GetExecutableModule()); - if (exe_module_sp.get()) - return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec()); - // However, if there is no executable module, we return true since we might - // be preparing to attach. - return true; -} - -bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, - ThreadList &new_thread_list) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_THREAD); - // Add all the threads that were previously running and for which we did not - // detect a thread exited event. - int new_size = 0; - int continued_threads = 0; - int exited_threads = 0; - int new_threads = 0; - - for (ThreadSP old_thread : old_thread_list.Threads()) { - lldb::tid_t old_thread_id = old_thread->GetID(); - auto exited_thread_iter = - m_session_data->m_exited_threads.find(old_thread_id); - if (exited_thread_iter == m_session_data->m_exited_threads.end()) { - new_thread_list.AddThread(old_thread); - ++new_size; - ++continued_threads; - LLDB_LOGV(log, "Thread {0} was running and is still running.", - old_thread_id); - } else { - LLDB_LOGV(log, "Thread {0} was running and has exited.", old_thread_id); - ++exited_threads; - } - } - - // Also add all the threads that are new since the last time we broke into - // the debugger. - for (const auto &thread_info : m_session_data->m_new_threads) { - ThreadSP thread(new TargetThreadWindows(*this, thread_info.second)); - thread->SetID(thread_info.first); - new_thread_list.AddThread(thread); - ++new_size; - ++new_threads; - LLDB_LOGV(log, "Thread {0} is new since last update.", thread_info.first); - } - - LLDB_LOG(log, "{0} new threads, {1} old threads, {2} exited threads.", - new_threads, continued_threads, exited_threads); - - m_session_data->m_new_threads.clear(); - m_session_data->m_exited_threads.clear(); - - return new_size > 0; -} - -bool ProcessWindows::IsAlive() { - StateType state = GetPrivateState(); - switch (state) { - case eStateCrashed: - case eStateDetached: - case eStateUnloaded: - case eStateExited: - case eStateInvalid: - return false; - default: - return true; - } -} - -size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf, - size_t size, Status &error) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - - if (!m_session_data) - return 0; - - LLDB_LOG(log, "attempting to read {0} bytes from address {1:x}", size, - vm_addr); - - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_read = 0; - if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, - buf, size, &bytes_read)) { - // Reading from the process can fail for a number of reasons - set the - // error code and make sure that the number of bytes read is set back to 0 - // because in some scenarios the value of bytes_read returned from the API - // is garbage. - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "reading failed with error: {0}", error); - bytes_read = 0; - } - return bytes_read; -} - -size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, - size_t size, Status &error) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - LLDB_LOG(log, "attempting to write {0} bytes into address {1:x}", size, - vm_addr); - - if (!m_session_data) { - LLDB_LOG(log, "cannot write, there is no active debugger connection."); - return 0; - } - - HostProcess process = m_session_data->m_debugger->GetProcess(); - void *addr = reinterpret_cast<void *>(vm_addr); - SIZE_T bytes_written = 0; - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (WriteProcessMemory(handle, addr, buf, size, &bytes_written)) - FlushInstructionCache(handle, addr, bytes_written); - else { - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "writing failed with error: {0}", error); - } - return bytes_written; -} - -lldb::addr_t ProcessWindows::DoAllocateMemory(size_t size, uint32_t permissions, - Status &error) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size, - permissions); - - if (!m_session_data) { - LLDB_LOG(log, "cannot allocate, there is no active debugger connection."); - error.SetErrorString( - "cannot allocate, there is no active debugger connection"); - return LLDB_INVALID_ADDRESS; - } - - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - auto protect = ConvertLldbToWinApiProtect(permissions); - auto result = VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect); - if (!result) { - error.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "allocating failed with error: {0}", error); - return LLDB_INVALID_ADDRESS; - } - - return reinterpret_cast<addr_t>(result); -} - -Status ProcessWindows::DoDeallocateMemory(lldb::addr_t ptr) { - Status result; - - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - llvm::sys::ScopedLock lock(m_mutex); - LLDB_LOG(log, "attempting to deallocate bytes at address {0}", ptr); - - if (!m_session_data) { - LLDB_LOG(log, "cannot deallocate, there is no active debugger connection."); - result.SetErrorString( - "cannot deallocate, there is no active debugger connection"); - return result; - } - - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (!VirtualFreeEx(handle, reinterpret_cast<LPVOID>(ptr), 0, MEM_RELEASE)) { - result.SetError(GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, "deallocating failed with error: {0}", result); - return result; - } - - return result; -} - -Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr, - MemoryRegionInfo &info) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY); - Status error; - llvm::sys::ScopedLock lock(m_mutex); - info.Clear(); - - if (!m_session_data) { - error.SetErrorString( - "GetMemoryRegionInfo called with no debugging session."); - LLDB_LOG(log, "error: {0}", error); - return error; - } - HostProcess process = m_session_data->m_debugger->GetProcess(); - lldb::process_t handle = process.GetNativeProcess().GetSystemHandle(); - if (handle == nullptr || handle == LLDB_INVALID_PROCESS) { - error.SetErrorString( - "GetMemoryRegionInfo called with an invalid target process."); - LLDB_LOG(log, "error: {0}", error); - return error; - } - - LLDB_LOG(log, "getting info for address {0:x}", vm_addr); - - void *addr = reinterpret_cast<void *>(vm_addr); - MEMORY_BASIC_INFORMATION mem_info = {}; - SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info)); - if (result == 0) { - if (::GetLastError() == ERROR_INVALID_PARAMETER) { - // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with - // an address past the highest accessible address. We should return a - // range from the vm_addr to LLDB_INVALID_ADDRESS - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - info.SetMapped(MemoryRegionInfo::eNo); - return error; - } else { - error.SetError(::GetLastError(), eErrorTypeWin32); - LLDB_LOG(log, - "VirtualQueryEx returned error {0} while getting memory " - "region info for address {1:x}", - error, vm_addr); - return error; - } - } - - // Protect bits are only valid for MEM_COMMIT regions. - if (mem_info.State == MEM_COMMIT) { - const bool readable = IsPageReadable(mem_info.Protect); - const bool executable = IsPageExecutable(mem_info.Protect); - const bool writable = IsPageWritable(mem_info.Protect); - info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - info.SetExecutable(executable ? MemoryRegionInfo::eYes - : MemoryRegionInfo::eNo); - info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo); - } else { - info.SetReadable(MemoryRegionInfo::eNo); - info.SetExecutable(MemoryRegionInfo::eNo); - info.SetWritable(MemoryRegionInfo::eNo); - } - - // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE. - if (mem_info.State != MEM_FREE) { - info.GetRange().SetRangeBase( - reinterpret_cast<addr_t>(mem_info.AllocationBase)); - info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) + - mem_info.RegionSize); - info.SetMapped(MemoryRegionInfo::eYes); - } else { - // In the unmapped case we need to return the distance to the next block of - // memory. VirtualQueryEx nearly does that except that it gives the - // distance from the start of the page containing vm_addr. - SYSTEM_INFO data; - GetSystemInfo(&data); - DWORD page_offset = vm_addr % data.dwPageSize; - info.GetRange().SetRangeBase(vm_addr); - info.GetRange().SetByteSize(mem_info.RegionSize - page_offset); - info.SetMapped(MemoryRegionInfo::eNo); - } - - error.SetError(::GetLastError(), eErrorTypeWin32); - LLDB_LOGV(log, - "Memory region info for address {0}: readable={1}, " - "executable={2}, writable={3}", - vm_addr, info.GetReadable(), info.GetExecutable(), - info.GetWritable()); - return error; -} - -lldb::addr_t ProcessWindows::GetImageInfoAddress() { - Target &target = GetTarget(); - ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile(); - Address addr = obj_file->GetImageInfoAddress(&target); - if (addr.IsValid()) - return addr.GetLoadAddress(&target); - else - return LLDB_INVALID_ADDRESS; -} - -void ProcessWindows::OnExitProcess(uint32_t exit_code) { - // No need to acquire the lock since m_session_data isn't accessed. - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code); - - TargetSP target = CalculateTarget(); - if (target) { - ModuleSP executable_module = target->GetExecutableModule(); - ModuleList unloaded_modules; - unloaded_modules.Append(executable_module); - target->ModulesDidUnload(unloaded_modules, true); - } - - SetProcessExitStatus(GetID(), true, 0, exit_code); - SetPrivateState(eStateExited); - - // If the process exits before any initial stop then notify the debugger - // of the error otherwise WaitForDebuggerConnection() will be blocked. - // An example of this issue is when a process fails to load a dependent DLL. - if (m_session_data && !m_session_data->m_initial_stop_received) { - Status error(exit_code, eErrorTypeWin32); - OnDebuggerError(error, 0); - } -} - -void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) { - DebuggerThreadSP debugger = m_session_data->m_debugger; - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}", - debugger->GetProcess().GetProcessId(), image_base); - - ModuleSP module = GetTarget().GetExecutableModule(); - if (!module) { - // During attach, we won't have the executable module, so find it now. - const DWORD pid = debugger->GetProcess().GetProcessId(); - const std::string file_name = GetProcessExecutableName(pid); - if (file_name.empty()) { - return; - } - - FileSpec executable_file(file_name); - FileSystem::Instance().Resolve(executable_file); - ModuleSpec module_spec(executable_file); - Status error; - module = GetTarget().GetSharedModule(module_spec, &error); - if (!module) { - return; - } - - GetTarget().SetExecutableModule(module, eLoadDependentsNo); - } - - bool load_addr_changed; - module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); - - // Add the main executable module to the list of pending module loads. We - // can't call GetTarget().ModulesDidLoad() here because we still haven't - // returned from DoLaunch() / DoAttach() yet so the target may not have set - // the process instance to `this` yet. - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wmain_thread = - debugger->GetMainThread().GetNativeThread(); - m_session_data->m_new_threads[wmain_thread.GetThreadId()] = - debugger->GetMainThread(); -} - -ExceptionResult -ProcessWindows::OnDebugException(bool first_chance, - const ExceptionRecord &record) { - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION); - llvm::sys::ScopedLock lock(m_mutex); - - // FIXME: Without this check, occasionally when running the test suite there - // is - // an issue where m_session_data can be null. It's not clear how this could - // happen but it only surfaces while running the test suite. In order to - // properly diagnose this, we probably need to first figure allow the test - // suite to print out full lldb logs, and then add logging to the process - // plugin. - if (!m_session_data) { - LLDB_LOG(log, - "Debugger thread reported exception {0:x} at address {1:x}, " - "but there is no session.", - record.GetExceptionCode(), record.GetExceptionAddress()); - return ExceptionResult::SendToApplication; - } - - if (!first_chance) { - // Not any second chance exception is an application crash by definition. - // It may be an expression evaluation crash. - SetPrivateState(eStateStopped); - } - - ExceptionResult result = ExceptionResult::SendToApplication; - switch (record.GetExceptionCode()) { - case EXCEPTION_BREAKPOINT: - // Handle breakpoints at the first chance. - result = ExceptionResult::BreakInDebugger; - - if (!m_session_data->m_initial_stop_received) { - LLDB_LOG( - log, - "Hit loader breakpoint at address {0:x}, setting initial stop event.", - record.GetExceptionAddress()); - m_session_data->m_initial_stop_received = true; - ::SetEvent(m_session_data->m_initial_stop_event); - } else { - LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.", - record.GetExceptionAddress()); - } - SetPrivateState(eStateStopped); - break; - case EXCEPTION_SINGLE_STEP: - result = ExceptionResult::BreakInDebugger; - SetPrivateState(eStateStopped); - break; - default: - LLDB_LOG(log, - "Debugger thread reported exception {0:x} at address {1:x} " - "(first_chance={2})", - record.GetExceptionCode(), record.GetExceptionAddress(), - first_chance); - // For non-breakpoints, give the application a chance to handle the - // exception first. - if (first_chance) - result = ExceptionResult::SendToApplication; - else - result = ExceptionResult::BreakInDebugger; - } - - return result; -} - -void ProcessWindows::OnCreateThread(const HostThread &new_thread) { - llvm::sys::ScopedLock lock(m_mutex); - const HostThreadWindows &wnew_thread = new_thread.GetNativeThread(); - m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread; -} - -void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) { - llvm::sys::ScopedLock lock(m_mutex); - - // On a forced termination, we may get exit thread events after the session - // data has been cleaned up. - if (!m_session_data) - return; - - // A thread may have started and exited before the debugger stopped allowing a - // refresh. - // Just remove it from the new threads list in that case. - auto iter = m_session_data->m_new_threads.find(thread_id); - if (iter != m_session_data->m_new_threads.end()) - m_session_data->m_new_threads.erase(iter); - else - m_session_data->m_exited_threads.insert(thread_id); -} - -void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec, - lldb::addr_t module_addr) { - // Confusingly, there is no Target::AddSharedModule. Instead, calling - // GetSharedModule() with a new module will add it to the module list and - // return a corresponding ModuleSP. - Status error; - ModuleSP module = GetTarget().GetSharedModule(module_spec, &error); - bool load_addr_changed = false; - module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed); - - ModuleList loaded_modules; - loaded_modules.Append(module); - GetTarget().ModulesDidLoad(loaded_modules); -} - -void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) { - Address resolved_addr; - if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) { - ModuleSP module = resolved_addr.GetModule(); - if (module) { - ModuleList unloaded_modules; - unloaded_modules.Append(module); - GetTarget().ModulesDidUnload(unloaded_modules, false); - } - } -} - -void ProcessWindows::OnDebugString(const std::string &string) {} - -void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) { - llvm::sys::ScopedLock lock(m_mutex); - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS); - - if (m_session_data->m_initial_stop_received) { - // This happened while debugging. Do we shutdown the debugging session, - // try to continue, or do something else? - LLDB_LOG(log, - "Error {0} occurred during debugging. Unexpected behavior " - "may result. {1}", - error.GetError(), error); - } else { - // If we haven't actually launched the process yet, this was an error - // launching the process. Set the internal error and signal the initial - // stop event so that the DoLaunch method wakes up and returns a failure. - m_session_data->m_launch_error = error; - ::SetEvent(m_session_data->m_initial_stop_event); - LLDB_LOG( - log, - "Error {0} occurred launching the process before the initial stop. {1}", - error.GetError(), error); - return; - } -} - -Status ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger, - HostProcess &process) { - Status result; - Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS | - WINDOWS_LOG_BREAKPOINTS); - LLDB_LOG(log, "Waiting for loader breakpoint."); - - // Block this function until we receive the initial stop from the process. - if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == - WAIT_OBJECT_0) { - LLDB_LOG(log, "hit loader breakpoint, returning."); - - process = debugger->GetProcess(); - return m_session_data->m_launch_error; - } else - return Status(::GetLastError(), eErrorTypeWin32); -} - -// The Windows page protection bits are NOT independent masks that can be -// bitwise-ORed together. For example, PAGE_EXECUTE_READ is not (PAGE_EXECUTE -// | PAGE_READ). To test for an access type, it's necessary to test for any of -// the bits that provide that access type. -bool ProcessWindows::IsPageReadable(uint32_t protect) { - return (protect & PAGE_NOACCESS) == 0; -} - -bool ProcessWindows::IsPageWritable(uint32_t protect) { - return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY | - PAGE_READWRITE | PAGE_WRITECOPY)) != 0; -} - -bool ProcessWindows::IsPageExecutable(uint32_t protect) { - return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | - PAGE_EXECUTE_WRITECOPY)) != 0; -} - -} // namespace lldb_private diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.h b/source/Plugins/Process/Windows/Common/ProcessWindows.h deleted file mode 100644 index 00e384f584080..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindows.h +++ /dev/null @@ -1,121 +0,0 @@ -//===-- 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_ - -#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; - lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, - Status &error) override; - Status DoDeallocateMemory(lldb::addr_t ptr) 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_ diff --git a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp deleted file mode 100644 index 386e9a5816c5f..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.cpp +++ /dev/null @@ -1,41 +0,0 @@ -//===-- 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() {} - - - - - - - - - diff --git a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h b/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h deleted file mode 100644 index b7f59c7081431..0000000000000 --- a/source/Plugins/Process/Windows/Common/ProcessWindowsLog.h +++ /dev/null @@ -1,36 +0,0 @@ -//===-- 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_ diff --git a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp b/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp deleted file mode 100644 index 90d43b2cf8284..0000000000000 --- a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//===-- 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; - - 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; -} diff --git a/source/Plugins/Process/Windows/Common/RegisterContextWindows.h b/source/Plugins/Process/Windows/Common/RegisterContextWindows.h deleted file mode 100644 index bd09295c2f238..0000000000000 --- a/source/Plugins/Process/Windows/Common/RegisterContextWindows.h +++ /dev/null @@ -1,67 +0,0 @@ -//===-- 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_ diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp deleted file mode 100644 index b121dc7bf15ea..0000000000000 --- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp +++ /dev/null @@ -1,147 +0,0 @@ -//===-- 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 "lldb/Utility/Log.h" -#include "lldb/Utility/Logging.h" -#include "lldb/Utility/State.h" - -#include "Plugins/Process/Utility/UnwindLLDB.h" -#include "ProcessWindows.h" -#include "ProcessWindowsLog.h" -#include "TargetThreadWindows.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_thread_reg_ctx_sp(), 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 = CreateRegisterContextForFrame(nullptr); - - return m_reg_context_sp; -} - -RegisterContextSP -TargetThreadWindows::CreateRegisterContextForFrame(StackFrame *frame) { - RegisterContextSP reg_ctx_sp; - uint32_t concrete_frame_idx = 0; - Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD)); - - if (frame) - concrete_frame_idx = frame->GetConcreteFrameIndex(); - - if (concrete_frame_idx == 0) { - if (!m_thread_reg_ctx_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 - LLDB_LOG(log, "This is a Wow64 process, we should create a " - "RegisterContextWindows_Wow64, but we don't."); -#else - m_thread_reg_ctx_sp.reset( - new RegisterContextWindows_x86(*this, concrete_frame_idx)); -#endif - break; - case llvm::Triple::x86_64: -#if defined(_WIN64) - m_thread_reg_ctx_sp.reset( - new RegisterContextWindows_x64(*this, concrete_frame_idx)); -#else - LLDB_LOG(log, "LLDB is 32-bit, but the target process is 64-bit."); -#endif - default: - break; - } - } - reg_ctx_sp = m_thread_reg_ctx_sp; - } else { - Unwind *unwinder = GetUnwinder(); - if (unwinder != nullptr) - reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame); - } - - return reg_ctx_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) - m_unwinder_ap.reset(new UnwindLLDB(*this)); - return m_unwinder_ap.get(); -} - -Status TargetThreadWindows::DoResume() { - StateType resume_state = GetTemporaryResumeState(); - StateType current_state = GetState(); - if (resume_state == current_state) - return Status(); - - 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 { - // ResumeThread returns -1 on error, or the thread's *previous* suspend - // count on success. This means that the return value is 1 when the thread - // was restarted. Note that DWORD is an unsigned int, so we need to - // explicitly compare with -1. - previous_suspend_count = ::ResumeThread(thread_handle); - - if (previous_suspend_count == (DWORD)-1) - return Status(::GetLastError(), eErrorTypeWin32); - - } while (previous_suspend_count > 1); - } - - return Status(); -} diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.h b/source/Plugins/Process/Windows/Common/TargetThreadWindows.h deleted file mode 100644 index 952c0f55b57f3..0000000000000 --- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.h +++ /dev/null @@ -1,50 +0,0 @@ -//===-- 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; - - Status DoResume(); - - HostThread GetHostThread() const { return m_host_thread; } - -private: - lldb::RegisterContextSP m_thread_reg_ctx_sp; - HostThread m_host_thread; -}; -} // namespace lldb_private - -#endif diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp deleted file mode 100644 index 584136a6e5bb4..0000000000000 --- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp +++ /dev/null @@ -1,341 +0,0 @@ -//===-- 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/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-private-types.h" - -#include "RegisterContextWindows_x64.h" -#include "Plugins/Process/Utility/RegisterContext_x86.h" -#include "TargetThreadWindows.h" -#include "Plugins/Process/Utility/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, - eRegisterIndexRbp, - eRegisterIndexRsp, - eRegisterIndexR8, - eRegisterIndexR9, - eRegisterIndexR10, - eRegisterIndexR11, - eRegisterIndexR12, - eRegisterIndexR13, - eRegisterIndexR14, - eRegisterIndexR15, - 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_REGNUM_GENERIC_ARG1, - LLDB_INVALID_REGNUM, lldb_rcx_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(rdx, nullptr), - {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG2, - 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(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(r8, nullptr), - {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG3, - LLDB_INVALID_REGNUM, lldb_r8_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r9, nullptr), - {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG4, - LLDB_INVALID_REGNUM, lldb_r9_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r10, nullptr), - {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_REGNUM_GENERIC_ARG5, - LLDB_INVALID_REGNUM, lldb_r10_x86_64}, - nullptr, - nullptr}, - {DEFINE_GPR(r11, nullptr), - {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_REGNUM_GENERIC_ARG6, - 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(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, - eRegisterIndexRbp, eRegisterIndexRsp, eRegisterIndexR8, - eRegisterIndexR9, eRegisterIndexR10, eRegisterIndexR11, - eRegisterIndexR12, eRegisterIndexR13, eRegisterIndexR14, - eRegisterIndexR15, 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 ®_value) { - if (!CacheAllRegisterValues()) - return false; - - if (reg_info == nullptr) - 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 ®_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); -} diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h deleted file mode 100644 index 62cedc8fbab04..0000000000000 --- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h +++ /dev/null @@ -1,48 +0,0 @@ -//===-- 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 ®_value) override; - - bool WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; -}; -} - -#endif // #ifndef liblldb_RegisterContextWindows_x64_H_ diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp deleted file mode 100644 index e012f9105f31a..0000000000000 --- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ /dev/null @@ -1,287 +0,0 @@ -//===-- 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/Host/windows/HostThreadWindows.h" -#include "lldb/Host/windows/windows.h" -#include "lldb/Utility/RegisterValue.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-private-types.h" - -#include "ProcessWindowsLog.h" -#include "RegisterContextWindows_x86.h" -#include "Plugins/Process/Utility/RegisterContext_x86.h" -#include "TargetThreadWindows.h" -#include "Plugins/Process/Utility/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 ®_value) { - if (!CacheAllRegisterValues()) - return false; - - if (reg_info == nullptr) - 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 ®_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 ®_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; -} diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h deleted file mode 100644 index aae645fdb5a3e..0000000000000 --- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h +++ /dev/null @@ -1,52 +0,0 @@ -//===-- RegisterContextWindows_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_RegisterContextWindows_x86_H_ -#define liblldb_RegisterContextWindows_x86_H_ - -#include "RegisterContextWindows.h" -#include "lldb/lldb-forward.h" - -namespace lldb_private { - -class Thread; - -class RegisterContextWindows_x86 : public RegisterContextWindows { -public: - //------------------------------------------------------------------ - // Constructors and Destructors - //------------------------------------------------------------------ - RegisterContextWindows_x86(Thread &thread, uint32_t concrete_frame_idx); - - virtual ~RegisterContextWindows_x86(); - - //------------------------------------------------------------------ - // 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 ®_value) override; - - bool WriteRegister(const RegisterInfo *reg_info, - const RegisterValue ®_value) override; - -private: - bool ReadRegisterHelper(DWORD flags_required, const char *reg_name, - DWORD value, RegisterValue ®_value) const; -}; -} - -#endif // #ifndef liblldb_RegisterContextWindows_x86_H_ |