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