diff options
author | Zachary Turner <zturner@google.com> | 2014-11-07 23:44:13 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2014-11-07 23:44:13 +0000 |
commit | 02862bc83acd8d10a0a8b6cea4b63a25f46ad68a (patch) | |
tree | 7054d08ca1d879f139d86ab1a5f75981028fcb91 /lldb/source/Plugins/Process/Windows/DebuggerThread.cpp | |
parent | c15788a23a3695e32b590644f78ab3d6931a12a5 (diff) | |
download | bcm5719-llvm-02862bc83acd8d10a0a8b6cea4b63a25f46ad68a.tar.gz bcm5719-llvm-02862bc83acd8d10a0a8b6cea4b63a25f46ad68a.zip |
Remove the top-level DebugDriverThread in ProcessWindows.
Originally the idea was that we would queue requests to a master
thread that would dispatch them to other slave threads each
responsible for debugging an individual process. This might make
some scenarios more scalable and responsive, but for now it seems
to be unwarranted complexity for no observable benefit.
llvm-svn: 221561
Diffstat (limited to 'lldb/source/Plugins/Process/Windows/DebuggerThread.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/Windows/DebuggerThread.cpp | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Windows/DebuggerThread.cpp b/lldb/source/Plugins/Process/Windows/DebuggerThread.cpp new file mode 100644 index 00000000000..da4b375596a --- /dev/null +++ b/lldb/source/Plugins/Process/Windows/DebuggerThread.cpp @@ -0,0 +1,230 @@ +//===-- DebuggerThread.DebuggerThread --------------------------------------*- 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 "IDebugDelegate.h" +#include "ProcessMessages.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/HostProcessWindows.h" +#include "lldb/Host/windows/HostThreadWindows.h" +#include "lldb/Host/windows/ProcessLauncherWindows.h" +#include "lldb/Target/ProcessLaunchInfo.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; +}; +} + +DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) + : m_debug_delegate(debug_delegate) + , m_image_file(nullptr) + , m_launched_event(nullptr) +{ + m_launched_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); +} + +DebuggerThread::~DebuggerThread() +{ + if (m_launched_event != nullptr) + ::CloseHandle(m_launched_event); +} + +HostProcess +DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) +{ + Error error; + + DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); + HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebuggerThreadRoutine, context, &error)); + if (error.Success()) + ::WaitForSingleObject(m_launched_event, INFINITE); + + return m_process; +} + +lldb::thread_result_t +DebuggerThread::DebuggerThreadRoutine(void *data) +{ + DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); + lldb::thread_result_t result = context->m_thread->DebuggerThreadRoutine(context->m_launch_info); + delete context; + return result; +} + +lldb::thread_result_t +DebuggerThread::DebuggerThreadRoutine(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(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); + + Error 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 + SetEvent(m_launched_event); + + return 0; +} + +void +DebuggerThread::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 +DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id) +{ + return DBG_CONTINUE; +} + +DWORD +DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id) +{ + return DBG_CONTINUE; +} + +DWORD +DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id) +{ + 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()); + + // 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); + ((HostThreadWindows &)m_main_thread.GetNativeThread()).SetOwnsHandle(false); + m_image_file = info.hFile; + + SetEvent(m_launched_event); + + return DBG_CONTINUE; +} + +DWORD +DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id) +{ + return DBG_CONTINUE; +} + +DWORD +DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id) +{ + ProcessMessageExitProcess message(m_process, info.dwExitCode); + m_debug_delegate->OnExitProcess(message); + + m_process = HostProcess(); + m_main_thread = HostThread(); + ::CloseHandle(m_image_file); + m_image_file = nullptr; + return DBG_CONTINUE; +} + +DWORD +DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id) +{ + // Windows does not automatically close info.hFile when the DLL is unloaded. + ::CloseHandle(info.hFile); + return DBG_CONTINUE; +} + +DWORD +DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id) +{ + 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) +{ + Error error(info.dwError, eErrorTypeWin32); + ProcessMessageDebuggerError message(m_process, error, info.dwType); + m_debug_delegate->OnDebuggerError(message); + + return DBG_CONTINUE; +} |