180814287SRaphael Isemann //===-- DebuggerThread.cpp ------------------------------------------------===// 24ad5def9SAdrian McCarthy // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64ad5def9SAdrian McCarthy // 74ad5def9SAdrian McCarthy //===----------------------------------------------------------------------===// 84ad5def9SAdrian McCarthy 94ad5def9SAdrian McCarthy #include "DebuggerThread.h" 104ad5def9SAdrian McCarthy #include "ExceptionRecord.h" 114ad5def9SAdrian McCarthy #include "IDebugDelegate.h" 124ad5def9SAdrian McCarthy 134ad5def9SAdrian McCarthy #include "lldb/Core/ModuleSpec.h" 14e7404d99SPavel Labath #include "lldb/Host/ProcessLaunchInfo.h" 154ad5def9SAdrian McCarthy #include "lldb/Host/ThreadLauncher.h" 164ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostProcessWindows.h" 174ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h" 184ad5def9SAdrian McCarthy #include "lldb/Host/windows/ProcessLauncherWindows.h" 194ad5def9SAdrian McCarthy #include "lldb/Target/Process.h" 205713a05bSZachary Turner #include "lldb/Utility/FileSpec.h" 216f9e6901SZachary Turner #include "lldb/Utility/Log.h" 227fae4932SRaphael Isemann #include "lldb/Utility/Predicate.h" 2397206d57SZachary Turner #include "lldb/Utility/Status.h" 244ad5def9SAdrian McCarthy 254ad5def9SAdrian McCarthy #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h" 264ad5def9SAdrian McCarthy 274ad5def9SAdrian McCarthy #include "llvm/ADT/STLExtras.h" 284ad5def9SAdrian McCarthy #include "llvm/Support/ConvertUTF.h" 29ed96be99SZachary Turner #include "llvm/Support/Threading.h" 304ad5def9SAdrian McCarthy #include "llvm/Support/raw_ostream.h" 314ad5def9SAdrian McCarthy 325146a9eaSAaron Smith #ifndef STATUS_WX86_BREAKPOINT 335146a9eaSAaron Smith #define STATUS_WX86_BREAKPOINT 0x4000001FL // For WOW64 345146a9eaSAaron Smith #endif 355146a9eaSAaron Smith 364ad5def9SAdrian McCarthy using namespace lldb; 374ad5def9SAdrian McCarthy using namespace lldb_private; 384ad5def9SAdrian McCarthy 394ad5def9SAdrian McCarthy DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate) 404ad5def9SAdrian McCarthy : m_debug_delegate(debug_delegate), m_pid_to_detach(0), 414ad5def9SAdrian McCarthy m_is_shutting_down(false) { 424ad5def9SAdrian McCarthy m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); 434ad5def9SAdrian McCarthy } 444ad5def9SAdrian McCarthy 454ad5def9SAdrian McCarthy DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); } 464ad5def9SAdrian McCarthy 4797206d57SZachary Turner Status DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) { 486730df47SPavel Labath Log *log = GetLog(WindowsLog::Process); 49a385d2c1SPavel Labath LLDB_LOG(log, "launching '{0}'", launch_info.GetExecutableFile().GetPath()); 504ad5def9SAdrian McCarthy 51631b5f7dSStella Stamenova Status result; 52*d0810779SPavel Labath llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread( 53*d0810779SPavel Labath "lldb.plugin.process-windows.secondary[?]", 54*d0810779SPavel Labath [this, launch_info] { return DebuggerThreadLaunchRoutine(launch_info); }); 5564ec505dSJonas Devlieghere if (!secondary_thread) { 5664ec505dSJonas Devlieghere result = Status(secondary_thread.takeError()); 57631b5f7dSStella Stamenova LLDB_LOG(log, "couldn't launch debugger thread. {0}", result); 58631b5f7dSStella Stamenova } 594ad5def9SAdrian McCarthy 60631b5f7dSStella Stamenova return result; 614ad5def9SAdrian McCarthy } 624ad5def9SAdrian McCarthy 6397206d57SZachary Turner Status DebuggerThread::DebugAttach(lldb::pid_t pid, 644ad5def9SAdrian McCarthy const ProcessAttachInfo &attach_info) { 656730df47SPavel Labath Log *log = GetLog(WindowsLog::Process); 66a385d2c1SPavel Labath LLDB_LOG(log, "attaching to '{0}'", pid); 674ad5def9SAdrian McCarthy 68631b5f7dSStella Stamenova Status result; 69*d0810779SPavel Labath llvm::Expected<HostThread> secondary_thread = ThreadLauncher::LaunchThread( 70*d0810779SPavel Labath "lldb.plugin.process-windows.secondary[?]", [this, pid, attach_info] { 71*d0810779SPavel Labath return DebuggerThreadAttachRoutine(pid, attach_info); 72*d0810779SPavel Labath }); 7364ec505dSJonas Devlieghere if (!secondary_thread) { 7464ec505dSJonas Devlieghere result = Status(secondary_thread.takeError()); 75631b5f7dSStella Stamenova LLDB_LOG(log, "couldn't attach to process '{0}'. {1}", pid, result); 76631b5f7dSStella Stamenova } 774ad5def9SAdrian McCarthy 78631b5f7dSStella Stamenova return result; 794ad5def9SAdrian McCarthy } 804ad5def9SAdrian McCarthy 814ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine( 824ad5def9SAdrian McCarthy const ProcessLaunchInfo &launch_info) { 834ad5def9SAdrian McCarthy // Grab a shared_ptr reference to this so that we know it won't get deleted 8405097246SAdrian Prantl // until after the thread routine has exited. 854ad5def9SAdrian McCarthy std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 864ad5def9SAdrian McCarthy 876730df47SPavel Labath Log *log = GetLog(WindowsLog::Process); 88a385d2c1SPavel Labath LLDB_LOG(log, "preparing to launch '{0}' on background thread.", 89a385d2c1SPavel Labath launch_info.GetExecutableFile().GetPath()); 904ad5def9SAdrian McCarthy 9197206d57SZachary Turner Status error; 924ad5def9SAdrian McCarthy ProcessLauncherWindows launcher; 934ad5def9SAdrian McCarthy HostProcess process(launcher.LaunchProcess(launch_info, error)); 944ad5def9SAdrian McCarthy // If we couldn't create the process, notify waiters immediately. Otherwise 9505097246SAdrian Prantl // enter the debug loop and wait until we get the create process debug 9605097246SAdrian Prantl // notification. Note that if the process was created successfully, we can 9705097246SAdrian Prantl // throw away the process handle we got from CreateProcess because Windows 9805097246SAdrian Prantl // will give us another (potentially more useful?) handle when it sends us 9905097246SAdrian Prantl // the CREATE_PROCESS_DEBUG_EVENT. 1004ad5def9SAdrian McCarthy if (error.Success()) 1014ad5def9SAdrian McCarthy DebugLoop(); 1024ad5def9SAdrian McCarthy else 1034ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, 0); 1044ad5def9SAdrian McCarthy 10585200645SKonrad Kleine return {}; 1064ad5def9SAdrian McCarthy } 1074ad5def9SAdrian McCarthy 1084ad5def9SAdrian McCarthy lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine( 1094ad5def9SAdrian McCarthy lldb::pid_t pid, const ProcessAttachInfo &attach_info) { 1104ad5def9SAdrian McCarthy // Grab a shared_ptr reference to this so that we know it won't get deleted 11105097246SAdrian Prantl // until after the thread routine has exited. 1124ad5def9SAdrian McCarthy std::shared_ptr<DebuggerThread> this_ref(shared_from_this()); 1134ad5def9SAdrian McCarthy 1146730df47SPavel Labath Log *log = GetLog(WindowsLog::Process); 115a385d2c1SPavel Labath LLDB_LOG(log, "preparing to attach to process '{0}' on background thread.", 1164ad5def9SAdrian McCarthy pid); 1174ad5def9SAdrian McCarthy 1184ad5def9SAdrian McCarthy if (!DebugActiveProcess((DWORD)pid)) { 11997206d57SZachary Turner Status error(::GetLastError(), eErrorTypeWin32); 1204ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, 0); 12185200645SKonrad Kleine return {}; 1224ad5def9SAdrian McCarthy } 1234ad5def9SAdrian McCarthy 12405097246SAdrian Prantl // The attach was successful, enter the debug loop. From here on out, this 12505097246SAdrian Prantl // is no different than a create process operation, so all the same comments 12605097246SAdrian Prantl // in DebugLaunch should apply from this point out. 1274ad5def9SAdrian McCarthy DebugLoop(); 1284ad5def9SAdrian McCarthy 12985200645SKonrad Kleine return {}; 1304ad5def9SAdrian McCarthy } 1314ad5def9SAdrian McCarthy 13297206d57SZachary Turner Status DebuggerThread::StopDebugging(bool terminate) { 13397206d57SZachary Turner Status error; 1344ad5def9SAdrian McCarthy 1354ad5def9SAdrian McCarthy lldb::pid_t pid = m_process.GetProcessId(); 1364ad5def9SAdrian McCarthy 1376730df47SPavel Labath Log *log = GetLog(WindowsLog::Process); 138a385d2c1SPavel Labath LLDB_LOG(log, "terminate = {0}, inferior={1}.", terminate, pid); 1394ad5def9SAdrian McCarthy 1404ad5def9SAdrian McCarthy // Set m_is_shutting_down to true if it was false. Return if it was already 1414ad5def9SAdrian McCarthy // true. 1424ad5def9SAdrian McCarthy bool expected = false; 1434ad5def9SAdrian McCarthy if (!m_is_shutting_down.compare_exchange_strong(expected, true)) 1444ad5def9SAdrian McCarthy return error; 1454ad5def9SAdrian McCarthy 1464ad5def9SAdrian McCarthy // Make a copy of the process, since the termination sequence will reset 1474ad5def9SAdrian McCarthy // DebuggerThread's internal copy and it needs to remain open for the Wait 1484ad5def9SAdrian McCarthy // operation. 1494ad5def9SAdrian McCarthy HostProcess process_copy = m_process; 1504ad5def9SAdrian McCarthy lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle(); 1514ad5def9SAdrian McCarthy 1524ad5def9SAdrian McCarthy if (terminate) { 1539d6fabf9SStella Stamenova if (handle != nullptr && handle != LLDB_INVALID_PROCESS) { 1544ad5def9SAdrian McCarthy // Initiate the termination before continuing the exception, so that the 15505097246SAdrian Prantl // next debug event we get is the exit process event, and not some other 15605097246SAdrian Prantl // event. 1574ad5def9SAdrian McCarthy BOOL terminate_suceeded = TerminateProcess(handle, 0); 158a385d2c1SPavel Labath LLDB_LOG(log, 159a385d2c1SPavel Labath "calling TerminateProcess({0}, 0) (inferior={1}), success={2}", 160a385d2c1SPavel Labath handle, pid, terminate_suceeded); 1619d6fabf9SStella Stamenova } else { 1629d6fabf9SStella Stamenova LLDB_LOG(log, 163e3037904SAaron Smith "NOT calling TerminateProcess because the inferior is not valid " 164e3037904SAaron Smith "({0}, 0) (inferior={1})", 1659d6fabf9SStella Stamenova handle, pid); 1669d6fabf9SStella Stamenova } 1674ad5def9SAdrian McCarthy } 1684ad5def9SAdrian McCarthy 1694ad5def9SAdrian McCarthy // If we're stuck waiting for an exception to continue (e.g. the user is at a 17005097246SAdrian Prantl // breakpoint messing around in the debugger), continue it now. But only 17105097246SAdrian Prantl // AFTER calling TerminateProcess to make sure that the very next call to 17205097246SAdrian Prantl // WaitForDebugEvent is an exit process event. 1734ad5def9SAdrian McCarthy if (m_active_exception.get()) { 174a385d2c1SPavel Labath LLDB_LOG(log, "masking active exception"); 1754ad5def9SAdrian McCarthy ContinueAsyncException(ExceptionResult::MaskException); 1764ad5def9SAdrian McCarthy } 1774ad5def9SAdrian McCarthy 1784ad5def9SAdrian McCarthy if (!terminate) { 1794ad5def9SAdrian McCarthy // Indicate that we want to detach. 1804ad5def9SAdrian McCarthy m_pid_to_detach = GetProcess().GetProcessId(); 1814ad5def9SAdrian McCarthy 1824ad5def9SAdrian McCarthy // Force a fresh break so that the detach can happen from the debugger 1834ad5def9SAdrian McCarthy // thread. 1844ad5def9SAdrian McCarthy if (!::DebugBreakProcess( 1854ad5def9SAdrian McCarthy GetProcess().GetNativeProcess().GetSystemHandle())) { 1864ad5def9SAdrian McCarthy error.SetError(::GetLastError(), eErrorTypeWin32); 1874ad5def9SAdrian McCarthy } 1884ad5def9SAdrian McCarthy } 1894ad5def9SAdrian McCarthy 190a385d2c1SPavel Labath LLDB_LOG(log, "waiting for detach from process {0} to complete.", pid); 1914ad5def9SAdrian McCarthy 1924ad5def9SAdrian McCarthy DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000); 1934ad5def9SAdrian McCarthy if (wait_result != WAIT_OBJECT_0) { 1944ad5def9SAdrian McCarthy error.SetError(GetLastError(), eErrorTypeWin32); 195a385d2c1SPavel Labath LLDB_LOG(log, "error: WaitForSingleObject({0}, 5000) returned {1}", 1964ad5def9SAdrian McCarthy m_debugging_ended_event, wait_result); 197a385d2c1SPavel Labath } else 198a385d2c1SPavel Labath LLDB_LOG(log, "detach from process {0} completed successfully.", pid); 1994ad5def9SAdrian McCarthy 2004ad5def9SAdrian McCarthy if (!error.Success()) { 201a385d2c1SPavel Labath LLDB_LOG(log, "encountered an error while trying to stop process {0}. {1}", 202a385d2c1SPavel Labath pid, error); 2034ad5def9SAdrian McCarthy } 2044ad5def9SAdrian McCarthy return error; 2054ad5def9SAdrian McCarthy } 2064ad5def9SAdrian McCarthy 2074ad5def9SAdrian McCarthy void DebuggerThread::ContinueAsyncException(ExceptionResult result) { 2084ad5def9SAdrian McCarthy if (!m_active_exception.get()) 2094ad5def9SAdrian McCarthy return; 2104ad5def9SAdrian McCarthy 2116730df47SPavel Labath Log *log = GetLog(WindowsLog::Process | WindowsLog::Exception); 212a385d2c1SPavel Labath LLDB_LOG(log, "broadcasting for inferior process {0}.", 2134ad5def9SAdrian McCarthy m_process.GetProcessId()); 2144ad5def9SAdrian McCarthy 2154ad5def9SAdrian McCarthy m_active_exception.reset(); 2164ad5def9SAdrian McCarthy m_exception_pred.SetValue(result, eBroadcastAlways); 2174ad5def9SAdrian McCarthy } 2184ad5def9SAdrian McCarthy 2194ad5def9SAdrian McCarthy void DebuggerThread::FreeProcessHandles() { 2204ad5def9SAdrian McCarthy m_process = HostProcess(); 2214ad5def9SAdrian McCarthy m_main_thread = HostThread(); 2224ad5def9SAdrian McCarthy if (m_image_file) { 2234ad5def9SAdrian McCarthy ::CloseHandle(m_image_file); 2244ad5def9SAdrian McCarthy m_image_file = nullptr; 2254ad5def9SAdrian McCarthy } 2264ad5def9SAdrian McCarthy } 2274ad5def9SAdrian McCarthy 2284ad5def9SAdrian McCarthy void DebuggerThread::DebugLoop() { 2296730df47SPavel Labath Log *log = GetLog(WindowsLog::Event); 2304ad5def9SAdrian McCarthy DEBUG_EVENT dbe = {}; 2314ad5def9SAdrian McCarthy bool should_debug = true; 232a385d2c1SPavel Labath LLDB_LOGV(log, "Entering WaitForDebugEvent loop"); 2334ad5def9SAdrian McCarthy while (should_debug) { 234a385d2c1SPavel Labath LLDB_LOGV(log, "Calling WaitForDebugEvent"); 2354ad5def9SAdrian McCarthy BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE); 2364ad5def9SAdrian McCarthy if (wait_result) { 2374ad5def9SAdrian McCarthy DWORD continue_status = DBG_CONTINUE; 2384ad5def9SAdrian McCarthy switch (dbe.dwDebugEventCode) { 239e3037904SAaron Smith default: 240e3037904SAaron Smith llvm_unreachable("Unhandle debug event code!"); 2414ad5def9SAdrian McCarthy case EXCEPTION_DEBUG_EVENT: { 2424ad5def9SAdrian McCarthy ExceptionResult status = 2434ad5def9SAdrian McCarthy HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); 2444ad5def9SAdrian McCarthy 2454ad5def9SAdrian McCarthy if (status == ExceptionResult::MaskException) 2464ad5def9SAdrian McCarthy continue_status = DBG_CONTINUE; 2474ad5def9SAdrian McCarthy else if (status == ExceptionResult::SendToApplication) 2484ad5def9SAdrian McCarthy continue_status = DBG_EXCEPTION_NOT_HANDLED; 2494ad5def9SAdrian McCarthy 2504ad5def9SAdrian McCarthy break; 2514ad5def9SAdrian McCarthy } 2524ad5def9SAdrian McCarthy case CREATE_THREAD_DEBUG_EVENT: 2534ad5def9SAdrian McCarthy continue_status = 2544ad5def9SAdrian McCarthy HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId); 2554ad5def9SAdrian McCarthy break; 2564ad5def9SAdrian McCarthy case CREATE_PROCESS_DEBUG_EVENT: 2574ad5def9SAdrian McCarthy continue_status = 2584ad5def9SAdrian McCarthy HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId); 2594ad5def9SAdrian McCarthy break; 2604ad5def9SAdrian McCarthy case EXIT_THREAD_DEBUG_EVENT: 2614ad5def9SAdrian McCarthy continue_status = 2624ad5def9SAdrian McCarthy HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId); 2634ad5def9SAdrian McCarthy break; 2644ad5def9SAdrian McCarthy case EXIT_PROCESS_DEBUG_EVENT: 2654ad5def9SAdrian McCarthy continue_status = 2664ad5def9SAdrian McCarthy HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId); 2674ad5def9SAdrian McCarthy should_debug = false; 2684ad5def9SAdrian McCarthy break; 2694ad5def9SAdrian McCarthy case LOAD_DLL_DEBUG_EVENT: 2704ad5def9SAdrian McCarthy continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId); 2714ad5def9SAdrian McCarthy break; 2724ad5def9SAdrian McCarthy case UNLOAD_DLL_DEBUG_EVENT: 2734ad5def9SAdrian McCarthy continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId); 2744ad5def9SAdrian McCarthy break; 2754ad5def9SAdrian McCarthy case OUTPUT_DEBUG_STRING_EVENT: 2764ad5def9SAdrian McCarthy continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId); 2774ad5def9SAdrian McCarthy break; 2784ad5def9SAdrian McCarthy case RIP_EVENT: 2794ad5def9SAdrian McCarthy continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId); 2804ad5def9SAdrian McCarthy if (dbe.u.RipInfo.dwType == SLE_ERROR) 2814ad5def9SAdrian McCarthy should_debug = false; 2824ad5def9SAdrian McCarthy break; 2834ad5def9SAdrian McCarthy } 2844ad5def9SAdrian McCarthy 285a385d2c1SPavel Labath LLDB_LOGV(log, "calling ContinueDebugEvent({0}, {1}, {2}) on thread {3}.", 2864ad5def9SAdrian McCarthy dbe.dwProcessId, dbe.dwThreadId, continue_status, 2874ad5def9SAdrian McCarthy ::GetCurrentThreadId()); 2884ad5def9SAdrian McCarthy 2894ad5def9SAdrian McCarthy ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status); 2904ad5def9SAdrian McCarthy 2914ad5def9SAdrian McCarthy if (m_detached) { 2924ad5def9SAdrian McCarthy should_debug = false; 2934ad5def9SAdrian McCarthy } 2944ad5def9SAdrian McCarthy } else { 295a385d2c1SPavel Labath LLDB_LOG(log, "returned FALSE from WaitForDebugEvent. Error = {0}", 2964ad5def9SAdrian McCarthy ::GetLastError()); 2974ad5def9SAdrian McCarthy 2984ad5def9SAdrian McCarthy should_debug = false; 2994ad5def9SAdrian McCarthy } 3004ad5def9SAdrian McCarthy } 3014ad5def9SAdrian McCarthy FreeProcessHandles(); 3024ad5def9SAdrian McCarthy 303a385d2c1SPavel Labath LLDB_LOG(log, "WaitForDebugEvent loop completed, exiting."); 304e3037904SAaron Smith ::SetEvent(m_debugging_ended_event); 3054ad5def9SAdrian McCarthy } 3064ad5def9SAdrian McCarthy 3074ad5def9SAdrian McCarthy ExceptionResult 3084ad5def9SAdrian McCarthy DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, 3094ad5def9SAdrian McCarthy DWORD thread_id) { 3106730df47SPavel Labath Log *log = GetLog(WindowsLog::Event | WindowsLog::Exception); 3114ad5def9SAdrian McCarthy if (m_is_shutting_down) { 3124ad5def9SAdrian McCarthy // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic 3134ad5def9SAdrian McCarthy // exception that 3144ad5def9SAdrian McCarthy // we use simply to wake up the DebuggerThread so that we can close out the 3154ad5def9SAdrian McCarthy // debug loop. 3164ad5def9SAdrian McCarthy if (m_pid_to_detach != 0 && 3175146a9eaSAaron Smith (info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT || 3185146a9eaSAaron Smith info.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT)) { 319a385d2c1SPavel Labath LLDB_LOG(log, "Breakpoint exception is cue to detach from process {0:x}", 3204ad5def9SAdrian McCarthy m_pid_to_detach.load()); 3214ad5def9SAdrian McCarthy ::DebugActiveProcessStop(m_pid_to_detach); 3224ad5def9SAdrian McCarthy m_detached = true; 3234ad5def9SAdrian McCarthy } 3244ad5def9SAdrian McCarthy 3254ad5def9SAdrian McCarthy // Don't perform any blocking operations while we're shutting down. That 32605097246SAdrian Prantl // will cause TerminateProcess -> WaitForSingleObject to time out. 3274ad5def9SAdrian McCarthy return ExceptionResult::SendToApplication; 3284ad5def9SAdrian McCarthy } 3294ad5def9SAdrian McCarthy 3304ad5def9SAdrian McCarthy bool first_chance = (info.dwFirstChance != 0); 3314ad5def9SAdrian McCarthy 3324ad5def9SAdrian McCarthy m_active_exception.reset( 3334ad5def9SAdrian McCarthy new ExceptionRecord(info.ExceptionRecord, thread_id)); 334a385d2c1SPavel Labath LLDB_LOG(log, "encountered {0} chance exception {1:x} on thread {2:x}", 3354ad5def9SAdrian McCarthy first_chance ? "first" : "second", 3364ad5def9SAdrian McCarthy info.ExceptionRecord.ExceptionCode, thread_id); 3374ad5def9SAdrian McCarthy 3384ad5def9SAdrian McCarthy ExceptionResult result = 3394ad5def9SAdrian McCarthy m_debug_delegate->OnDebugException(first_chance, *m_active_exception); 3404ad5def9SAdrian McCarthy m_exception_pred.SetValue(result, eBroadcastNever); 3414ad5def9SAdrian McCarthy 342a385d2c1SPavel Labath LLDB_LOG(log, "waiting for ExceptionPred != BreakInDebugger"); 3434b130331SPavel Labath result = *m_exception_pred.WaitForValueNotEqualTo( 3444b130331SPavel Labath ExceptionResult::BreakInDebugger); 3454ad5def9SAdrian McCarthy 346a385d2c1SPavel Labath LLDB_LOG(log, "got ExceptionPred = {0}", (int)m_exception_pred.GetValue()); 3474ad5def9SAdrian McCarthy return result; 3484ad5def9SAdrian McCarthy } 3494ad5def9SAdrian McCarthy 3504ad5def9SAdrian McCarthy DWORD 3514ad5def9SAdrian McCarthy DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, 3524ad5def9SAdrian McCarthy DWORD thread_id) { 3536730df47SPavel Labath Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread); 354e3037904SAaron Smith LLDB_LOG(log, "Thread {0} spawned in process {1}", thread_id, 355a385d2c1SPavel Labath m_process.GetProcessId()); 3564ad5def9SAdrian McCarthy HostThread thread(info.hThread); 3574ad5def9SAdrian McCarthy thread.GetNativeThread().SetOwnsHandle(false); 3584ad5def9SAdrian McCarthy m_debug_delegate->OnCreateThread(thread); 3594ad5def9SAdrian McCarthy return DBG_CONTINUE; 3604ad5def9SAdrian McCarthy } 3614ad5def9SAdrian McCarthy 3624ad5def9SAdrian McCarthy DWORD 3634ad5def9SAdrian McCarthy DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, 3644ad5def9SAdrian McCarthy DWORD thread_id) { 3656730df47SPavel Labath Log *log = GetLog(WindowsLog::Event | WindowsLog::Process); 3664ad5def9SAdrian McCarthy uint32_t process_id = ::GetProcessId(info.hProcess); 3674ad5def9SAdrian McCarthy 368a385d2c1SPavel Labath LLDB_LOG(log, "process {0} spawned", process_id); 3694ad5def9SAdrian McCarthy 3704ad5def9SAdrian McCarthy std::string thread_name; 3714ad5def9SAdrian McCarthy llvm::raw_string_ostream name_stream(thread_name); 37264ec505dSJonas Devlieghere name_stream << "lldb.plugin.process-windows.secondary[" << process_id << "]"; 3734ad5def9SAdrian McCarthy name_stream.flush(); 374ed96be99SZachary Turner llvm::set_thread_name(thread_name); 3754ad5def9SAdrian McCarthy 3764ad5def9SAdrian McCarthy // info.hProcess and info.hThread are closed automatically by Windows when 3774ad5def9SAdrian McCarthy // EXIT_PROCESS_DEBUG_EVENT is received. 3784ad5def9SAdrian McCarthy m_process = HostProcess(info.hProcess); 3794ad5def9SAdrian McCarthy ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false); 3804ad5def9SAdrian McCarthy m_main_thread = HostThread(info.hThread); 3814ad5def9SAdrian McCarthy m_main_thread.GetNativeThread().SetOwnsHandle(false); 3824ad5def9SAdrian McCarthy m_image_file = info.hFile; 3834ad5def9SAdrian McCarthy 3844ad5def9SAdrian McCarthy lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage); 3854ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerConnected(load_addr); 3864ad5def9SAdrian McCarthy 3874ad5def9SAdrian McCarthy return DBG_CONTINUE; 3884ad5def9SAdrian McCarthy } 3894ad5def9SAdrian McCarthy 3904ad5def9SAdrian McCarthy DWORD 3914ad5def9SAdrian McCarthy DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, 3924ad5def9SAdrian McCarthy DWORD thread_id) { 3936730df47SPavel Labath Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread); 394a385d2c1SPavel Labath LLDB_LOG(log, "Thread {0} exited with code {1} in process {2}", thread_id, 395a385d2c1SPavel Labath info.dwExitCode, m_process.GetProcessId()); 3964ad5def9SAdrian McCarthy m_debug_delegate->OnExitThread(thread_id, info.dwExitCode); 3974ad5def9SAdrian McCarthy return DBG_CONTINUE; 3984ad5def9SAdrian McCarthy } 3994ad5def9SAdrian McCarthy 4004ad5def9SAdrian McCarthy DWORD 4014ad5def9SAdrian McCarthy DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, 4024ad5def9SAdrian McCarthy DWORD thread_id) { 4036730df47SPavel Labath Log *log = GetLog(WindowsLog::Event | WindowsLog::Thread); 404a385d2c1SPavel Labath LLDB_LOG(log, "process {0} exited with code {1}", m_process.GetProcessId(), 405a385d2c1SPavel Labath info.dwExitCode); 4064ad5def9SAdrian McCarthy 4074ad5def9SAdrian McCarthy m_debug_delegate->OnExitProcess(info.dwExitCode); 4084ad5def9SAdrian McCarthy 4094ad5def9SAdrian McCarthy return DBG_CONTINUE; 4104ad5def9SAdrian McCarthy } 4114ad5def9SAdrian McCarthy 4124ad5def9SAdrian McCarthy DWORD 4134ad5def9SAdrian McCarthy DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, 4144ad5def9SAdrian McCarthy DWORD thread_id) { 4156730df47SPavel Labath Log *log = GetLog(WindowsLog::Event); 4164ad5def9SAdrian McCarthy if (info.hFile == nullptr) { 4174ad5def9SAdrian McCarthy // Not sure what this is, so just ignore it. 418a385d2c1SPavel Labath LLDB_LOG(log, "Warning: Inferior {0} has a NULL file handle, returning...", 4194ad5def9SAdrian McCarthy m_process.GetProcessId()); 4204ad5def9SAdrian McCarthy return DBG_CONTINUE; 4214ad5def9SAdrian McCarthy } 4224ad5def9SAdrian McCarthy 4234ad5def9SAdrian McCarthy std::vector<wchar_t> buffer(1); 4244ad5def9SAdrian McCarthy DWORD required_size = 4254ad5def9SAdrian McCarthy GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS); 4264ad5def9SAdrian McCarthy if (required_size > 0) { 4274ad5def9SAdrian McCarthy buffer.resize(required_size + 1); 4284ad5def9SAdrian McCarthy required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0], 4294ad5def9SAdrian McCarthy required_size, VOLUME_NAME_DOS); 4304ad5def9SAdrian McCarthy std::string path_str_utf8; 4314ad5def9SAdrian McCarthy llvm::convertWideToUTF8(buffer.data(), path_str_utf8); 4324ad5def9SAdrian McCarthy llvm::StringRef path_str = path_str_utf8; 4334ad5def9SAdrian McCarthy const char *path = path_str.data(); 4344ad5def9SAdrian McCarthy if (path_str.startswith("\\\\?\\")) 4354ad5def9SAdrian McCarthy path += 4; 4364ad5def9SAdrian McCarthy 43754bb3161SAleksandr Urakov FileSpec file_spec(path); 4384ad5def9SAdrian McCarthy ModuleSpec module_spec(file_spec); 4394ad5def9SAdrian McCarthy lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll); 4404ad5def9SAdrian McCarthy 441a385d2c1SPavel Labath LLDB_LOG(log, "Inferior {0} - DLL '{1}' loaded at address {2:x}...", 4424ad5def9SAdrian McCarthy m_process.GetProcessId(), path, info.lpBaseOfDll); 4434ad5def9SAdrian McCarthy 4444ad5def9SAdrian McCarthy m_debug_delegate->OnLoadDll(module_spec, load_addr); 4454ad5def9SAdrian McCarthy } else { 446a385d2c1SPavel Labath LLDB_LOG( 447a385d2c1SPavel Labath log, 448a385d2c1SPavel Labath "Inferior {0} - Error {1} occurred calling GetFinalPathNameByHandle", 4494ad5def9SAdrian McCarthy m_process.GetProcessId(), ::GetLastError()); 4504ad5def9SAdrian McCarthy } 4514ad5def9SAdrian McCarthy // Windows does not automatically close info.hFile, so we need to do it. 4524ad5def9SAdrian McCarthy ::CloseHandle(info.hFile); 4534ad5def9SAdrian McCarthy return DBG_CONTINUE; 4544ad5def9SAdrian McCarthy } 4554ad5def9SAdrian McCarthy 4564ad5def9SAdrian McCarthy DWORD 4574ad5def9SAdrian McCarthy DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, 4584ad5def9SAdrian McCarthy DWORD thread_id) { 4596730df47SPavel Labath Log *log = GetLog(WindowsLog::Event); 460a385d2c1SPavel Labath LLDB_LOG(log, "process {0} unloading DLL at addr {1:x}.", 4614ad5def9SAdrian McCarthy m_process.GetProcessId(), info.lpBaseOfDll); 4624ad5def9SAdrian McCarthy 4634ad5def9SAdrian McCarthy m_debug_delegate->OnUnloadDll( 4644ad5def9SAdrian McCarthy reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll)); 4654ad5def9SAdrian McCarthy return DBG_CONTINUE; 4664ad5def9SAdrian McCarthy } 4674ad5def9SAdrian McCarthy 4684ad5def9SAdrian McCarthy DWORD 4694ad5def9SAdrian McCarthy DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, 4704ad5def9SAdrian McCarthy DWORD thread_id) { 4714ad5def9SAdrian McCarthy return DBG_CONTINUE; 4724ad5def9SAdrian McCarthy } 4734ad5def9SAdrian McCarthy 4744ad5def9SAdrian McCarthy DWORD 4754ad5def9SAdrian McCarthy DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) { 4766730df47SPavel Labath Log *log = GetLog(WindowsLog::Event); 477a385d2c1SPavel Labath LLDB_LOG(log, "encountered error {0} (type={1}) in process {2} thread {3}", 4784ad5def9SAdrian McCarthy info.dwError, info.dwType, m_process.GetProcessId(), thread_id); 4794ad5def9SAdrian McCarthy 48097206d57SZachary Turner Status error(info.dwError, eErrorTypeWin32); 4814ad5def9SAdrian McCarthy m_debug_delegate->OnDebuggerError(error, info.dwType); 4824ad5def9SAdrian McCarthy 4834ad5def9SAdrian McCarthy return DBG_CONTINUE; 4844ad5def9SAdrian McCarthy } 485