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