summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Windows
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Windows')
-rw-r--r--lldb/source/Plugins/Process/Windows/CMakeLists.txt5
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugDriverThread.cpp247
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugDriverThread.h79
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.cpp55
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.h70
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugMonitorMessages.cpp62
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugMonitorMessages.h86
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugOneProcessThread.cpp227
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugOneProcessThread.h63
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugProcessLauncher.cpp38
-rw-r--r--lldb/source/Plugins/Process/Windows/DebugProcessLauncher.h40
-rw-r--r--lldb/source/Plugins/Process/Windows/ProcessWindows.cpp34
-rw-r--r--lldb/source/Plugins/Process/Windows/ProcessWindows.h15
-rw-r--r--lldb/source/Plugins/Process/Windows/SlaveMessages.h86
14 files changed, 1100 insertions, 7 deletions
diff --git a/lldb/source/Plugins/Process/Windows/CMakeLists.txt b/lldb/source/Plugins/Process/Windows/CMakeLists.txt
index 55a9be83f04..b128d17533f 100644
--- a/lldb/source/Plugins/Process/Windows/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Windows/CMakeLists.txt
@@ -4,6 +4,11 @@ include_directories(.)
include_directories(../Utility)
add_lldb_library(lldbPluginProcessWindows
+ DebugMonitorMessages.cpp
+ DebugMonitorMessageResults.cpp
+ DebugOneProcessThread.cpp
+ DebugProcessLauncher.cpp
+ DebugDriverThread.cpp
ProcessWindows.cpp
)
diff --git a/lldb/source/Plugins/Process/Windows/DebugDriverThread.cpp b/lldb/source/Plugins/Process/Windows/DebugDriverThread.cpp
new file mode 100644
index 00000000000..16a6c89a684
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugDriverThread.cpp
@@ -0,0 +1,247 @@
+//===-- DebugDriverThread.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugDriverThread.h"
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+#include "DebugOneProcessThread.h"
+#include "SlaveMessages.h"
+
+#include "lldb/Core/Log.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Target/Process.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugDriverThread *DebugDriverThread::m_instance = NULL;
+
+DebugDriverThread::DebugDriverThread()
+{
+ m_monitor_thread = ThreadLauncher::LaunchThread("lldb.plugin.process-windows.monitor-thread", MonitorThread, this, nullptr);
+ m_shutdown_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_monitor_event = ::CreateEvent(NULL, FALSE, FALSE, NULL);
+ ::CreatePipe(&m_monitor_pipe_read, &m_monitor_pipe_write, NULL, 1024);
+}
+
+DebugDriverThread::~DebugDriverThread()
+{
+}
+
+void
+DebugDriverThread::Initialize()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("DebugDriverThread::Initialize");
+
+ m_instance = new DebugDriverThread();
+}
+
+void
+DebugDriverThread::Teardown()
+{
+ m_instance->Shutdown();
+
+ delete m_instance;
+ m_instance = nullptr;
+}
+
+void
+DebugDriverThread::Shutdown()
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (log)
+ log->Printf("DebugDriverThread::Shutdown");
+
+ if (!m_shutdown_event)
+ return;
+ ::SetEvent(m_shutdown_event);
+ m_monitor_thread.Join(nullptr);
+
+ ::CloseHandle(m_shutdown_event);
+ ::CloseHandle(m_monitor_event);
+ ::CloseHandle(m_monitor_pipe_read);
+ ::CloseHandle(m_monitor_pipe_write);
+
+ m_shutdown_event = nullptr;
+ m_monitor_event = nullptr;
+ m_monitor_pipe_read = nullptr;
+ m_monitor_pipe_write = nullptr;
+}
+
+DebugDriverThread &
+DebugDriverThread::GetInstance()
+{
+ return *m_instance;
+}
+
+void
+DebugDriverThread::PostDebugMessage(const DebugMonitorMessage *message)
+{
+ message->Retain();
+ if (!::WriteFile(m_monitor_pipe_write, &message, sizeof(message), NULL, NULL))
+ {
+ message->Release();
+ return;
+ }
+
+ ::SetEvent(m_monitor_event);
+}
+
+const DebugMonitorMessageResult *
+DebugDriverThread::HandleMonitorMessage(const DebugMonitorMessage *message)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ switch (message->GetMessageType())
+ {
+ case MonitorMessageType::eLaunchProcess:
+ {
+ const auto *launch_message = static_cast<const LaunchProcessMessage *>(message);
+ return HandleMonitorMessage(launch_message);
+ }
+ default:
+ if (log)
+ log->Printf("DebugDriverThread received unknown message type %d.", message->GetMessageType());
+ return nullptr;
+ }
+}
+
+const LaunchProcessMessageResult *
+DebugDriverThread::HandleMonitorMessage(const LaunchProcessMessage *launch_message)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ const char *exe = launch_message->GetLaunchInfo().GetExecutableFile().GetPath().c_str();
+ if (log)
+ log->Printf("DebugDriverThread launching process '%s'.", exe);
+
+ // Create a DebugOneProcessThread which will do the actual creation and enter a debug loop on
+ // a background thread, only returning after the process has been created on the background
+ // thread.
+ std::shared_ptr<DebugOneProcessThread> slave(new DebugOneProcessThread(m_monitor_thread));
+ const LaunchProcessMessageResult *result = slave->DebugLaunch(launch_message);
+ if (result && result->GetError().Success())
+ {
+ if (log)
+ log->Printf("DebugDriverThread launched process '%s' with PID %d.", exe, result->GetProcess().GetProcessId());
+ m_debugged_processes.insert(std::make_pair(result->GetProcess().GetProcessId(), slave));
+ }
+ else
+ {
+ if (log)
+ log->Printf("An error occured launching process '%s' -- %s.", exe, result->GetError().AsCString());
+ }
+ return result;
+}
+
+void
+DebugDriverThread::HandleSlaveEvent(const SlaveMessageProcessExited &message)
+{
+ lldb::pid_t pid = message.GetProcess().GetProcessId();
+
+ m_debugged_processes.erase(pid);
+
+ Process::SetProcessExitStatus(nullptr, pid, true, 0, message.GetExitCode());
+}
+
+void
+DebugDriverThread::HandleSlaveEvent(const SlaveMessageRipEvent &message)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ lldb::pid_t pid = message.GetProcess().GetProcessId();
+ m_debugged_processes.erase(pid);
+
+ if (log)
+ {
+ log->Printf("An error was encountered while debugging process %d. Debugging has been terminated. Error = s.", pid,
+ message.GetError().AsCString());
+ }
+}
+
+bool
+DebugDriverThread::ProcessMonitorMessages()
+{
+ DWORD bytes_available = 0;
+ if (!PeekNamedPipe(m_monitor_pipe_read, NULL, 0, NULL, &bytes_available, NULL))
+ {
+ // There's some kind of error with the named pipe. Fail out and stop monitoring.
+ return false;
+ }
+
+ if (bytes_available <= 0)
+ {
+ // There's no data available, but the operation succeeded.
+ return true;
+ }
+
+ int count = bytes_available / sizeof(DebugMonitorMessage *);
+ std::vector<DebugMonitorMessage *> messages(count);
+ if (!::ReadFile(m_monitor_pipe_read, &messages[0], bytes_available, NULL, NULL))
+ return false;
+
+ for (DebugMonitorMessage *message : messages)
+ {
+ const DebugMonitorMessageResult *result = HandleMonitorMessage(message);
+ message->CompleteMessage(result);
+ message->Release();
+ }
+ return true;
+}
+
+lldb::thread_result_t
+DebugDriverThread::MonitorThread(void *data)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessWindows DebugDriverThread starting up.");
+
+ DebugDriverThread *monitor_thread = static_cast<DebugDriverThread *>(data);
+ const int kMonitorEventIndex = 0;
+ const int kShutdownEventIndex = 1;
+
+ Error error;
+ HANDLE events[kShutdownEventIndex + 1];
+ events[kMonitorEventIndex] = monitor_thread->m_monitor_event;
+ events[kShutdownEventIndex] = monitor_thread->m_shutdown_event;
+
+ while (true)
+ {
+ bool exit = false;
+ // See if any new processes are ready for debug monitoring.
+ DWORD result = WaitForMultipleObjectsEx(llvm::array_lengthof(events), events, FALSE, 1000, TRUE);
+ switch (result)
+ {
+ case WAIT_OBJECT_0 + kMonitorEventIndex:
+ // LLDB is telling us to do something. Process pending messages in our queue.
+ monitor_thread->ProcessMonitorMessages();
+ break;
+ case WAIT_OBJECT_0 + kShutdownEventIndex:
+ error.SetErrorString("Shutdown event received.");
+ exit = true;
+ break;
+ case WAIT_TIMEOUT:
+ case WAIT_IO_COMPLETION:
+ break;
+ default:
+ error.SetError(GetLastError(), eErrorTypeWin32);
+ exit = true;
+ break;
+ }
+ if (exit)
+ break;
+ }
+
+ if (log)
+ log->Printf("ProcessWindows Debug monitor thread exiting. %s", error.AsCString());
+ return 0;
+}
diff --git a/lldb/source/Plugins/Process/Windows/DebugDriverThread.h b/lldb/source/Plugins/Process/Windows/DebugDriverThread.h
new file mode 100644
index 00000000000..720e02e78f8
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugDriverThread.h
@@ -0,0 +1,79 @@
+//===-- DebugDriverThread.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_DebugDriverThread_H_
+#define liblldb_Plugins_Process_Windows_DebugDriverThread_H_
+
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/lldb-types.h"
+
+#include <map>
+
+class ProcessWindows;
+
+namespace lldb_private
+{
+class DebugMonitorMessage;
+class DebugMonitorMessageResult;
+class DebugOneProcessThread;
+class LaunchProcessMessage;
+class LaunchProcessMessageResult;
+
+class SlaveMessageProcessExited;
+class SlaveMessageRipEvent;
+
+//----------------------------------------------------------------------
+// DebugDriverThread
+//
+// Runs a background thread that pumps a queue from the application to tell the
+// debugger to do different things like launching processes, attaching to
+// processes, etc.
+//----------------------------------------------------------------------
+class DebugDriverThread
+{
+ friend class DebugOneProcessThread;
+
+ public:
+ virtual ~DebugDriverThread();
+
+ static void Initialize();
+ static void Teardown();
+ static DebugDriverThread &GetInstance();
+
+ void PostDebugMessage(const DebugMonitorMessage *message);
+
+ private:
+ DebugDriverThread();
+
+ void Shutdown();
+
+ bool ProcessMonitorMessages();
+ const DebugMonitorMessageResult *HandleMonitorMessage(const DebugMonitorMessage *message);
+ const LaunchProcessMessageResult *HandleMonitorMessage(const LaunchProcessMessage *launch_message);
+
+ // Slave message handlers. These are invoked by the
+ void HandleSlaveEvent(const SlaveMessageProcessExited &message);
+ void HandleSlaveEvent(const SlaveMessageRipEvent &message);
+
+ static DebugDriverThread *m_instance;
+
+ std::map<lldb::pid_t, std::shared_ptr<DebugOneProcessThread>> m_debugged_processes;
+
+ HANDLE m_monitor_event;
+ HANDLE m_shutdown_event;
+ HANDLE m_monitor_pipe_read;
+ HANDLE m_monitor_pipe_write;
+ lldb_private::HostThread m_monitor_thread;
+
+ static lldb::thread_result_t MonitorThread(void *data);
+};
+}
+
+#endif
diff --git a/lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.cpp b/lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.cpp
new file mode 100644
index 00000000000..fb329aab7e9
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.cpp
@@ -0,0 +1,55 @@
+//===-- DebugMonitorMessageResults.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugMonitorMessageResults.h"
+#include "DebugMonitorMessages.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugMonitorMessageResult::DebugMonitorMessageResult(const DebugMonitorMessage *message)
+ : m_message(message)
+{
+ Retain();
+ if (m_message)
+ m_message->Retain();
+}
+
+DebugMonitorMessageResult::~DebugMonitorMessageResult()
+{
+ if (m_message)
+ m_message->Release();
+}
+
+void
+DebugMonitorMessageResult::SetError(const Error &error)
+{
+ m_error = error;
+}
+
+LaunchProcessMessageResult::LaunchProcessMessageResult(const LaunchProcessMessage *message)
+ : DebugMonitorMessageResult(message)
+{
+}
+
+LaunchProcessMessageResult *
+LaunchProcessMessageResult::Create(const LaunchProcessMessage *message)
+{
+ return new LaunchProcessMessageResult(message);
+}
+
+void
+LaunchProcessMessageResult::SetProcess(const HostProcess &process)
+{
+ m_process = process;
+}
diff --git a/lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.h b/lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.h
new file mode 100644
index 00000000000..e25dba51011
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugMonitorMessageResults.h
@@ -0,0 +1,70 @@
+//===-- DebugMonitorMessages.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_DebugMonitorMessageResults_H_
+#define liblldb_Plugins_Process_Windows_DebugMonitorMessageResults_H_
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+namespace lldb_private
+{
+
+class DebugMonitorMessage;
+class DebugMonitorMessageResult;
+class LaunchProcessMessage;
+
+class DebugMonitorMessageResult : public llvm::ThreadSafeRefCountedBase<DebugMonitorMessageResult>
+{
+ public:
+ virtual ~DebugMonitorMessageResult();
+
+ const Error &
+ GetError() const
+ {
+ return m_error;
+ }
+ const DebugMonitorMessage *
+ GetOriginalMessage() const
+ {
+ return m_message;
+ }
+
+ void SetError(const Error &error);
+
+ protected:
+ explicit DebugMonitorMessageResult(const DebugMonitorMessage *message);
+
+ private:
+ Error m_error;
+ const DebugMonitorMessage *m_message;
+};
+
+class LaunchProcessMessageResult : public DebugMonitorMessageResult
+{
+ public:
+ static LaunchProcessMessageResult *Create(const LaunchProcessMessage *message);
+
+ void SetProcess(const HostProcess &process);
+ const HostProcess &
+ GetProcess() const
+ {
+ return m_process;
+ }
+
+ private:
+ LaunchProcessMessageResult(const LaunchProcessMessage *message);
+
+ HostProcess m_process;
+};
+}
+
+#endif
diff --git a/lldb/source/Plugins/Process/Windows/DebugMonitorMessages.cpp b/lldb/source/Plugins/Process/Windows/DebugMonitorMessages.cpp
new file mode 100644
index 00000000000..86904a604f2
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugMonitorMessages.cpp
@@ -0,0 +1,62 @@
+//===-- DebugMonitorMessages.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugMonitorMessage::DebugMonitorMessage(MonitorMessageType message_type)
+ : m_message_type(message_type)
+{
+ Retain();
+ m_completion_predicate.SetValue(nullptr, eBroadcastNever);
+}
+
+DebugMonitorMessage::~DebugMonitorMessage()
+{
+ const DebugMonitorMessageResult *result = m_completion_predicate.GetValue();
+ if (result)
+ result->Release();
+ m_completion_predicate.SetValue(nullptr, eBroadcastNever);
+}
+
+const DebugMonitorMessageResult *
+DebugMonitorMessage::WaitForCompletion()
+{
+ const DebugMonitorMessageResult *result = nullptr;
+ m_completion_predicate.WaitForValueNotEqualTo(nullptr, result);
+ return result;
+}
+
+void
+DebugMonitorMessage::CompleteMessage(const DebugMonitorMessageResult *result)
+{
+ if (result)
+ result->Retain();
+ m_completion_predicate.SetValue(result, eBroadcastAlways);
+}
+
+LaunchProcessMessage::LaunchProcessMessage(const ProcessLaunchInfo &launch_info, lldb::ProcessSP process_plugin)
+ : DebugMonitorMessage(MonitorMessageType::eLaunchProcess)
+ , m_launch_info(launch_info)
+ , m_process_plugin(process_plugin)
+{
+}
+
+LaunchProcessMessage *
+LaunchProcessMessage::Create(const ProcessLaunchInfo &launch_info, lldb::ProcessSP process_plugin)
+{
+ return new LaunchProcessMessage(launch_info, process_plugin);
+}
diff --git a/lldb/source/Plugins/Process/Windows/DebugMonitorMessages.h b/lldb/source/Plugins/Process/Windows/DebugMonitorMessages.h
new file mode 100644
index 00000000000..28e95183c16
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugMonitorMessages.h
@@ -0,0 +1,86 @@
+//===-- DebugMonitorMessages.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_DebugMonitorMessages_H_
+#define liblldb_Plugins_Process_Windows_DebugMonitorMessages_H_
+
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/windows/windows.h"
+#include "lldb/lldb-types.h"
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+
+#include <map>
+#include <memory>
+
+class ProcessWindows;
+
+namespace lldb_private
+{
+class DebugMonitorMessage;
+class DebugMonitorMessageResult;
+class ProcessLaunchInfo;
+
+enum class MonitorMessageType
+{
+ eLaunchProcess, // Launch a process under the control of the debugger.
+ eAttachProcess, // Attach to an existing process, and give control to the debugger.
+ eDetachProcess, // Detach from a process that the debugger currently controls.
+ eSuspendProcess, // Suspend a process.
+ eResumeProcess, // Resume a suspended process.
+};
+
+class DebugMonitorMessage : public llvm::ThreadSafeRefCountedBase<DebugMonitorMessage>
+{
+ public:
+ virtual ~DebugMonitorMessage();
+
+ const DebugMonitorMessageResult *WaitForCompletion();
+ void CompleteMessage(const DebugMonitorMessageResult *result);
+
+ MonitorMessageType
+ GetMessageType() const
+ {
+ return m_message_type;
+ }
+
+ protected:
+ explicit DebugMonitorMessage(MonitorMessageType message_type);
+
+ private:
+ Predicate<const DebugMonitorMessageResult *> m_completion_predicate;
+ MonitorMessageType m_message_type;
+};
+
+class LaunchProcessMessage : public DebugMonitorMessage
+{
+ public:
+ static LaunchProcessMessage *Create(const ProcessLaunchInfo &launch_info, lldb::ProcessSP m_process_plugin);
+ const ProcessLaunchInfo &
+ GetLaunchInfo() const
+ {
+ return m_launch_info;
+ }
+
+ lldb::ProcessSP
+ GetProcessPlugin() const
+ {
+ return m_process_plugin;
+ }
+
+ private:
+ LaunchProcessMessage(const ProcessLaunchInfo &launch_info, lldb::ProcessSP m_process_plugin);
+
+ const ProcessLaunchInfo &m_launch_info;
+ lldb::ProcessSP m_process_plugin;
+};
+}
+
+#endif
diff --git a/lldb/source/Plugins/Process/Windows/DebugOneProcessThread.cpp b/lldb/source/Plugins/Process/Windows/DebugOneProcessThread.cpp
new file mode 100644
index 00000000000..6d10f8c3ae7
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugOneProcessThread.cpp
@@ -0,0 +1,227 @@
+//===-- DebugDriverThread.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugDriverThread.h"
+#include "DebugOneProcessThread.h"
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+#include "SlaveMessages.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/ThisThread.h"
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Host/windows/HostThreadWindows.h"
+#include "lldb/Host/windows/ProcessLauncherWindows.h"
+
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace
+{
+struct DebugLaunchContext
+{
+ DebugOneProcessThread *instance;
+ const LaunchProcessMessage *launch;
+};
+}
+
+DebugOneProcessThread::DebugOneProcessThread(HostThread driver_thread)
+ : m_driver_thread(driver_thread)
+{
+ m_launch_predicate.SetValue(nullptr, eBroadcastNever);
+}
+
+DebugOneProcessThread::~DebugOneProcessThread()
+{
+}
+
+const LaunchProcessMessageResult *
+DebugOneProcessThread::DebugLaunch(const LaunchProcessMessage *message)
+{
+ Error error;
+ const LaunchProcessMessageResult *result = nullptr;
+ DebugLaunchContext context;
+ context.instance = this;
+ context.launch = message;
+
+ HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebugLaunchThread, &context, &error));
+ if (error.Success())
+ m_launch_predicate.WaitForValueNotEqualTo(nullptr, result);
+
+ return result;
+}
+
+lldb::thread_result_t
+DebugOneProcessThread::DebugLaunchThread(void *data)
+{
+ DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
+ DebugOneProcessThread *thread = context->instance;
+ return thread->DebugLaunchThread(context->launch);
+}
+
+lldb::thread_result_t
+DebugOneProcessThread::DebugLaunchThread(const LaunchProcessMessage *message)
+{
+ // 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<DebugOneProcessThread> this_ref(shared_from_this());
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ Error error;
+ ProcessLauncherWindows launcher;
+
+ m_process_plugin = message->GetProcessPlugin();
+ m_process = launcher.LaunchProcess(message->GetLaunchInfo(), error);
+
+ std::string thread_name;
+ llvm::raw_string_ostream name_stream(thread_name);
+ name_stream << "lldb.plugin.process-windows.slave[" << m_process.GetProcessId() << "]";
+ name_stream.flush();
+ ThisThread::SetName(thread_name.c_str());
+
+ LaunchProcessMessageResult *result = LaunchProcessMessageResult::Create(message);
+ result->SetError(error);
+ result->SetProcess(m_process);
+ m_launch_predicate.SetValue(result, eBroadcastAlways);
+
+ DebugLoop();
+ if (log)
+ log->Printf("Debug monitor thread '%s' exiting.", thread_name.c_str());
+
+ return 0;
+}
+
+void
+DebugOneProcessThread::DebugLoop()
+{
+ DEBUG_EVENT dbe = {0};
+ bool exit = false;
+ while (!exit && WaitForDebugEvent(&dbe, INFINITE))
+ {
+ DWORD continue_status = DBG_CONTINUE;
+ switch (dbe.dwDebugEventCode)
+ {
+ case EXCEPTION_DEBUG_EVENT:
+ continue_status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
+ 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);
+ exit = true;
+ 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)
+ exit = true;
+ break;
+ }
+
+ ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);
+ }
+}
+
+DWORD
+DebugOneProcessThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
+{
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id)
+{
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id)
+{
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id)
+{
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id)
+{
+ HANDLE driver = m_driver_thread.GetNativeThread().GetSystemHandle();
+ SlaveMessageProcessExited *message = new SlaveMessageProcessExited(m_process, info.dwExitCode);
+
+ QueueUserAPC(NotifySlaveProcessExited, driver, reinterpret_cast<ULONG_PTR>(message));
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
+{
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
+{
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id)
+{
+ return DBG_CONTINUE;
+}
+
+DWORD
+DebugOneProcessThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id)
+{
+ HANDLE driver = m_driver_thread.GetNativeThread().GetSystemHandle();
+ Error error(info.dwError, eErrorTypeWin32);
+ SlaveMessageRipEvent *message = new SlaveMessageRipEvent(m_process, error, info.dwType);
+
+ QueueUserAPC(NotifySlaveRipEvent, driver, reinterpret_cast<ULONG_PTR>(message));
+ return DBG_CONTINUE;
+}
+
+void
+DebugOneProcessThread::NotifySlaveProcessExited(ULONG_PTR message)
+{
+ SlaveMessageProcessExited *slave_message = reinterpret_cast<SlaveMessageProcessExited *>(message);
+ DebugDriverThread::GetInstance().HandleSlaveEvent(*slave_message);
+ delete slave_message;
+}
+
+void
+DebugOneProcessThread::NotifySlaveRipEvent(ULONG_PTR message)
+{
+ SlaveMessageRipEvent *slave_message = reinterpret_cast<SlaveMessageRipEvent *>(message);
+ DebugDriverThread::GetInstance().HandleSlaveEvent(*slave_message);
+ delete slave_message;
+}
diff --git a/lldb/source/Plugins/Process/Windows/DebugOneProcessThread.h b/lldb/source/Plugins/Process/Windows/DebugOneProcessThread.h
new file mode 100644
index 00000000000..56934e0337e
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugOneProcessThread.h
@@ -0,0 +1,63 @@
+//===-- DebugOneProcessThread.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_DebugOneProcessThread_H_
+#define liblldb_Plugins_Process_Windows_DebugOneProcessThread_H_
+
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/HostThread.h"
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/windows/windows.h"
+
+namespace lldb_private
+{
+class LaunchProcessMessage;
+class LaunchProcessMessageResult;
+
+//----------------------------------------------------------------------
+// DebugOneProcessThread
+//
+// Debugs a single process, notifying the process plugin and/or the debugger
+// driver thread as appropriate when interesting things occur.
+//----------------------------------------------------------------------
+class DebugOneProcessThread : public std::enable_shared_from_this<DebugOneProcessThread>
+{
+ public:
+ DebugOneProcessThread(HostThread driver_thread);
+ virtual ~DebugOneProcessThread();
+
+ const LaunchProcessMessageResult *DebugLaunch(const LaunchProcessMessage *message);
+
+ private:
+ void DebugLoop();
+ DWORD 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);
+
+ static void __stdcall NotifySlaveProcessExited(ULONG_PTR message);
+ static void __stdcall NotifySlaveRipEvent(ULONG_PTR message);
+
+ // The main debug driver thread which is controlling this slave.
+ lldb_private::HostThread m_driver_thread;
+ Predicate<const LaunchProcessMessageResult *> m_launch_predicate;
+ lldb::ProcessSP m_process_plugin;
+ HostProcess m_process;
+
+ static lldb::thread_result_t DebugLaunchThread(void *data);
+ lldb::thread_result_t DebugLaunchThread(const LaunchProcessMessage *message);
+};
+}
+
+#endif
diff --git a/lldb/source/Plugins/Process/Windows/DebugProcessLauncher.cpp b/lldb/source/Plugins/Process/Windows/DebugProcessLauncher.cpp
new file mode 100644
index 00000000000..3b9f7da2cff
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugProcessLauncher.cpp
@@ -0,0 +1,38 @@
+//===-- DebugProcessLauncher.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DebugDriverThread.h"
+#include "DebugMonitorMessages.h"
+#include "DebugMonitorMessageResults.h"
+#include "DebugProcessLauncher.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DebugProcessLauncher::DebugProcessLauncher(lldb::ProcessSP process_plugin)
+ : m_process_plugin(process_plugin)
+{
+}
+
+HostProcess
+DebugProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error)
+{
+ LaunchProcessMessage *message = LaunchProcessMessage::Create(launch_info, m_process_plugin);
+ DebugDriverThread::GetInstance().PostDebugMessage(message);
+ const LaunchProcessMessageResult *result = static_cast<const LaunchProcessMessageResult *>(message->WaitForCompletion());
+ error = result->GetError();
+ HostProcess process = result->GetProcess();
+
+ message->Release();
+ return process;
+}
diff --git a/lldb/source/Plugins/Process/Windows/DebugProcessLauncher.h b/lldb/source/Plugins/Process/Windows/DebugProcessLauncher.h
new file mode 100644
index 00000000000..fd2b2c62388
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/DebugProcessLauncher.h
@@ -0,0 +1,40 @@
+//===-- DebugProcessLauncher.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_DebugProcessLauncher_H_
+#define liblldb_Plugins_Process_Windows_DebugProcessLauncher_H_
+
+#include "lldb/Host/ProcessLauncher.h"
+#include "lldb/lldb-forward.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+// DebugProcessLauncher
+//
+// DebugProcessLauncher launches a process for debugging on Windows. On
+// Windows, the debug loop that detects events and status changes in a debugged
+// process must run on the same thread that calls CreateProcess. So
+// DebugProcessLauncher is built with this in mind. It queues a request to the
+// DebugDriverThread to launch a new process, then waits for a notification from
+// that thread that the launch is complete.
+//----------------------------------------------------------------------
+class DebugProcessLauncher : public ProcessLauncher
+{
+ public:
+ explicit DebugProcessLauncher(lldb::ProcessSP process_plugin);
+ virtual HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Error &error);
+
+ private:
+ lldb::ProcessSP m_process_plugin;
+};
+}
+
+#endif
diff --git a/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp b/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp
index 50ee9f60217..e71c25f83a5 100644
--- a/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp
+++ b/lldb/source/Plugins/Process/Windows/ProcessWindows.cpp
@@ -11,18 +11,24 @@
#include "lldb/Host/windows/windows.h"
// C++ Includes
+#include <vector>
+
// Other libraries and framework includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
+#include "lldb/Host/MonitoringProcessLauncher.h"
+#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/windows/ProcessLauncherWindows.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Target.h"
+#include "DebugDriverThread.h"
+#include "DebugProcessLauncher.h"
#include "ProcessWindows.h"
using namespace lldb;
@@ -48,6 +54,7 @@ ProcessWindows::Initialize()
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
+ DebugDriverThread::Initialize();
}
}
@@ -59,9 +66,14 @@ ProcessWindows::ProcessWindows(Target& target, Listener &listener)
{
}
+ProcessWindows::~ProcessWindows()
+{
+}
+
void
ProcessWindows::Terminate()
{
+ DebugDriverThread::Teardown();
}
lldb_private::ConstString
@@ -89,7 +101,26 @@ Error
ProcessWindows::DoLaunch(Module *exe_module,
ProcessLaunchInfo &launch_info)
{
- return Host::LaunchProcess(launch_info);
+ Error result;
+ HostProcess process;
+ SetPrivateState(eStateLaunching);
+ if (launch_info.GetFlags().Test(eLaunchFlagDebug))
+ {
+ // If we're trying to debug this process, we need to use a
+ // DebugProcessLauncher so that we can enter a WaitForDebugEvent loop
+ // on the same thread that does the CreateProcess.
+ DebugProcessLauncher launcher(shared_from_this());
+ process = launcher.LaunchProcess(launch_info, result);
+ }
+ else
+ return Host::LaunchProcess(launch_info);
+
+ if (!result.Success())
+ return result;
+
+ launch_info.SetProcessID(process.GetProcessId());
+ SetID(process.GetProcessId());
+ return result;
}
Error
@@ -181,4 +212,3 @@ ProcessWindows::CanDebug(Target &target, bool plugin_specified_by_name)
return exe_module_sp->GetFileSpec().Exists();
return false;
}
-
diff --git a/lldb/source/Plugins/Process/Windows/ProcessWindows.h b/lldb/source/Plugins/Process/Windows/ProcessWindows.h
index 2feb46ffa5e..31ceddfa3ef 100644
--- a/lldb/source/Plugins/Process/Windows/ProcessWindows.h
+++ b/lldb/source/Plugins/Process/Windows/ProcessWindows.h
@@ -13,13 +13,20 @@
// C Includes
// C++ Includes
+#include <map>
#include <queue>
// Other libraries and framework includes
+#include "lldb/Host/HostThread.h"
#include "lldb/Target/Process.h"
class ProcessMonitor;
+namespace lldb_private
+{
+class HostProcess;
+}
+
class ProcessWindows :
public lldb_private::Process
{
@@ -50,6 +57,8 @@ public:
ProcessWindows(lldb_private::Target& target,
lldb_private::Listener &listener);
+ ~ProcessWindows();
+
virtual lldb_private::Error
DoDetach(bool keep_stopped);
@@ -99,11 +108,7 @@ public:
virtual bool
IsAlive ();
- virtual size_t
- DoReadMemory (lldb::addr_t vm_addr,
- void *buf,
- size_t size,
- lldb_private::Error &error);
+ virtual size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, lldb_private::Error &error);
};
#endif // liblldb_Plugins_Process_Windows_ProcessWindows_H_
diff --git a/lldb/source/Plugins/Process/Windows/SlaveMessages.h b/lldb/source/Plugins/Process/Windows/SlaveMessages.h
new file mode 100644
index 00000000000..adbd0befe92
--- /dev/null
+++ b/lldb/source/Plugins/Process/Windows/SlaveMessages.h
@@ -0,0 +1,86 @@
+//===-- SlaveMessages.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_SlaveMessages_H_
+#define liblldb_Plugins_Process_Windows_SlaveMessages_H_
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/HostProcess.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+// SlaveMessageBase
+//
+// SlaveMessageBase serves as a base class for all messages which debug slaves
+// can send up to the driver thread to notify it of events related to processes
+// which are being debugged.
+//----------------------------------------------------------------------
+class SlaveMessageBase
+{
+ public:
+ SlaveMessageBase(const HostProcess &process)
+ : m_process(process)
+ {
+ }
+
+ virtual ~SlaveMessageBase() {}
+
+ const HostProcess &
+ GetProcess() const
+ {
+ return m_process;
+ }
+
+ protected:
+ HostProcess m_process;
+};
+
+class SlaveMessageProcessExited : public SlaveMessageBase
+{
+ public:
+ SlaveMessageProcessExited(const HostProcess &process, DWORD exit_code)
+ : SlaveMessageBase(process)
+ , m_exit_code(exit_code)
+ {
+ }
+
+ DWORD
+ GetExitCode() const { return m_exit_code; }
+
+ private:
+ DWORD m_exit_code;
+};
+
+class SlaveMessageRipEvent : public SlaveMessageBase
+{
+ public:
+ SlaveMessageRipEvent(const HostProcess &process, const Error &error, DWORD type)
+ : SlaveMessageBase(process)
+ , m_error(error)
+ , m_type(type)
+ {
+ }
+
+ const Error &
+ GetError() const
+ {
+ return m_error;
+ }
+ DWORD
+ GetType() const { return m_type; }
+
+ private:
+ Error m_error;
+ DWORD m_type;
+};
+}
+
+#endif
OpenPOWER on IntegriCloud