1*4ad5def9SAdrian McCarthy //===-- DebuggerThread.DebuggerThread --------------------------------------*- 2*4ad5def9SAdrian McCarthy // C++ -*-===// 3*4ad5def9SAdrian McCarthy // 4*4ad5def9SAdrian McCarthy // The LLVM Compiler Infrastructure 5*4ad5def9SAdrian McCarthy // 6*4ad5def9SAdrian McCarthy // This file is distributed under the University of Illinois Open Source 7*4ad5def9SAdrian McCarthy // License. See LICENSE.TXT for details. 8*4ad5def9SAdrian McCarthy // 9*4ad5def9SAdrian McCarthy //===----------------------------------------------------------------------===// 10*4ad5def9SAdrian McCarthy 11*4ad5def9SAdrian McCarthy #include "DebuggerThread.h" 12*4ad5def9SAdrian McCarthy #include "ExceptionRecord.h" 13*4ad5def9SAdrian McCarthy #include "IDebugDelegate.h" 14*4ad5def9SAdrian McCarthy 15*4ad5def9SAdrian McCarthy #include "lldb/Core/Error.h" 16*4ad5def9SAdrian McCarthy #include "lldb/Core/Log.h" 17*4ad5def9SAdrian McCarthy #include "lldb/Core/ModuleSpec.h" 18*4ad5def9SAdrian McCarthy #include "lldb/Host/FileSpec.h" 19*4ad5def9SAdrian McCarthy #include "lldb/Host/Predicate.h" 20*4ad5def9SAdrian McCarthy #include "lldb/Host/ThisThread.h" 21*4ad5def9SAdrian McCarthy #include "lldb/Host/ThreadLauncher.h" 22*4ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostProcessWindows.h" 23*4ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h" 24*4ad5def9SAdrian McCarthy #include "lldb/Host/windows/ProcessLauncherWindows.h" 25*4ad5def9SAdrian McCarthy #include "lldb/Target/Process.h" 26*4ad5def9SAdrian McCarthy #include "lldb/Target/ProcessLaunchInfo.h" 27*4ad5def9SAdrian McCarthy 28*4ad5def9SAdrian McCarthy #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" 29*4ad5def9SAdrian McCarthy 30*4ad5def9SAdrian McCarthy #include "llvm/ADT/STLExtras.h" 31*4ad5def9SAdrian McCarthy #include "llvm/Support/ConvertUTF.h" 32*4ad5def9SAdrian McCarthy #include "llvm/Support/raw_ostream.h" 33*4ad5def9SAdrian McCarthy 34*4ad5def9SAdrian McCarthy using namespace lldb; 35*4ad5def9SAdrian McCarthy using namespace lldb_private; 36*4ad5def9SAdrian McCarthy 37*4ad5def9SAdrian McCarthy namespace { 38*4ad5def9SAdrian McCarthy struct DebugLaunchContext { 39*4ad5def9SAdrian McCarthy DebugLaunchContext(DebuggerThread *thread, 40*4ad5def9SAdrian McCarthy const ProcessLaunchInfo &launch_info) 41*4ad5def9SAdrian McCarthy : m_thread(thread), m_launch_info(launch_info) {} 42*4ad5def9SAdrian McCarthy DebuggerThread *m_thread; 43*4ad5def9SAdrian McCarthy ProcessLaunchInfo m_launch_info; 44*4ad5def9SAdrian McCarthy }; 45*4ad5def9SAdrian McCarthy 46*4ad5def9SAdrian McCarthy struct DebugAttachContext { 47*4ad5def9SAdrian McCarthy DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, 48*4ad5def9SAdrian McCarthy const ProcessAttachInfo &attach_info) 49*4ad5def9SAdrian McCarthy : m_thread(thread), m_pid(pid), m_attach_info(attach_info) {} 50*4ad5def9SAdrian McCarthy DebuggerThread *m_thread; 51*4ad5def9SAdrian McCarthy lldb::pid_t m_pid; 52*4ad5def9SAdrian McCarthy ProcessAttachInfo m_attach_info; 53*4ad5def9SAdrian McCarthy }; 54*4ad5def9SAdrian McCarthy } 55*4ad5def9SAdrian McCarthy 56*4ad5def9SAdrian McCarthy DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) 57*4ad5def9SAdrian McCarthy : m_debug_delegate(debug_delegate), m_pid_to_detach(0), 58*4ad5def9SAdrian McCarthy m_is_shutting_down(false) { 59*4ad5def9SAdrian McCarthy m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 60*4ad5def9SAdrian McCarthy } 61*4ad5def9SAdrian McCarthy 62*4ad5def9SAdrian McCarthy DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } 63*4ad5def9SAdrian McCarthy 64*4ad5def9SAdrian McCarthy Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { 65*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 66*4ad5def9SAdrian McCarthy "DebuggerThread::DebugLaunch launching '%s'", 67*4ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str()); 68*4ad5def9SAdrian McCarthy 69*4ad5def9SAdrian McCarthy Error error; 70*4ad5def9SAdrian McCarthy DebugLaunchContext *context = new DebugLaunchContext(this, launch_info); 71*4ad5def9SAdrian McCarthy HostThread slave_thread(ThreadLauncher::LaunchThread( 72*4ad5def9SAdrian McCarthy "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine, 73*4ad5def9SAdrian McCarthy context, &error)); 74*4ad5def9SAdrian McCarthy 75*4ad5def9SAdrian McCarthy if (!error.Success()) { 76*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, 77*4ad5def9SAdrian McCarthy "DebugLaunch couldn't launch debugger thread. %s", 78*4ad5def9SAdrian McCarthy error.AsCString()); 79*4ad5def9SAdrian McCarthy } 80*4ad5def9SAdrian McCarthy 81*4ad5def9SAdrian McCarthy return error; 82*4ad5def9SAdrian McCarthy } 83*4ad5def9SAdrian McCarthy 84*4ad5def9SAdrian McCarthy Error DebuggerThread::DebugAttach(lldb::pid_t pid, 85*4ad5def9SAdrian McCarthy const ProcessAttachInfo &attach_info) { 86*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 87*4ad5def9SAdrian McCarthy "DebuggerThread::DebugAttach attaching to '%llu'", pid); 88*4ad5def9SAdrian McCarthy 89*4ad5def9SAdrian McCarthy Error error; 90*4ad5def9SAdrian McCarthy DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info); 91*4ad5def9SAdrian McCarthy HostThread slave_thread(ThreadLauncher::LaunchThread( 92*4ad5def9SAdrian McCarthy "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine, 93*4ad5def9SAdrian McCarthy context, &error)); 94*4ad5def9SAdrian McCarthy 95*4ad5def9SAdrian McCarthy if (!error.Success()) { 96*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, 97*4ad5def9SAdrian McCarthy "DebugAttach couldn't attach to process '%llu'. %s", pid, 98*4ad5def9SAdrian McCarthy error.AsCString()); 99*4ad5def9SAdrian McCarthy } 100*4ad5def9SAdrian McCarthy 101*4ad5def9SAdrian McCarthy return error; 102*4ad5def9SAdrian McCarthy } 103*4ad5def9SAdrian McCarthy 104*4ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) { 105*4ad5def9SAdrian McCarthy DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data); 106*4ad5def9SAdrian McCarthy lldb::thread_result_t result = 107*4ad5def9SAdrian McCarthy context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info); 108*4ad5def9SAdrian McCarthy delete context; 109*4ad5def9SAdrian McCarthy return result; 110*4ad5def9SAdrian McCarthy } 111*4ad5def9SAdrian McCarthy 112*4ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) { 113*4ad5def9SAdrian McCarthy DebugAttachContext *context = static_cast<DebugAttachContext *>(data); 114*4ad5def9SAdrian McCarthy lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine( 115*4ad5def9SAdrian McCarthy context->m_pid, context->m_attach_info); 116*4ad5def9SAdrian McCarthy delete context; 117*4ad5def9SAdrian McCarthy return result; 118*4ad5def9SAdrian McCarthy } 119*4ad5def9SAdrian McCarthy 120*4ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( 121*4ad5def9SAdrian McCarthy const ProcessLaunchInfo &launch_info) { 122*4ad5def9SAdrian McCarthy // Grab a shared_ptr reference to this so that we know it won't get deleted 123*4ad5def9SAdrian McCarthy // until after the 124*4ad5def9SAdrian McCarthy // thread routine has exited. 125*4ad5def9SAdrian McCarthy std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 126*4ad5def9SAdrian McCarthy 127*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 128*4ad5def9SAdrian McCarthy "DebuggerThread preparing to launch '%s' on background thread.", 129*4ad5def9SAdrian McCarthy launch_info.GetExecutableFile().GetPath().c_str()); 130*4ad5def9SAdrian McCarthy 131*4ad5def9SAdrian McCarthy Error error; 132*4ad5def9SAdrian McCarthy ProcessLauncherWindows launcher; 133*4ad5def9SAdrian McCarthy HostProcess process(launcher.LaunchProcess(launch_info, error)); 134*4ad5def9SAdrian McCarthy // If we couldn't create the process, notify waiters immediately. Otherwise 135*4ad5def9SAdrian McCarthy // enter the debug 136*4ad5def9SAdrian McCarthy // loop and wait until we get the create process debug notification. Note 137*4ad5def9SAdrian McCarthy // that if the process 138*4ad5def9SAdrian McCarthy // was created successfully, we can throw away the process handle we got from 139*4ad5def9SAdrian McCarthy // CreateProcess 140*4ad5def9SAdrian McCarthy // because Windows will give us another (potentially more useful?) handle when 141*4ad5def9SAdrian McCarthy // it sends us the 142*4ad5def9SAdrian McCarthy // CREATE_PROCESS_DEBUG_EVENT. 143*4ad5def9SAdrian McCarthy if (error.Success()) 144*4ad5def9SAdrian McCarthy DebugLoop(); 145*4ad5def9SAdrian McCarthy else 146*4ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, 0); 147*4ad5def9SAdrian McCarthy 148*4ad5def9SAdrian McCarthy return 0; 149*4ad5def9SAdrian McCarthy } 150*4ad5def9SAdrian McCarthy 151*4ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( 152*4ad5def9SAdrian McCarthy lldb::pid_t pid, const ProcessAttachInfo &attach_info) { 153*4ad5def9SAdrian McCarthy // Grab a shared_ptr reference to this so that we know it won't get deleted 154*4ad5def9SAdrian McCarthy // until after the 155*4ad5def9SAdrian McCarthy // thread routine has exited. 156*4ad5def9SAdrian McCarthy std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 157*4ad5def9SAdrian McCarthy 158*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to " 159*4ad5def9SAdrian McCarthy "process '%llu' on background thread.", 160*4ad5def9SAdrian McCarthy pid); 161*4ad5def9SAdrian McCarthy 162*4ad5def9SAdrian McCarthy if (!DebugActiveProcess((DWORD)pid)) { 163*4ad5def9SAdrian McCarthy Error error(::GetLastError(), eErrorTypeWin32); 164*4ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, 0); 165*4ad5def9SAdrian McCarthy return 0; 166*4ad5def9SAdrian McCarthy } 167*4ad5def9SAdrian McCarthy 168*4ad5def9SAdrian McCarthy // The attach was successful, enter the debug loop. From here on out, this is 169*4ad5def9SAdrian McCarthy // no different than 170*4ad5def9SAdrian McCarthy // a create process operation, so all the same comments in DebugLaunch should 171*4ad5def9SAdrian McCarthy // apply from this 172*4ad5def9SAdrian McCarthy // point out. 173*4ad5def9SAdrian McCarthy DebugLoop(); 174*4ad5def9SAdrian McCarthy 175*4ad5def9SAdrian McCarthy return 0; 176*4ad5def9SAdrian McCarthy } 177*4ad5def9SAdrian McCarthy 178*4ad5def9SAdrian McCarthy Error DebuggerThread::StopDebugging(bool terminate) { 179*4ad5def9SAdrian McCarthy Error error; 180*4ad5def9SAdrian McCarthy 181*4ad5def9SAdrian McCarthy lldb::pid_t pid = m_process.GetProcessId(); 182*4ad5def9SAdrian McCarthy 183*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, 184*4ad5def9SAdrian McCarthy "StopDebugging('%s') called (inferior=%I64u).", 185*4ad5def9SAdrian McCarthy (terminate ? "true" : "false"), pid); 186*4ad5def9SAdrian McCarthy 187*4ad5def9SAdrian McCarthy // Set m_is_shutting_down to true if it was false. Return if it was already 188*4ad5def9SAdrian McCarthy // true. 189*4ad5def9SAdrian McCarthy bool expected = false; 190*4ad5def9SAdrian McCarthy if (!m_is_shutting_down.compare_exchange_strong(expected, true)) 191*4ad5def9SAdrian McCarthy return error; 192*4ad5def9SAdrian McCarthy 193*4ad5def9SAdrian McCarthy // Make a copy of the process, since the termination sequence will reset 194*4ad5def9SAdrian McCarthy // DebuggerThread's internal copy and it needs to remain open for the Wait 195*4ad5def9SAdrian McCarthy // operation. 196*4ad5def9SAdrian McCarthy HostProcess process_copy = m_process; 197*4ad5def9SAdrian McCarthy lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); 198*4ad5def9SAdrian McCarthy 199*4ad5def9SAdrian McCarthy if (terminate) { 200*4ad5def9SAdrian McCarthy // Initiate the termination before continuing the exception, so that the 201*4ad5def9SAdrian McCarthy // next debug 202*4ad5def9SAdrian McCarthy // event we get is the exit process event, and not some other event. 203*4ad5def9SAdrian McCarthy BOOL terminate_suceeded = TerminateProcess(handle, 0); 204*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging called " 205*4ad5def9SAdrian McCarthy "TerminateProcess(0x%p, 0) " 206*4ad5def9SAdrian McCarthy "(inferior=%I64u), success='%s'", 207*4ad5def9SAdrian McCarthy handle, pid, (terminate_suceeded ? "true" : "false")); 208*4ad5def9SAdrian McCarthy } 209*4ad5def9SAdrian McCarthy 210*4ad5def9SAdrian McCarthy // If we're stuck waiting for an exception to continue (e.g. the user is at a 211*4ad5def9SAdrian McCarthy // breakpoint 212*4ad5def9SAdrian McCarthy // messing around in the debugger), continue it now. But only AFTER calling 213*4ad5def9SAdrian McCarthy // TerminateProcess 214*4ad5def9SAdrian McCarthy // to make sure that the very next call to WaitForDebugEvent is an exit 215*4ad5def9SAdrian McCarthy // process event. 216*4ad5def9SAdrian McCarthy if (m_active_exception.get()) { 217*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, 218*4ad5def9SAdrian McCarthy "StopDebugging masking active exception"); 219*4ad5def9SAdrian McCarthy 220*4ad5def9SAdrian McCarthy ContinueAsyncException(ExceptionResult::MaskException); 221*4ad5def9SAdrian McCarthy } 222*4ad5def9SAdrian McCarthy 223*4ad5def9SAdrian McCarthy if (!terminate) { 224*4ad5def9SAdrian McCarthy // Indicate that we want to detach. 225*4ad5def9SAdrian McCarthy m_pid_to_detach = GetProcess().GetProcessId(); 226*4ad5def9SAdrian McCarthy 227*4ad5def9SAdrian McCarthy // Force a fresh break so that the detach can happen from the debugger 228*4ad5def9SAdrian McCarthy // thread. 229*4ad5def9SAdrian McCarthy if (!::DebugBreakProcess( 230*4ad5def9SAdrian McCarthy GetProcess().GetNativeProcess().GetSystemHandle())) { 231*4ad5def9SAdrian McCarthy error.SetError(::GetLastError(), eErrorTypeWin32); 232*4ad5def9SAdrian McCarthy } 233*4ad5def9SAdrian McCarthy } 234*4ad5def9SAdrian McCarthy 235*4ad5def9SAdrian McCarthy WINLOG_IFALL( 236*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 237*4ad5def9SAdrian McCarthy "StopDebugging waiting for detach from process %llu to complete.", pid); 238*4ad5def9SAdrian McCarthy 239*4ad5def9SAdrian McCarthy DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); 240*4ad5def9SAdrian McCarthy if (wait_result != WAIT_OBJECT_0) { 241*4ad5def9SAdrian McCarthy error.SetError(GetLastError(), eErrorTypeWin32); 242*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, 243*4ad5def9SAdrian McCarthy "StopDebugging WaitForSingleObject(0x%p, 5000) returned %lu", 244*4ad5def9SAdrian McCarthy m_debugging_ended_event, wait_result); 245*4ad5def9SAdrian McCarthy } else { 246*4ad5def9SAdrian McCarthy WINLOG_IFALL( 247*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 248*4ad5def9SAdrian McCarthy "StopDebugging detach from process %llu completed successfully.", pid); 249*4ad5def9SAdrian McCarthy } 250*4ad5def9SAdrian McCarthy 251*4ad5def9SAdrian McCarthy if (!error.Success()) { 252*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging encountered an error " 253*4ad5def9SAdrian McCarthy "while trying to stop process %llu. %s", 254*4ad5def9SAdrian McCarthy pid, error.AsCString()); 255*4ad5def9SAdrian McCarthy } 256*4ad5def9SAdrian McCarthy return error; 257*4ad5def9SAdrian McCarthy } 258*4ad5def9SAdrian McCarthy 259*4ad5def9SAdrian McCarthy void DebuggerThread::ContinueAsyncException(ExceptionResult result) { 260*4ad5def9SAdrian McCarthy if (!m_active_exception.get()) 261*4ad5def9SAdrian McCarthy return; 262*4ad5def9SAdrian McCarthy 263*4ad5def9SAdrian McCarthy WINLOG_IFANY( 264*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION, 265*4ad5def9SAdrian McCarthy "ContinueAsyncException called for inferior process %I64u, broadcasting.", 266*4ad5def9SAdrian McCarthy m_process.GetProcessId()); 267*4ad5def9SAdrian McCarthy 268*4ad5def9SAdrian McCarthy m_active_exception.reset(); 269*4ad5def9SAdrian McCarthy m_exception_pred.SetValue(result, eBroadcastAlways); 270*4ad5def9SAdrian McCarthy } 271*4ad5def9SAdrian McCarthy 272*4ad5def9SAdrian McCarthy void DebuggerThread::FreeProcessHandles() { 273*4ad5def9SAdrian McCarthy m_process = HostProcess(); 274*4ad5def9SAdrian McCarthy m_main_thread = HostThread(); 275*4ad5def9SAdrian McCarthy if (m_image_file) { 276*4ad5def9SAdrian McCarthy ::CloseHandle(m_image_file); 277*4ad5def9SAdrian McCarthy m_image_file = nullptr; 278*4ad5def9SAdrian McCarthy } 279*4ad5def9SAdrian McCarthy } 280*4ad5def9SAdrian McCarthy 281*4ad5def9SAdrian McCarthy void DebuggerThread::DebugLoop() { 282*4ad5def9SAdrian McCarthy DEBUG_EVENT dbe = {}; 283*4ad5def9SAdrian McCarthy bool should_debug = true; 284*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop"); 285*4ad5def9SAdrian McCarthy while (should_debug) { 286*4ad5def9SAdrian McCarthy WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent"); 287*4ad5def9SAdrian McCarthy BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); 288*4ad5def9SAdrian McCarthy if (wait_result) { 289*4ad5def9SAdrian McCarthy DWORD continue_status = DBG_CONTINUE; 290*4ad5def9SAdrian McCarthy switch (dbe.dwDebugEventCode) { 291*4ad5def9SAdrian McCarthy case EXCEPTION_DEBUG_EVENT: { 292*4ad5def9SAdrian McCarthy ExceptionResult status = 293*4ad5def9SAdrian McCarthy HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); 294*4ad5def9SAdrian McCarthy 295*4ad5def9SAdrian McCarthy if (status == ExceptionResult::MaskException) 296*4ad5def9SAdrian McCarthy continue_status = DBG_CONTINUE; 297*4ad5def9SAdrian McCarthy else if (status == ExceptionResult::SendToApplication) 298*4ad5def9SAdrian McCarthy continue_status = DBG_EXCEPTION_NOT_HANDLED; 299*4ad5def9SAdrian McCarthy 300*4ad5def9SAdrian McCarthy break; 301*4ad5def9SAdrian McCarthy } 302*4ad5def9SAdrian McCarthy case CREATE_THREAD_DEBUG_EVENT: 303*4ad5def9SAdrian McCarthy continue_status = 304*4ad5def9SAdrian McCarthy HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); 305*4ad5def9SAdrian McCarthy break; 306*4ad5def9SAdrian McCarthy case CREATE_PROCESS_DEBUG_EVENT: 307*4ad5def9SAdrian McCarthy continue_status = 308*4ad5def9SAdrian McCarthy HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); 309*4ad5def9SAdrian McCarthy break; 310*4ad5def9SAdrian McCarthy case EXIT_THREAD_DEBUG_EVENT: 311*4ad5def9SAdrian McCarthy continue_status = 312*4ad5def9SAdrian McCarthy HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); 313*4ad5def9SAdrian McCarthy break; 314*4ad5def9SAdrian McCarthy case EXIT_PROCESS_DEBUG_EVENT: 315*4ad5def9SAdrian McCarthy continue_status = 316*4ad5def9SAdrian McCarthy HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); 317*4ad5def9SAdrian McCarthy should_debug = false; 318*4ad5def9SAdrian McCarthy break; 319*4ad5def9SAdrian McCarthy case LOAD_DLL_DEBUG_EVENT: 320*4ad5def9SAdrian McCarthy continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); 321*4ad5def9SAdrian McCarthy break; 322*4ad5def9SAdrian McCarthy case UNLOAD_DLL_DEBUG_EVENT: 323*4ad5def9SAdrian McCarthy continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); 324*4ad5def9SAdrian McCarthy break; 325*4ad5def9SAdrian McCarthy case OUTPUT_DEBUG_STRING_EVENT: 326*4ad5def9SAdrian McCarthy continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); 327*4ad5def9SAdrian McCarthy break; 328*4ad5def9SAdrian McCarthy case RIP_EVENT: 329*4ad5def9SAdrian McCarthy continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); 330*4ad5def9SAdrian McCarthy if (dbe.u.RipInfo.dwType == SLE_ERROR) 331*4ad5def9SAdrian McCarthy should_debug = false; 332*4ad5def9SAdrian McCarthy break; 333*4ad5def9SAdrian McCarthy } 334*4ad5def9SAdrian McCarthy 335*4ad5def9SAdrian McCarthy WINLOGD_IFALL( 336*4ad5def9SAdrian McCarthy WINDOWS_LOG_EVENT, 337*4ad5def9SAdrian McCarthy "DebugLoop calling ContinueDebugEvent(%lu, %lu, %lu) on thread %lu.", 338*4ad5def9SAdrian McCarthy dbe.dwProcessId, dbe.dwThreadId, continue_status, 339*4ad5def9SAdrian McCarthy ::GetCurrentThreadId()); 340*4ad5def9SAdrian McCarthy 341*4ad5def9SAdrian McCarthy ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); 342*4ad5def9SAdrian McCarthy 343*4ad5def9SAdrian McCarthy if (m_detached) { 344*4ad5def9SAdrian McCarthy should_debug = false; 345*4ad5def9SAdrian McCarthy } 346*4ad5def9SAdrian McCarthy } else { 347*4ad5def9SAdrian McCarthy WINERR_IFALL( 348*4ad5def9SAdrian McCarthy WINDOWS_LOG_EVENT, 349*4ad5def9SAdrian McCarthy "DebugLoop returned FALSE from WaitForDebugEvent. Error = %lu", 350*4ad5def9SAdrian McCarthy ::GetLastError()); 351*4ad5def9SAdrian McCarthy 352*4ad5def9SAdrian McCarthy should_debug = false; 353*4ad5def9SAdrian McCarthy } 354*4ad5def9SAdrian McCarthy } 355*4ad5def9SAdrian McCarthy FreeProcessHandles(); 356*4ad5def9SAdrian McCarthy 357*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting."); 358*4ad5def9SAdrian McCarthy SetEvent(m_debugging_ended_event); 359*4ad5def9SAdrian McCarthy } 360*4ad5def9SAdrian McCarthy 361*4ad5def9SAdrian McCarthy ExceptionResult 362*4ad5def9SAdrian McCarthy DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, 363*4ad5def9SAdrian McCarthy DWORD thread_id) { 364*4ad5def9SAdrian McCarthy if (m_is_shutting_down) { 365*4ad5def9SAdrian McCarthy // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic 366*4ad5def9SAdrian McCarthy // exception that 367*4ad5def9SAdrian McCarthy // we use simply to wake up the DebuggerThread so that we can close out the 368*4ad5def9SAdrian McCarthy // debug loop. 369*4ad5def9SAdrian McCarthy if (m_pid_to_detach != 0 && 370*4ad5def9SAdrian McCarthy info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { 371*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | 372*4ad5def9SAdrian McCarthy WINDOWS_LOG_PROCESS, 373*4ad5def9SAdrian McCarthy "Breakpoint exception is cue to detach from process 0x%lx", 374*4ad5def9SAdrian McCarthy m_pid_to_detach.load()); 375*4ad5def9SAdrian McCarthy ::DebugActiveProcessStop(m_pid_to_detach); 376*4ad5def9SAdrian McCarthy m_detached = true; 377*4ad5def9SAdrian McCarthy } 378*4ad5def9SAdrian McCarthy 379*4ad5def9SAdrian McCarthy // Don't perform any blocking operations while we're shutting down. That 380*4ad5def9SAdrian McCarthy // will 381*4ad5def9SAdrian McCarthy // cause TerminateProcess -> WaitForSingleObject to time out. 382*4ad5def9SAdrian McCarthy return ExceptionResult::SendToApplication; 383*4ad5def9SAdrian McCarthy } 384*4ad5def9SAdrian McCarthy 385*4ad5def9SAdrian McCarthy bool first_chance = (info.dwFirstChance != 0); 386*4ad5def9SAdrian McCarthy 387*4ad5def9SAdrian McCarthy m_active_exception.reset( 388*4ad5def9SAdrian McCarthy new ExceptionRecord(info.ExceptionRecord, thread_id)); 389*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, 390*4ad5def9SAdrian McCarthy "HandleExceptionEvent encountered %s chance exception 0x%lx on " 391*4ad5def9SAdrian McCarthy "thread 0x%lx", 392*4ad5def9SAdrian McCarthy first_chance ? "first" : "second", 393*4ad5def9SAdrian McCarthy info.ExceptionRecord.ExceptionCode, thread_id); 394*4ad5def9SAdrian McCarthy 395*4ad5def9SAdrian McCarthy ExceptionResult result = 396*4ad5def9SAdrian McCarthy m_debug_delegate->OnDebugException(first_chance, *m_active_exception); 397*4ad5def9SAdrian McCarthy m_exception_pred.SetValue(result, eBroadcastNever); 398*4ad5def9SAdrian McCarthy 399*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, 400*4ad5def9SAdrian McCarthy "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred " 401*4ad5def9SAdrian McCarthy "!= BreakInDebugger"); 402*4ad5def9SAdrian McCarthy 403*4ad5def9SAdrian McCarthy m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, 404*4ad5def9SAdrian McCarthy result); 405*4ad5def9SAdrian McCarthy 406*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION, 407*4ad5def9SAdrian McCarthy "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u", 408*4ad5def9SAdrian McCarthy m_exception_pred.GetValue()); 409*4ad5def9SAdrian McCarthy 410*4ad5def9SAdrian McCarthy return result; 411*4ad5def9SAdrian McCarthy } 412*4ad5def9SAdrian McCarthy 413*4ad5def9SAdrian McCarthy DWORD 414*4ad5def9SAdrian McCarthy DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, 415*4ad5def9SAdrian McCarthy DWORD thread_id) { 416*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, 417*4ad5def9SAdrian McCarthy "HandleCreateThreadEvent Thread 0x%lx spawned in process %llu", 418*4ad5def9SAdrian McCarthy thread_id, m_process.GetProcessId()); 419*4ad5def9SAdrian McCarthy HostThread thread(info.hThread); 420*4ad5def9SAdrian McCarthy thread.GetNativeThread().SetOwnsHandle(false); 421*4ad5def9SAdrian McCarthy m_debug_delegate->OnCreateThread(thread); 422*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 423*4ad5def9SAdrian McCarthy } 424*4ad5def9SAdrian McCarthy 425*4ad5def9SAdrian McCarthy DWORD 426*4ad5def9SAdrian McCarthy DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, 427*4ad5def9SAdrian McCarthy DWORD thread_id) { 428*4ad5def9SAdrian McCarthy uint32_t process_id = ::GetProcessId(info.hProcess); 429*4ad5def9SAdrian McCarthy 430*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, 431*4ad5def9SAdrian McCarthy "HandleCreateProcessEvent process %u spawned", process_id); 432*4ad5def9SAdrian McCarthy 433*4ad5def9SAdrian McCarthy std::string thread_name; 434*4ad5def9SAdrian McCarthy llvm::raw_string_ostream name_stream(thread_name); 435*4ad5def9SAdrian McCarthy name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]"; 436*4ad5def9SAdrian McCarthy name_stream.flush(); 437*4ad5def9SAdrian McCarthy ThisThread::SetName(thread_name.c_str()); 438*4ad5def9SAdrian McCarthy 439*4ad5def9SAdrian McCarthy // info.hProcess and info.hThread are closed automatically by Windows when 440*4ad5def9SAdrian McCarthy // EXIT_PROCESS_DEBUG_EVENT is received. 441*4ad5def9SAdrian McCarthy m_process = HostProcess(info.hProcess); 442*4ad5def9SAdrian McCarthy ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); 443*4ad5def9SAdrian McCarthy m_main_thread = HostThread(info.hThread); 444*4ad5def9SAdrian McCarthy m_main_thread.GetNativeThread().SetOwnsHandle(false); 445*4ad5def9SAdrian McCarthy m_image_file = info.hFile; 446*4ad5def9SAdrian McCarthy 447*4ad5def9SAdrian McCarthy lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); 448*4ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerConnected(load_addr); 449*4ad5def9SAdrian McCarthy 450*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 451*4ad5def9SAdrian McCarthy } 452*4ad5def9SAdrian McCarthy 453*4ad5def9SAdrian McCarthy DWORD 454*4ad5def9SAdrian McCarthy DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, 455*4ad5def9SAdrian McCarthy DWORD thread_id) { 456*4ad5def9SAdrian McCarthy WINLOG_IFANY( 457*4ad5def9SAdrian McCarthy WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, 458*4ad5def9SAdrian McCarthy "HandleExitThreadEvent Thread %lu exited with code %lu in process %llu", 459*4ad5def9SAdrian McCarthy thread_id, info.dwExitCode, m_process.GetProcessId()); 460*4ad5def9SAdrian McCarthy m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); 461*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 462*4ad5def9SAdrian McCarthy } 463*4ad5def9SAdrian McCarthy 464*4ad5def9SAdrian McCarthy DWORD 465*4ad5def9SAdrian McCarthy DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, 466*4ad5def9SAdrian McCarthy DWORD thread_id) { 467*4ad5def9SAdrian McCarthy WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD, 468*4ad5def9SAdrian McCarthy "HandleExitProcessEvent process %llu exited with code %lu", 469*4ad5def9SAdrian McCarthy m_process.GetProcessId(), info.dwExitCode); 470*4ad5def9SAdrian McCarthy 471*4ad5def9SAdrian McCarthy m_debug_delegate->OnExitProcess(info.dwExitCode); 472*4ad5def9SAdrian McCarthy 473*4ad5def9SAdrian McCarthy FreeProcessHandles(); 474*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 475*4ad5def9SAdrian McCarthy } 476*4ad5def9SAdrian McCarthy 477*4ad5def9SAdrian McCarthy DWORD 478*4ad5def9SAdrian McCarthy DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, 479*4ad5def9SAdrian McCarthy DWORD thread_id) { 480*4ad5def9SAdrian McCarthy if (info.hFile == nullptr) { 481*4ad5def9SAdrian McCarthy // Not sure what this is, so just ignore it. 482*4ad5def9SAdrian McCarthy WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %llu - HandleLoadDllEvent has " 483*4ad5def9SAdrian McCarthy "a NULL file handle, returning...", 484*4ad5def9SAdrian McCarthy m_process.GetProcessId()); 485*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 486*4ad5def9SAdrian McCarthy } 487*4ad5def9SAdrian McCarthy 488*4ad5def9SAdrian McCarthy std::vector<wchar_t> buffer(1); 489*4ad5def9SAdrian McCarthy DWORD required_size = 490*4ad5def9SAdrian McCarthy GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); 491*4ad5def9SAdrian McCarthy if (required_size > 0) { 492*4ad5def9SAdrian McCarthy buffer.resize(required_size + 1); 493*4ad5def9SAdrian McCarthy required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 494*4ad5def9SAdrian McCarthy required_size, VOLUME_NAME_DOS); 495*4ad5def9SAdrian McCarthy std::string path_str_utf8; 496*4ad5def9SAdrian McCarthy llvm::convertWideToUTF8(buffer.data(), path_str_utf8); 497*4ad5def9SAdrian McCarthy llvm::StringRef path_str = path_str_utf8; 498*4ad5def9SAdrian McCarthy const char *path = path_str.data(); 499*4ad5def9SAdrian McCarthy if (path_str.startswith("\\\\?\\")) 500*4ad5def9SAdrian McCarthy path += 4; 501*4ad5def9SAdrian McCarthy 502*4ad5def9SAdrian McCarthy FileSpec file_spec(path, false); 503*4ad5def9SAdrian McCarthy ModuleSpec module_spec(file_spec); 504*4ad5def9SAdrian McCarthy lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); 505*4ad5def9SAdrian McCarthy 506*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL " 507*4ad5def9SAdrian McCarthy "'%s' loaded at address 0x%p...", 508*4ad5def9SAdrian McCarthy m_process.GetProcessId(), path, info.lpBaseOfDll); 509*4ad5def9SAdrian McCarthy 510*4ad5def9SAdrian McCarthy m_debug_delegate->OnLoadDll(module_spec, load_addr); 511*4ad5def9SAdrian McCarthy } else { 512*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_EVENT, "Inferior %llu - HandleLoadDllEvent Error " 513*4ad5def9SAdrian McCarthy "%lu occurred calling " 514*4ad5def9SAdrian McCarthy "GetFinalPathNameByHandle", 515*4ad5def9SAdrian McCarthy m_process.GetProcessId(), ::GetLastError()); 516*4ad5def9SAdrian McCarthy } 517*4ad5def9SAdrian McCarthy // Windows does not automatically close info.hFile, so we need to do it. 518*4ad5def9SAdrian McCarthy ::CloseHandle(info.hFile); 519*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 520*4ad5def9SAdrian McCarthy } 521*4ad5def9SAdrian McCarthy 522*4ad5def9SAdrian McCarthy DWORD 523*4ad5def9SAdrian McCarthy DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, 524*4ad5def9SAdrian McCarthy DWORD thread_id) { 525*4ad5def9SAdrian McCarthy WINLOG_IFALL(WINDOWS_LOG_EVENT, 526*4ad5def9SAdrian McCarthy "HandleUnloadDllEvent process %llu unloading DLL at addr 0x%p.", 527*4ad5def9SAdrian McCarthy m_process.GetProcessId(), info.lpBaseOfDll); 528*4ad5def9SAdrian McCarthy 529*4ad5def9SAdrian McCarthy m_debug_delegate->OnUnloadDll( 530*4ad5def9SAdrian McCarthy reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); 531*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 532*4ad5def9SAdrian McCarthy } 533*4ad5def9SAdrian McCarthy 534*4ad5def9SAdrian McCarthy DWORD 535*4ad5def9SAdrian McCarthy DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, 536*4ad5def9SAdrian McCarthy DWORD thread_id) { 537*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 538*4ad5def9SAdrian McCarthy } 539*4ad5def9SAdrian McCarthy 540*4ad5def9SAdrian McCarthy DWORD 541*4ad5def9SAdrian McCarthy DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { 542*4ad5def9SAdrian McCarthy WINERR_IFALL(WINDOWS_LOG_EVENT, "HandleRipEvent encountered error %lu " 543*4ad5def9SAdrian McCarthy "(type=%lu) in process %llu thread %lu", 544*4ad5def9SAdrian McCarthy info.dwError, info.dwType, m_process.GetProcessId(), thread_id); 545*4ad5def9SAdrian McCarthy 546*4ad5def9SAdrian McCarthy Error error(info.dwError, eErrorTypeWin32); 547*4ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, info.dwType); 548*4ad5def9SAdrian McCarthy 549*4ad5def9SAdrian McCarthy return DBG_CONTINUE; 550*4ad5def9SAdrian McCarthy } 551