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