1*696bd635SAlexander Shaposhnikov //===-- DebuggerThread.cpp --------------------------------------*- C++ -*-===// 24ad5def9SAdrian McCarthy // 34ad5def9SAdrian McCarthy // The LLVM Compiler Infrastructure 44ad5def9SAdrian McCarthy // 54ad5def9SAdrian McCarthy // This file is distributed under the University of Illinois Open Source 64ad5def9SAdrian McCarthy // License. See LICENSE.TXT for details. 74ad5def9SAdrian McCarthy // 84ad5def9SAdrian McCarthy //===----------------------------------------------------------------------===// 94ad5def9SAdrian McCarthy 104ad5def9SAdrian McCarthy #include "DebuggerThread.h" 114ad5def9SAdrian McCarthy #include "ExceptionRecord.h" 124ad5def9SAdrian McCarthy #include "IDebugDelegate.h" 134ad5def9SAdrian McCarthy 144ad5def9SAdrian McCarthy #include "lldb/Core/Error.h" 154ad5def9SAdrian McCarthy #include "lldb/Core/Log.h" 164ad5def9SAdrian McCarthy #include "lldb/Core/ModuleSpec.h" 174ad5def9SAdrian McCarthy #include "lldb/Host/FileSpec.h" 184ad5def9SAdrian McCarthy #include "lldb/Host/Predicate.h" 194ad5def9SAdrian McCarthy #include "lldb/Host/ThisThread.h" 204ad5def9SAdrian McCarthy #include "lldb/Host/ThreadLauncher.h" 214ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostProcessWindows.h" 224ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h" 234ad5def9SAdrian McCarthy #include "lldb/Host/windows/ProcessLauncherWindows.h" 244ad5def9SAdrian McCarthy #include "lldb/Target/Process.h" 254ad5def9SAdrian McCarthy #include "lldb/Target/ProcessLaunchInfo.h" 264ad5def9SAdrian McCarthy 274ad5def9SAdrian McCarthy #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" 284ad5def9SAdrian McCarthy 294ad5def9SAdrian McCarthy #include "llvm/ADT/STLExtras.h" 304ad5def9SAdrian McCarthy #include "llvm/Support/ConvertUTF.h" 314ad5def9SAdrian McCarthy #include "llvm/Support/raw_ostream.h" 324ad5def9SAdrian McCarthy 334ad5def9SAdrian McCarthy using namespace lldb; 344ad5def9SAdrian McCarthy using namespace lldb_private; 354ad5def9SAdrian McCarthy 364ad5def9SAdrian McCarthy namespace { 374ad5def9SAdrian McCarthy struct DebugLaunchContext { 384ad5def9SAdrian McCarthy DebugLaunchContext(DebuggerThread *thread, 394ad5def9SAdrian McCarthy const ProcessLaunchInfo &launch_info) 404ad5def9SAdrian McCarthy : m_thread(thread), m_launch_info(launch_info) {} 414ad5def9SAdrian McCarthy DebuggerThread *m_thread; 424ad5def9SAdrian McCarthy ProcessLaunchInfo m_launch_info; 434ad5def9SAdrian McCarthy }; 444ad5def9SAdrian McCarthy 454ad5def9SAdrian McCarthy struct DebugAttachContext { 464ad5def9SAdrian McCarthy DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, 474ad5def9SAdrian McCarthy const ProcessAttachInfo &attach_info) 484ad5def9SAdrian McCarthy : m_thread(thread), m_pid(pid), m_attach_info(attach_info) {} 494ad5def9SAdrian McCarthy DebuggerThread *m_thread; 504ad5def9SAdrian McCarthy lldb::pid_t m_pid; 514ad5def9SAdrian McCarthy ProcessAttachInfo m_attach_info; 524ad5def9SAdrian McCarthy }; 534ad5def9SAdrian McCarthy } 544ad5def9SAdrian McCarthy 554ad5def9SAdrian McCarthy DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) 564ad5def9SAdrian McCarthy : m_debug_delegate(debug_delegate), m_pid_to_detach(0), 574ad5def9SAdrian McCarthy m_is_shutting_down(false) { 584ad5def9SAdrian McCarthy m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 594ad5def9SAdrian McCarthy } 604ad5def9SAdrian McCarthy 614ad5def9SAdrian McCarthy DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } 624ad5def9SAdrian McCarthy 634ad5def9SAdrian McCarthy Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { 644ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 654ad5def9SAdrian McCarthy "DebuggerThread::DebugLaunch launching '%s'", 664ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str()); 674ad5def9SAdrian McCarthy 684ad5def9SAdrian McCarthy Error error; 694ad5def9SAdrian McCarthy DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); 704ad5def9SAdrian McCarthy HostThread slave_thread(ThreadLauncher::LaunchThread( 714ad5def9SAdrian McCarthy "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, 724ad5def9SAdrian McCarthy context, &error)); 734ad5def9SAdrian McCarthy 744ad5def9SAdrian McCarthy if (!error.Success()) { 754ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, 764ad5def9SAdrian McCarthy "DebugLaunch couldn't launch debugger thread. %s", 774ad5def9SAdrian McCarthy error.AsCString()); 784ad5def9SAdrian McCarthy } 794ad5def9SAdrian McCarthy 804ad5def9SAdrian McCarthy return error; 814ad5def9SAdrian McCarthy } 824ad5def9SAdrian McCarthy 834ad5def9SAdrian McCarthy Error DebuggerThread::DebugAttach(lldb::pid_t pid, 844ad5def9SAdrian McCarthy const ProcessAttachInfo &attach_info) { 854ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 864ad5def9SAdrian McCarthy "DebuggerThread::DebugAttach attaching to '%llu'", pid); 874ad5def9SAdrian McCarthy 884ad5def9SAdrian McCarthy Error error; 894ad5def9SAdrian McCarthy DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); 904ad5def9SAdrian McCarthy HostThread slave_thread(ThreadLauncher::LaunchThread( 914ad5def9SAdrian McCarthy "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, 924ad5def9SAdrian McCarthy context, &error)); 934ad5def9SAdrian McCarthy 944ad5def9SAdrian McCarthy if (!error.Success()) { 954ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, 964ad5def9SAdrian McCarthy "DebugAttach couldn't attach to process '%llu'. %s", pid, 974ad5def9SAdrian McCarthy error.AsCString()); 984ad5def9SAdrian McCarthy } 994ad5def9SAdrian McCarthy 1004ad5def9SAdrian McCarthy return error; 1014ad5def9SAdrian McCarthy } 1024ad5def9SAdrian McCarthy 1034ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) { 1044ad5def9SAdrian McCarthy DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); 1054ad5def9SAdrian McCarthy lldb::thread_result_t result = 1064ad5def9SAdrian McCarthy context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); 1074ad5def9SAdrian McCarthy delete context; 1084ad5def9SAdrian McCarthy return result; 1094ad5def9SAdrian McCarthy } 1104ad5def9SAdrian McCarthy 1114ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) { 1124ad5def9SAdrian McCarthy DebugAttachContext *context = static_cast<DebugAttachContext *>(data); 1134ad5def9SAdrian McCarthy lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine( 1144ad5def9SAdrian McCarthy context->m_pid, context->m_attach_info); 1154ad5def9SAdrian McCarthy delete context; 1164ad5def9SAdrian McCarthy return result; 1174ad5def9SAdrian McCarthy } 1184ad5def9SAdrian McCarthy 1194ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( 1204ad5def9SAdrian McCarthy const ProcessLaunchInfo &launch_info) { 1214ad5def9SAdrian McCarthy // Grab a shared_ptr reference to this so that we know it won't get deleted 1224ad5def9SAdrian McCarthy // until after the 1234ad5def9SAdrian McCarthy // thread routine has exited. 1244ad5def9SAdrian McCarthy std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 1254ad5def9SAdrian McCarthy 1264ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 1274ad5def9SAdrian McCarthy "DebuggerThread preparing to launch '%s' on background thread.", 1284ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str()); 1294ad5def9SAdrian McCarthy 1304ad5def9SAdrian McCarthy Error error; 1314ad5def9SAdrian McCarthy ProcessLauncherWindows launcher; 1324ad5def9SAdrian McCarthy HostProcess process(launcher.LaunchProcess(launch_info, error)); 1334ad5def9SAdrian McCarthy // If we couldn't create the process, notify waiters immediately. Otherwise 1344ad5def9SAdrian McCarthy // enter the debug 1354ad5def9SAdrian McCarthy // loop and wait until we get the create process debug notification. Note 1364ad5def9SAdrian McCarthy // that if the process 1374ad5def9SAdrian McCarthy // was created successfully, we can throw away the process handle we got from 1384ad5def9SAdrian McCarthy // CreateProcess 1394ad5def9SAdrian McCarthy // because Windows will give us another (potentially more useful?) handle when 1404ad5def9SAdrian McCarthy // it sends us the 1414ad5def9SAdrian McCarthy // CREATE_PROCESS_DEBUG_EVENT. 1424ad5def9SAdrian McCarthy if (error.Success()) 1434ad5def9SAdrian McCarthy DebugLoop(); 1444ad5def9SAdrian McCarthy else 1454ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, 0); 1464ad5def9SAdrian McCarthy 1474ad5def9SAdrian McCarthy return 0; 1484ad5def9SAdrian McCarthy } 1494ad5def9SAdrian McCarthy 1504ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( 1514ad5def9SAdrian McCarthy lldb::pid_t pid, const ProcessAttachInfo &attach_info) { 1524ad5def9SAdrian McCarthy // Grab a shared_ptr reference to this so that we know it won't get deleted 1534ad5def9SAdrian McCarthy // until after the 1544ad5def9SAdrian McCarthy // thread routine has exited. 1554ad5def9SAdrian McCarthy std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 1564ad5def9SAdrian McCarthy 1574ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to " 1584ad5def9SAdrian McCarthy "process '%llu' on background thread.", 1594ad5def9SAdrian McCarthy pid); 1604ad5def9SAdrian McCarthy 1614ad5def9SAdrian McCarthy if (!DebugActiveProcess((DWORD)pid)) { 1624ad5def9SAdrian McCarthy Error error(::GetLastError(), eErrorTypeWin32); 1634ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, 0); 1644ad5def9SAdrian McCarthy return 0; 1654ad5def9SAdrian McCarthy } 1664ad5def9SAdrian McCarthy 1674ad5def9SAdrian McCarthy // The attach was successful, enter the debug loop. From here on out, this is 1684ad5def9SAdrian McCarthy // no different than 1694ad5def9SAdrian McCarthy // a create process operation, so all the same comments in DebugLaunch should 1704ad5def9SAdrian McCarthy // apply from this 1714ad5def9SAdrian McCarthy // point out. 1724ad5def9SAdrian McCarthy DebugLoop(); 1734ad5def9SAdrian McCarthy 1744ad5def9SAdrian McCarthy return 0; 1754ad5def9SAdrian McCarthy } 1764ad5def9SAdrian McCarthy 1774ad5def9SAdrian McCarthy Error DebuggerThread::StopDebugging(bool terminate) { 1784ad5def9SAdrian McCarthy Error error; 1794ad5def9SAdrian McCarthy 1804ad5def9SAdrian McCarthy lldb::pid_t pid = m_process.GetProcessId(); 1814ad5def9SAdrian McCarthy 1824ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 1834ad5def9SAdrian McCarthy "StopDebugging('%s') called (inferior=%I64u).", 1844ad5def9SAdrian McCarthy (terminate ? "true" : "false"), pid); 1854ad5def9SAdrian McCarthy 1864ad5def9SAdrian McCarthy // Set m_is_shutting_down to true if it was false. Return if it was already 1874ad5def9SAdrian McCarthy // true. 1884ad5def9SAdrian McCarthy bool expected = false; 1894ad5def9SAdrian McCarthy if (!m_is_shutting_down.compare_exchange_strong(expected, true)) 1904ad5def9SAdrian McCarthy return error; 1914ad5def9SAdrian McCarthy 1924ad5def9SAdrian McCarthy // Make a copy of the process, since the termination sequence will reset 1934ad5def9SAdrian McCarthy // DebuggerThread's internal copy and it needs to remain open for the Wait 1944ad5def9SAdrian McCarthy // operation. 1954ad5def9SAdrian McCarthy HostProcess process_copy = m_process; 1964ad5def9SAdrian McCarthy lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); 1974ad5def9SAdrian McCarthy 1984ad5def9SAdrian McCarthy if (terminate) { 1994ad5def9SAdrian McCarthy // Initiate the termination before continuing the exception, so that the 2004ad5def9SAdrian McCarthy // next debug 2014ad5def9SAdrian McCarthy // event we get is the exit process event, and not some other event. 2024ad5def9SAdrian McCarthy BOOL terminate_suceeded = TerminateProcess(handle, 0); 2034ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging called " 2044ad5def9SAdrian McCarthy "TerminateProcess(0x%p, 0) " 2054ad5def9SAdrian McCarthy "(inferior=%I64u), success='%s'", 2064ad5def9SAdrian McCarthy handle, pid, (terminate_suceeded ? "true" : "false")); 2074ad5def9SAdrian McCarthy } 2084ad5def9SAdrian McCarthy 2094ad5def9SAdrian McCarthy // If we're stuck waiting for an exception to continue (e.g. the user is at a 2104ad5def9SAdrian McCarthy // breakpoint 2114ad5def9SAdrian McCarthy // messing around in the debugger), continue it now. But only AFTER calling 2124ad5def9SAdrian McCarthy // TerminateProcess 2134ad5def9SAdrian McCarthy // to make sure that the very next call to WaitForDebugEvent is an exit 2144ad5def9SAdrian McCarthy // process event. 2154ad5def9SAdrian McCarthy if (m_active_exception.get()) { 2164ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, 2174ad5def9SAdrian McCarthy "StopDebugging masking active exception"); 2184ad5def9SAdrian McCarthy 2194ad5def9SAdrian McCarthy ContinueAsyncException(ExceptionResult::MaskException); 2204ad5def9SAdrian McCarthy } 2214ad5def9SAdrian McCarthy 2224ad5def9SAdrian McCarthy if (!terminate) { 2234ad5def9SAdrian McCarthy // Indicate that we want to detach. 2244ad5def9SAdrian McCarthy m_pid_to_detach = GetProcess().GetProcessId(); 2254ad5def9SAdrian McCarthy 2264ad5def9SAdrian McCarthy // Force a fresh break so that the detach can happen from the debugger 2274ad5def9SAdrian McCarthy // thread. 2284ad5def9SAdrian McCarthy if (!::DebugBreakProcess( 2294ad5def9SAdrian McCarthy GetProcess().GetNativeProcess().GetSystemHandle())) { 2304ad5def9SAdrian McCarthy error.SetError(::GetLastError(), eErrorTypeWin32); 2314ad5def9SAdrian McCarthy } 2324ad5def9SAdrian McCarthy } 2334ad5def9SAdrian McCarthy 2344ad5def9SAdrian McCarthy WINLOG_IFALL( 2354ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 2364ad5def9SAdrian McCarthy "StopDebugging waiting for detach from process %llu to complete.", pid); 2374ad5def9SAdrian McCarthy 2384ad5def9SAdrian McCarthy DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); 2394ad5def9SAdrian McCarthy if (wait_result != WAIT_OBJECT_0) { 2404ad5def9SAdrian McCarthy error.SetError(GetLastError(), eErrorTypeWin32); 2414ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, 2424ad5def9SAdrian McCarthy "StopDebugging WaitForSingleObject(0x%p, 5000) returned %lu", 2434ad5def9SAdrian McCarthy m_debugging_ended_event, wait_result); 2444ad5def9SAdrian McCarthy } else { 2454ad5def9SAdrian McCarthy WINLOG_IFALL( 2464ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 2474ad5def9SAdrian McCarthy "StopDebugging detach from process %llu completed successfully.", pid); 2484ad5def9SAdrian McCarthy } 2494ad5def9SAdrian McCarthy 2504ad5def9SAdrian McCarthy if (!error.Success()) { 2514ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging encountered an error " 2524ad5def9SAdrian McCarthy "while trying to stop process %llu. %s", 2534ad5def9SAdrian McCarthy pid, error.AsCString()); 2544ad5def9SAdrian McCarthy } 2554ad5def9SAdrian McCarthy return error; 2564ad5def9SAdrian McCarthy } 2574ad5def9SAdrian McCarthy 2584ad5def9SAdrian McCarthy void DebuggerThread::ContinueAsyncException(ExceptionResult result) { 2594ad5def9SAdrian McCarthy if (!m_active_exception.get()) 2604ad5def9SAdrian McCarthy return; 2614ad5def9SAdrian McCarthy 2624ad5def9SAdrian McCarthy WINLOG_IFANY( 2634ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, 2644ad5def9SAdrian McCarthy "ContinueAsyncException called for inferior process %I64u, broadcasting.", 2654ad5def9SAdrian McCarthy m_process.GetProcessId()); 2664ad5def9SAdrian McCarthy 2674ad5def9SAdrian McCarthy m_active_exception.reset(); 2684ad5def9SAdrian McCarthy m_exception_pred.SetValue(result, eBroadcastAlways); 2694ad5def9SAdrian McCarthy } 2704ad5def9SAdrian McCarthy 2714ad5def9SAdrian McCarthy void DebuggerThread::FreeProcessHandles() { 2724ad5def9SAdrian McCarthy m_process = HostProcess(); 2734ad5def9SAdrian McCarthy m_main_thread = HostThread(); 2744ad5def9SAdrian McCarthy if (m_image_file) { 2754ad5def9SAdrian McCarthy ::CloseHandle(m_image_file); 2764ad5def9SAdrian McCarthy m_image_file = nullptr; 2774ad5def9SAdrian McCarthy } 2784ad5def9SAdrian McCarthy } 2794ad5def9SAdrian McCarthy 2804ad5def9SAdrian McCarthy void DebuggerThread::DebugLoop() { 2814ad5def9SAdrian McCarthy DEBUG_EVENT dbe = {}; 2824ad5def9SAdrian McCarthy bool should_debug = true; 2834ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); 2844ad5def9SAdrian McCarthy while (should_debug) { 2854ad5def9SAdrian McCarthy WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); 2864ad5def9SAdrian McCarthy BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); 2874ad5def9SAdrian McCarthy if (wait_result) { 2884ad5def9SAdrian McCarthy DWORD continue_status = DBG_CONTINUE; 2894ad5def9SAdrian McCarthy switch (dbe.dwDebugEventCode) { 2904ad5def9SAdrian McCarthy case EXCEPTION_DEBUG_EVENT: { 2914ad5def9SAdrian McCarthy ExceptionResult status = 2924ad5def9SAdrian McCarthy HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); 2934ad5def9SAdrian McCarthy 2944ad5def9SAdrian McCarthy if (status == ExceptionResult::MaskException) 2954ad5def9SAdrian McCarthy continue_status = DBG_CONTINUE; 2964ad5def9SAdrian McCarthy else if (status == ExceptionResult::SendToApplication) 2974ad5def9SAdrian McCarthy continue_status = DBG_EXCEPTION_NOT_HANDLED; 2984ad5def9SAdrian McCarthy 2994ad5def9SAdrian McCarthy break; 3004ad5def9SAdrian McCarthy } 3014ad5def9SAdrian McCarthy case CREATE_THREAD_DEBUG_EVENT: 3024ad5def9SAdrian McCarthy continue_status = 3034ad5def9SAdrian McCarthy HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); 3044ad5def9SAdrian McCarthy break; 3054ad5def9SAdrian McCarthy case CREATE_PROCESS_DEBUG_EVENT: 3064ad5def9SAdrian McCarthy continue_status = 3074ad5def9SAdrian McCarthy HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); 3084ad5def9SAdrian McCarthy break; 3094ad5def9SAdrian McCarthy case EXIT_THREAD_DEBUG_EVENT: 3104ad5def9SAdrian McCarthy continue_status = 3114ad5def9SAdrian McCarthy HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); 3124ad5def9SAdrian McCarthy break; 3134ad5def9SAdrian McCarthy case EXIT_PROCESS_DEBUG_EVENT: 3144ad5def9SAdrian McCarthy continue_status = 3154ad5def9SAdrian McCarthy HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); 3164ad5def9SAdrian McCarthy should_debug = false; 3174ad5def9SAdrian McCarthy break; 3184ad5def9SAdrian McCarthy case LOAD_DLL_DEBUG_EVENT: 3194ad5def9SAdrian McCarthy continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); 3204ad5def9SAdrian McCarthy break; 3214ad5def9SAdrian McCarthy case UNLOAD_DLL_DEBUG_EVENT: 3224ad5def9SAdrian McCarthy continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); 3234ad5def9SAdrian McCarthy break; 3244ad5def9SAdrian McCarthy case OUTPUT_DEBUG_STRING_EVENT: 3254ad5def9SAdrian McCarthy continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); 3264ad5def9SAdrian McCarthy break; 3274ad5def9SAdrian McCarthy case RIP_EVENT: 3284ad5def9SAdrian McCarthy continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); 3294ad5def9SAdrian McCarthy if (dbe.u.RipInfo.dwType == SLE_ERROR) 3304ad5def9SAdrian McCarthy should_debug = false; 3314ad5def9SAdrian McCarthy break; 3324ad5def9SAdrian McCarthy } 3334ad5def9SAdrian McCarthy 3344ad5def9SAdrian McCarthy WINLOGD_IFALL( 3354ad5def9SAdrian McCarthy WINDOWS_LOG_EVENT, 3364ad5def9SAdrian McCarthy "DebugLoop calling ContinueDebugEvent(%lu, %lu, %lu) on thread %lu.", 3374ad5def9SAdrian McCarthy dbe.dwProcessId, dbe.dwThreadId, continue_status, 3384ad5def9SAdrian McCarthy ::GetCurrentThreadId()); 3394ad5def9SAdrian McCarthy 3404ad5def9SAdrian McCarthy ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); 3414ad5def9SAdrian McCarthy 3424ad5def9SAdrian McCarthy if (m_detached) { 3434ad5def9SAdrian McCarthy should_debug = false; 3444ad5def9SAdrian McCarthy } 3454ad5def9SAdrian McCarthy } else { 3464ad5def9SAdrian McCarthy WINERR_IFALL( 3474ad5def9SAdrian McCarthy WINDOWS_LOG_EVENT, 3484ad5def9SAdrian McCarthy "DebugLoop returned FALSE from WaitForDebugEvent. Error = %lu", 3494ad5def9SAdrian McCarthy ::GetLastError()); 3504ad5def9SAdrian McCarthy 3514ad5def9SAdrian McCarthy should_debug = false; 3524ad5def9SAdrian McCarthy } 3534ad5def9SAdrian McCarthy } 3544ad5def9SAdrian McCarthy FreeProcessHandles(); 3554ad5def9SAdrian McCarthy 3564ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting."); 3574ad5def9SAdrian McCarthy SetEvent(m_debugging_ended_event); 3584ad5def9SAdrian McCarthy } 3594ad5def9SAdrian McCarthy 3604ad5def9SAdrian McCarthy ExceptionResult 3614ad5def9SAdrian McCarthy DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, 3624ad5def9SAdrian McCarthy DWORD thread_id) { 3634ad5def9SAdrian McCarthy if (m_is_shutting_down) { 3644ad5def9SAdrian McCarthy // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic 3654ad5def9SAdrian McCarthy // exception that 3664ad5def9SAdrian McCarthy // we use simply to wake up the DebuggerThread so that we can close out the 3674ad5def9SAdrian McCarthy // debug loop. 3684ad5def9SAdrian McCarthy if (m_pid_to_detach != 0 && 3694ad5def9SAdrian McCarthy info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { 3704ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | 3714ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 3724ad5def9SAdrian McCarthy "Breakpoint exception is cue to detach from process 0x%lx", 3734ad5def9SAdrian McCarthy m_pid_to_detach.load()); 3744ad5def9SAdrian McCarthy ::DebugActiveProcessStop(m_pid_to_detach); 3754ad5def9SAdrian McCarthy m_detached = true; 3764ad5def9SAdrian McCarthy } 3774ad5def9SAdrian McCarthy 3784ad5def9SAdrian McCarthy // Don't perform any blocking operations while we're shutting down. That 3794ad5def9SAdrian McCarthy // will 3804ad5def9SAdrian McCarthy // cause TerminateProcess -> WaitForSingleObject to time out. 3814ad5def9SAdrian McCarthy return ExceptionResult::SendToApplication; 3824ad5def9SAdrian McCarthy } 3834ad5def9SAdrian McCarthy 3844ad5def9SAdrian McCarthy bool first_chance = (info.dwFirstChance != 0); 3854ad5def9SAdrian McCarthy 3864ad5def9SAdrian McCarthy m_active_exception.reset( 3874ad5def9SAdrian McCarthy new ExceptionRecord(info.ExceptionRecord, thread_id)); 3884ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, 3894ad5def9SAdrian McCarthy "HandleExceptionEvent encountered %s chance exception 0x%lx on " 3904ad5def9SAdrian McCarthy "thread 0x%lx", 3914ad5def9SAdrian McCarthy first_chance ? "first" : "second", 3924ad5def9SAdrian McCarthy info.ExceptionRecord.ExceptionCode, thread_id); 3934ad5def9SAdrian McCarthy 3944ad5def9SAdrian McCarthy ExceptionResult result = 3954ad5def9SAdrian McCarthy m_debug_delegate->OnDebugException(first_chance, *m_active_exception); 3964ad5def9SAdrian McCarthy m_exception_pred.SetValue(result, eBroadcastNever); 3974ad5def9SAdrian McCarthy 3984ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, 3994ad5def9SAdrian McCarthy "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred " 4004ad5def9SAdrian McCarthy "!= BreakInDebugger"); 4014ad5def9SAdrian McCarthy 4024ad5def9SAdrian McCarthy m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, 4034ad5def9SAdrian McCarthy result); 4044ad5def9SAdrian McCarthy 4054ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, 4064ad5def9SAdrian McCarthy "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u", 4074ad5def9SAdrian McCarthy m_exception_pred.GetValue()); 4084ad5def9SAdrian McCarthy 4094ad5def9SAdrian McCarthy return result; 4104ad5def9SAdrian McCarthy } 4114ad5def9SAdrian McCarthy 4124ad5def9SAdrian McCarthy DWORD 4134ad5def9SAdrian McCarthy DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, 4144ad5def9SAdrian McCarthy DWORD thread_id) { 4154ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, 4164ad5def9SAdrian McCarthy "HandleCreateThreadEvent Thread 0x%lx spawned in process %llu", 4174ad5def9SAdrian McCarthy thread_id, m_process.GetProcessId()); 4184ad5def9SAdrian McCarthy HostThread thread(info.hThread); 4194ad5def9SAdrian McCarthy thread.GetNativeThread().SetOwnsHandle(false); 4204ad5def9SAdrian McCarthy m_debug_delegate->OnCreateThread(thread); 4214ad5def9SAdrian McCarthy return DBG_CONTINUE; 4224ad5def9SAdrian McCarthy } 4234ad5def9SAdrian McCarthy 4244ad5def9SAdrian McCarthy DWORD 4254ad5def9SAdrian McCarthy DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, 4264ad5def9SAdrian McCarthy DWORD thread_id) { 4274ad5def9SAdrian McCarthy uint32_t process_id = ::GetProcessId(info.hProcess); 4284ad5def9SAdrian McCarthy 4294ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, 4304ad5def9SAdrian McCarthy "HandleCreateProcessEvent process %u spawned", process_id); 4314ad5def9SAdrian McCarthy 4324ad5def9SAdrian McCarthy std::string thread_name; 4334ad5def9SAdrian McCarthy llvm::raw_string_ostream name_stream(thread_name); 4344ad5def9SAdrian McCarthy name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; 4354ad5def9SAdrian McCarthy name_stream.flush(); 4364ad5def9SAdrian McCarthy ThisThread::SetName(thread_name.c_str()); 4374ad5def9SAdrian McCarthy 4384ad5def9SAdrian McCarthy // info.hProcess and info.hThread are closed automatically by Windows when 4394ad5def9SAdrian McCarthy // EXIT_PROCESS_DEBUG_EVENT is received. 4404ad5def9SAdrian McCarthy m_process = HostProcess(info.hProcess); 4414ad5def9SAdrian McCarthy ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); 4424ad5def9SAdrian McCarthy m_main_thread = HostThread(info.hThread); 4434ad5def9SAdrian McCarthy m_main_thread.GetNativeThread().SetOwnsHandle(false); 4444ad5def9SAdrian McCarthy m_image_file = info.hFile; 4454ad5def9SAdrian McCarthy 4464ad5def9SAdrian McCarthy lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); 4474ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerConnected(load_addr); 4484ad5def9SAdrian McCarthy 4494ad5def9SAdrian McCarthy return DBG_CONTINUE; 4504ad5def9SAdrian McCarthy } 4514ad5def9SAdrian McCarthy 4524ad5def9SAdrian McCarthy DWORD 4534ad5def9SAdrian McCarthy DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, 4544ad5def9SAdrian McCarthy DWORD thread_id) { 4554ad5def9SAdrian McCarthy WINLOG_IFANY( 4564ad5def9SAdrian McCarthy WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, 4574ad5def9SAdrian McCarthy "HandleExitThreadEvent Thread %lu exited with code %lu in process %llu", 4584ad5def9SAdrian McCarthy thread_id, info.dwExitCode, m_process.GetProcessId()); 4594ad5def9SAdrian McCarthy m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); 4604ad5def9SAdrian McCarthy return DBG_CONTINUE; 4614ad5def9SAdrian McCarthy } 4624ad5def9SAdrian McCarthy 4634ad5def9SAdrian McCarthy DWORD 4644ad5def9SAdrian McCarthy DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, 4654ad5def9SAdrian McCarthy DWORD thread_id) { 4664ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, 4674ad5def9SAdrian McCarthy "HandleExitProcessEvent process %llu exited with code %lu", 4684ad5def9SAdrian McCarthy m_process.GetProcessId(), info.dwExitCode); 4694ad5def9SAdrian McCarthy 4704ad5def9SAdrian McCarthy m_debug_delegate->OnExitProcess(info.dwExitCode); 4714ad5def9SAdrian McCarthy 4724ad5def9SAdrian McCarthy FreeProcessHandles(); 4734ad5def9SAdrian McCarthy return DBG_CONTINUE; 4744ad5def9SAdrian McCarthy } 4754ad5def9SAdrian McCarthy 4764ad5def9SAdrian McCarthy DWORD 4774ad5def9SAdrian McCarthy DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, 4784ad5def9SAdrian McCarthy DWORD thread_id) { 4794ad5def9SAdrian McCarthy if (info.hFile == nullptr) { 4804ad5def9SAdrian McCarthy // Not sure what this is, so just ignore it. 4814ad5def9SAdrian McCarthy WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %llu - HandleLoadDllEvent has " 4824ad5def9SAdrian McCarthy "a NULL file handle, returning...", 4834ad5def9SAdrian McCarthy m_process.GetProcessId()); 4844ad5def9SAdrian McCarthy return DBG_CONTINUE; 4854ad5def9SAdrian McCarthy } 4864ad5def9SAdrian McCarthy 4874ad5def9SAdrian McCarthy std::vector<wchar_t> buffer(1); 4884ad5def9SAdrian McCarthy DWORD required_size = 4894ad5def9SAdrian McCarthy GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); 4904ad5def9SAdrian McCarthy if (required_size > 0) { 4914ad5def9SAdrian McCarthy buffer.resize(required_size + 1); 4924ad5def9SAdrian McCarthy required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 4934ad5def9SAdrian McCarthy required_size, VOLUME_NAME_DOS); 4944ad5def9SAdrian McCarthy std::string path_str_utf8; 4954ad5def9SAdrian McCarthy llvm::convertWideToUTF8(buffer.data(), path_str_utf8); 4964ad5def9SAdrian McCarthy llvm::StringRef path_str = path_str_utf8; 4974ad5def9SAdrian McCarthy const char *path = path_str.data(); 4984ad5def9SAdrian McCarthy if (path_str.startswith("\\\\?\\")) 4994ad5def9SAdrian McCarthy path += 4; 5004ad5def9SAdrian McCarthy 5014ad5def9SAdrian McCarthy FileSpec file_spec(path, false); 5024ad5def9SAdrian McCarthy ModuleSpec module_spec(file_spec); 5034ad5def9SAdrian McCarthy lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); 5044ad5def9SAdrian McCarthy 5054ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL " 5064ad5def9SAdrian McCarthy "'%s' loaded at address 0x%p...", 5074ad5def9SAdrian McCarthy m_process.GetProcessId(), path, info.lpBaseOfDll); 5084ad5def9SAdrian McCarthy 5094ad5def9SAdrian McCarthy m_debug_delegate->OnLoadDll(module_spec, load_addr); 5104ad5def9SAdrian McCarthy } else { 5114ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_EVENT, "Inferior %llu - HandleLoadDllEvent Error " 5124ad5def9SAdrian McCarthy "%lu occurred calling " 5134ad5def9SAdrian McCarthy "GetFinalPathNameByHandle", 5144ad5def9SAdrian McCarthy m_process.GetProcessId(), ::GetLastError()); 5154ad5def9SAdrian McCarthy } 5164ad5def9SAdrian McCarthy // Windows does not automatically close info.hFile, so we need to do it. 5174ad5def9SAdrian McCarthy ::CloseHandle(info.hFile); 5184ad5def9SAdrian McCarthy return DBG_CONTINUE; 5194ad5def9SAdrian McCarthy } 5204ad5def9SAdrian McCarthy 5214ad5def9SAdrian McCarthy DWORD 5224ad5def9SAdrian McCarthy DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, 5234ad5def9SAdrian McCarthy DWORD thread_id) { 5244ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, 5254ad5def9SAdrian McCarthy "HandleUnloadDllEvent process %llu unloading DLL at addr 0x%p.", 5264ad5def9SAdrian McCarthy m_process.GetProcessId(), info.lpBaseOfDll); 5274ad5def9SAdrian McCarthy 5284ad5def9SAdrian McCarthy m_debug_delegate->OnUnloadDll( 5294ad5def9SAdrian McCarthy reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); 5304ad5def9SAdrian McCarthy return DBG_CONTINUE; 5314ad5def9SAdrian McCarthy } 5324ad5def9SAdrian McCarthy 5334ad5def9SAdrian McCarthy DWORD 5344ad5def9SAdrian McCarthy DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, 5354ad5def9SAdrian McCarthy DWORD thread_id) { 5364ad5def9SAdrian McCarthy return DBG_CONTINUE; 5374ad5def9SAdrian McCarthy } 5384ad5def9SAdrian McCarthy 5394ad5def9SAdrian McCarthy DWORD 5404ad5def9SAdrian McCarthy DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { 5414ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_EVENT, "HandleRipEvent encountered error %lu " 5424ad5def9SAdrian McCarthy "(type=%lu) in process %llu thread %lu", 5434ad5def9SAdrian McCarthy info.dwError, info.dwType, m_process.GetProcessId(), thread_id); 5444ad5def9SAdrian McCarthy 5454ad5def9SAdrian McCarthy Error error(info.dwError, eErrorTypeWin32); 5464ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, info.dwType); 5474ad5def9SAdrian McCarthy 5484ad5def9SAdrian McCarthy return DBG_CONTINUE; 5494ad5def9SAdrian McCarthy } 550