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