blob: 4dcd7894e4d86cbd7add78c6f74b6942eb0788c3 [file] [log] [blame]
Kate Stoneb9c1b512016-09-06 20:57:50 +00001//===-- DebuggerThread.DebuggerThread --------------------------------------*-
2//C++ -*-===//
Zachary Turner02862bc2014-11-07 23:44:13 +00003//
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"
Zachary Turnerdcd80372014-11-11 00:00:14 +000012#include "ExceptionRecord.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000013#include "IDebugDelegate.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000014
15#include "lldb/Core/Error.h"
16#include "lldb/Core/Log.h"
Zachary Turnera32d2ce2014-11-12 19:31:56 +000017#include "lldb/Core/ModuleSpec.h"
18#include "lldb/Host/FileSpec.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000019#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"
Zachary Turnerc62733b2015-05-20 18:31:17 +000025#include "lldb/Target/Process.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000026#include "lldb/Target/ProcessLaunchInfo.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000027
Adrian McCarthy18a9135d2015-10-28 18:21:45 +000028#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"
Zachary Turner610e5292015-05-07 21:39:33 +000029
Zachary Turnera32d2ce2014-11-12 19:31:56 +000030#include "llvm/ADT/STLExtras.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000031#include "llvm/Support/ConvertUTF.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000032#include "llvm/Support/raw_ostream.h"
33
34using namespace lldb;
35using namespace lldb_private;
36
Kate Stoneb9c1b512016-09-06 20:57:50 +000037namespace {
38struct 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;
Zachary Turner02862bc2014-11-07 23:44:13 +000044};
Zachary Turnerc62733b2015-05-20 18:31:17 +000045
Kate Stoneb9c1b512016-09-06 20:57:50 +000046struct 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;
Zachary Turnerc62733b2015-05-20 18:31:17 +000053};
Zachary Turner02862bc2014-11-07 23:44:13 +000054}
55
56DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
Kate Stoneb9c1b512016-09-06 20:57:50 +000057 : m_debug_delegate(debug_delegate), m_image_file(nullptr),
58 m_debugging_ended_event(nullptr), m_is_shutting_down(false),
59 m_pid_to_detach(0), m_detached(false) {
60 m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
Zachary Turner02862bc2014-11-07 23:44:13 +000061}
62
Kate Stoneb9c1b512016-09-06 20:57:50 +000063DebuggerThread::~DebuggerThread() { ::CloseHandle(m_debugging_ended_event); }
64
65Error DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info) {
66 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
67 "DebuggerThread::DebugLaunch launching '%s'",
68 launch_info.GetExecutableFile().GetPath().c_str());
69
70 Error error;
71 DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
72 HostThread slave_thread(ThreadLauncher::LaunchThread(
73 "lldb.plugin.process-windows.slave[?]", DebuggerThreadLaunchRoutine,
74 context, &error));
75
76 if (!error.Success()) {
77 WINERR_IFALL(WINDOWS_LOG_PROCESS,
78 "DebugLaunch couldn't launch debugger thread. %s",
79 error.AsCString());
80 }
81
82 return error;
Zachary Turner02862bc2014-11-07 23:44:13 +000083}
84
Kate Stoneb9c1b512016-09-06 20:57:50 +000085Error DebuggerThread::DebugAttach(lldb::pid_t pid,
86 const ProcessAttachInfo &attach_info) {
87 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
88 "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid);
Zachary Turner02862bc2014-11-07 23:44:13 +000089
Kate Stoneb9c1b512016-09-06 20:57:50 +000090 Error error;
91 DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info);
92 HostThread slave_thread(ThreadLauncher::LaunchThread(
93 "lldb.plugin.process-windows.slave[?]", DebuggerThreadAttachRoutine,
94 context, &error));
Zachary Turner610e5292015-05-07 21:39:33 +000095
Kate Stoneb9c1b512016-09-06 20:57:50 +000096 if (!error.Success()) {
97 WINERR_IFALL(WINDOWS_LOG_PROCESS,
98 "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid,
99 error.AsCString());
100 }
Zachary Turner02862bc2014-11-07 23:44:13 +0000101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 return error;
Zachary Turner02862bc2014-11-07 23:44:13 +0000103}
104
Kate Stoneb9c1b512016-09-06 20:57:50 +0000105lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(void *data) {
106 DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
107 lldb::thread_result_t result =
108 context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info);
109 delete context;
110 return result;
Zachary Turnerc62733b2015-05-20 18:31:17 +0000111}
112
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(void *data) {
114 DebugAttachContext *context = static_cast<DebugAttachContext *>(data);
115 lldb::thread_result_t result = context->m_thread->DebuggerThreadAttachRoutine(
116 context->m_pid, context->m_attach_info);
117 delete context;
118 return result;
Zachary Turner02862bc2014-11-07 23:44:13 +0000119}
120
Kate Stoneb9c1b512016-09-06 20:57:50 +0000121lldb::thread_result_t DebuggerThread::DebuggerThreadLaunchRoutine(
122 const ProcessLaunchInfo &launch_info) {
123 // Grab a shared_ptr reference to this so that we know it won't get deleted
124 // until after the
125 // thread routine has exited.
126 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
Zachary Turnerc62733b2015-05-20 18:31:17 +0000127
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
129 "DebuggerThread preparing to launch '%s' on background thread.",
130 launch_info.GetExecutableFile().GetPath().c_str());
Zachary Turner02862bc2014-11-07 23:44:13 +0000131
Kate Stoneb9c1b512016-09-06 20:57:50 +0000132 Error error;
133 ProcessLauncherWindows launcher;
134 HostProcess process(launcher.LaunchProcess(launch_info, error));
135 // If we couldn't create the process, notify waiters immediately. Otherwise
136 // enter the debug
137 // loop and wait until we get the create process debug notification. Note
138 // that if the process
139 // was created successfully, we can throw away the process handle we got from
140 // CreateProcess
141 // because Windows will give us another (potentially more useful?) handle when
142 // it sends us the
143 // CREATE_PROCESS_DEBUG_EVENT.
144 if (error.Success())
Zachary Turnerc62733b2015-05-20 18:31:17 +0000145 DebugLoop();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 else
147 m_debug_delegate->OnDebuggerError(error, 0);
Zachary Turnerc62733b2015-05-20 18:31:17 +0000148
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 return 0;
150}
151
152lldb::thread_result_t DebuggerThread::DebuggerThreadAttachRoutine(
153 lldb::pid_t pid, const ProcessAttachInfo &attach_info) {
154 // Grab a shared_ptr reference to this so that we know it won't get deleted
155 // until after the
156 // thread routine has exited.
157 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
158
159 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to "
160 "process '%u' on background thread.",
161 (DWORD)pid);
162
163 if (!DebugActiveProcess((DWORD)pid)) {
164 Error error(::GetLastError(), eErrorTypeWin32);
165 m_debug_delegate->OnDebuggerError(error, 0);
Zachary Turnerc62733b2015-05-20 18:31:17 +0000166 return 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000167 }
168
169 // The attach was successful, enter the debug loop. From here on out, this is
170 // no different than
171 // a create process operation, so all the same comments in DebugLaunch should
172 // apply from this
173 // point out.
174 DebugLoop();
175
176 return 0;
Zachary Turnerc62733b2015-05-20 18:31:17 +0000177}
178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179Error DebuggerThread::StopDebugging(bool terminate) {
180 Error error;
Zachary Turnerc6a66532014-12-03 22:04:18 +0000181
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182 lldb::pid_t pid = m_process.GetProcessId();
Zachary Turner610e5292015-05-07 21:39:33 +0000183
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
185 "StopDebugging('%s') called (inferior=%I64u).",
186 (terminate ? "true" : "false"), pid);
Zachary Turner610e5292015-05-07 21:39:33 +0000187
Kate Stoneb9c1b512016-09-06 20:57:50 +0000188 // Set m_is_shutting_down to true if it was false. Return if it was already
189 // true.
190 bool expected = false;
191 if (!m_is_shutting_down.compare_exchange_strong(expected, true))
Zachary Turnerc6a66532014-12-03 22:04:18 +0000192 return error;
Zachary Turnerc6a66532014-12-03 22:04:18 +0000193
Kate Stoneb9c1b512016-09-06 20:57:50 +0000194 // Make a copy of the process, since the termination sequence will reset
195 // DebuggerThread's internal copy and it needs to remain open for the Wait
196 // operation.
197 HostProcess process_copy = m_process;
198 lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle();
Zachary Turnerc6a66532014-12-03 22:04:18 +0000199
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200 if (terminate) {
201 // Initiate the termination before continuing the exception, so that the
202 // next debug
203 // event we get is the exit process event, and not some other event.
204 BOOL terminate_suceeded = TerminateProcess(handle, 0);
205 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging called "
206 "TerminateProcess(0x%p, 0) "
207 "(inferior=%I64u), success='%s'",
208 handle, pid, (terminate_suceeded ? "true" : "false"));
209 }
Zachary Turner610e5292015-05-07 21:39:33 +0000210
Kate Stoneb9c1b512016-09-06 20:57:50 +0000211 // If we're stuck waiting for an exception to continue (e.g. the user is at a
212 // breakpoint
213 // messing around in the debugger), continue it now. But only AFTER calling
214 // TerminateProcess
215 // to make sure that the very next call to WaitForDebugEvent is an exit
216 // process event.
217 if (m_active_exception.get()) {
218 WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION,
219 "StopDebugging masking active exception");
Zachary Turnerc6a66532014-12-03 22:04:18 +0000220
Kate Stoneb9c1b512016-09-06 20:57:50 +0000221 ContinueAsyncException(ExceptionResult::MaskException);
222 }
223
224 if (!terminate) {
225 // Indicate that we want to detach.
226 m_pid_to_detach = GetProcess().GetProcessId();
227
228 // Force a fresh break so that the detach can happen from the debugger
229 // thread.
230 if (!::DebugBreakProcess(
231 GetProcess().GetNativeProcess().GetSystemHandle())) {
232 error.SetError(::GetLastError(), eErrorTypeWin32);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000233 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234 }
235
236 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
237 "StopDebugging waiting for detach from process %u to complete.",
238 pid);
239
240 DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000);
241 if (wait_result != WAIT_OBJECT_0) {
242 error.SetError(GetLastError(), eErrorTypeWin32);
243 WINERR_IFALL(WINDOWS_LOG_PROCESS,
244 "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u",
245 m_debugging_ended_event, wait_result);
246 } else {
247 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
248 "StopDebugging detach from process %u completed successfully.",
249 pid);
250 }
251
252 if (!error.Success()) {
253 WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging encountered an error "
254 "while trying to stop process %u. %s",
255 pid, error.AsCString());
256 }
257 return error;
Zachary Turnerdcd80372014-11-11 00:00:14 +0000258}
259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260void DebuggerThread::ContinueAsyncException(ExceptionResult result) {
261 if (!m_active_exception.get())
262 return;
Zachary Turnerdcd80372014-11-11 00:00:14 +0000263
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264 WINLOG_IFANY(
265 WINDOWS_LOG_PROCESS | WINDOWS_LOG_EXCEPTION,
266 "ContinueAsyncException called for inferior process %I64u, broadcasting.",
267 m_process.GetProcessId());
Zachary Turner6c3c0ed2015-10-02 22:47:04 +0000268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 m_active_exception.reset();
270 m_exception_pred.SetValue(result, eBroadcastAlways);
271}
Zachary Turner02862bc2014-11-07 23:44:13 +0000272
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273void DebuggerThread::FreeProcessHandles() {
274 m_process = HostProcess();
275 m_main_thread = HostThread();
276 if (m_image_file) {
277 ::CloseHandle(m_image_file);
278 m_image_file = nullptr;
279 }
280}
Zachary Turner610e5292015-05-07 21:39:33 +0000281
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282void DebuggerThread::DebugLoop() {
283 DEBUG_EVENT dbe = {0};
284 bool should_debug = true;
285 WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop");
286 while (should_debug) {
287 WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent");
288 BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE);
289 if (wait_result) {
290 DWORD continue_status = DBG_CONTINUE;
291 switch (dbe.dwDebugEventCode) {
292 case EXCEPTION_DEBUG_EVENT: {
293 ExceptionResult status =
294 HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
Adrian McCarthya59a7212015-06-19 18:26:53 +0000295
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 if (status == ExceptionResult::MaskException)
297 continue_status = DBG_CONTINUE;
298 else if (status == ExceptionResult::SendToApplication)
299 continue_status = DBG_EXCEPTION_NOT_HANDLED;
Zachary Turner610e5292015-05-07 21:39:33 +0000300
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301 break;
302 }
303 case CREATE_THREAD_DEBUG_EVENT:
304 continue_status =
305 HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
306 break;
307 case CREATE_PROCESS_DEBUG_EVENT:
308 continue_status =
309 HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId);
310 break;
311 case EXIT_THREAD_DEBUG_EVENT:
312 continue_status =
313 HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId);
314 break;
315 case EXIT_PROCESS_DEBUG_EVENT:
316 continue_status =
317 HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId);
318 should_debug = false;
319 break;
320 case LOAD_DLL_DEBUG_EVENT:
321 continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId);
322 break;
323 case UNLOAD_DLL_DEBUG_EVENT:
324 continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId);
325 break;
326 case OUTPUT_DEBUG_STRING_EVENT:
327 continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId);
328 break;
329 case RIP_EVENT:
330 continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId);
331 if (dbe.u.RipInfo.dwType == SLE_ERROR)
332 should_debug = false;
333 break;
334 }
335
336 WINLOGD_IFALL(
337 WINDOWS_LOG_EVENT,
338 "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.",
339 dbe.dwProcessId, dbe.dwThreadId, continue_status,
340 ::GetCurrentThreadId());
341
342 ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);
343
344 if (m_detached) {
345 should_debug = false;
346 }
347 } else {
348 WINERR_IFALL(
349 WINDOWS_LOG_EVENT,
350 "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u",
351 ::GetCurrentThreadId(), ::GetLastError());
352
353 should_debug = false;
Zachary Turner02862bc2014-11-07 23:44:13 +0000354 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000355 }
356 FreeProcessHandles();
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000357
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358 WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting.");
359 SetEvent(m_debugging_ended_event);
Zachary Turner02862bc2014-11-07 23:44:13 +0000360}
361
Zachary Turnerdcd80372014-11-11 00:00:14 +0000362ExceptionResult
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info,
364 DWORD thread_id) {
365 if (m_is_shutting_down) {
366 // A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic
367 // exception that
368 // we use simply to wake up the DebuggerThread so that we can close out the
369 // debug loop.
370 if (m_pid_to_detach != 0 &&
371 info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) {
372 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION |
373 WINDOWS_LOG_PROCESS,
374 "Breakpoint exception is cue to detach from process 0x%x",
375 m_pid_to_detach.load());
376 ::DebugActiveProcessStop(m_pid_to_detach);
377 m_detached = true;
Zachary Turner6c3c0ed2015-10-02 22:47:04 +0000378 }
379
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380 // Don't perform any blocking operations while we're shutting down. That
381 // will
382 // cause TerminateProcess -> WaitForSingleObject to time out.
383 return ExceptionResult::SendToApplication;
384 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000385
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386 bool first_chance = (info.dwFirstChance != 0);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000387
Kate Stoneb9c1b512016-09-06 20:57:50 +0000388 m_active_exception.reset(
389 new ExceptionRecord(info.ExceptionRecord, thread_id));
390 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION,
391 "HandleExceptionEvent encountered %s chance exception 0x%x on "
392 "thread 0x%x",
393 first_chance ? "first" : "second",
394 info.ExceptionRecord.ExceptionCode, thread_id);
Zachary Turner610e5292015-05-07 21:39:33 +0000395
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396 ExceptionResult result =
397 m_debug_delegate->OnDebugException(first_chance, *m_active_exception);
398 m_exception_pred.SetValue(result, eBroadcastNever);
Zachary Turner610e5292015-05-07 21:39:33 +0000399
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION,
401 "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred "
402 "!= BreakInDebugger");
Zachary Turnerc6a66532014-12-03 22:04:18 +0000403
Kate Stoneb9c1b512016-09-06 20:57:50 +0000404 m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger,
405 result);
Zachary Turner610e5292015-05-07 21:39:33 +0000406
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION,
408 "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u",
409 m_exception_pred.GetValue());
410
411 return result;
Zachary Turner02862bc2014-11-07 23:44:13 +0000412}
413
414DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000415DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info,
416 DWORD thread_id) {
417 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD,
418 "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u",
419 thread_id, m_process.GetProcessId());
420 HostThread thread(info.hThread);
421 thread.GetNativeThread().SetOwnsHandle(false);
422 m_debug_delegate->OnCreateThread(thread);
423 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000424}
425
426DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info,
428 DWORD thread_id) {
429 uint32_t process_id = ::GetProcessId(info.hProcess);
Zachary Turner610e5292015-05-07 21:39:33 +0000430
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS,
432 "HandleCreateProcessEvent process %u spawned", process_id);
Zachary Turner610e5292015-05-07 21:39:33 +0000433
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434 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());
Zachary Turner02862bc2014-11-07 23:44:13 +0000439
Kate Stoneb9c1b512016-09-06 20:57:50 +0000440 // 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;
Zachary Turner02862bc2014-11-07 23:44:13 +0000447
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage);
449 m_debug_delegate->OnDebuggerConnected(load_addr);
Zachary Turner02862bc2014-11-07 23:44:13 +0000450
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000452}
453
454DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000455DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info,
456 DWORD thread_id) {
457 WINLOG_IFANY(
458 WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD,
459 "HandleExitThreadEvent Thread %u exited with code %u in process %I64u",
460 thread_id, info.dwExitCode, m_process.GetProcessId());
461 m_debug_delegate->OnExitThread(thread_id, info.dwExitCode);
462 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000463}
464
465DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info,
467 DWORD thread_id) {
468 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD,
469 "HandleExitProcessEvent process %I64u exited with code %u",
470 m_process.GetProcessId(), info.dwExitCode);
Zachary Turner610e5292015-05-07 21:39:33 +0000471
Kate Stoneb9c1b512016-09-06 20:57:50 +0000472 m_debug_delegate->OnExitProcess(info.dwExitCode);
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000473
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474 FreeProcessHandles();
475 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000476}
477
478DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000479DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
480 DWORD thread_id) {
481 if (info.hFile == nullptr) {
482 // Not sure what this is, so just ignore it.
483 WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has "
484 "a NULL file handle, returning...",
485 m_process.GetProcessId());
Zachary Turner02862bc2014-11-07 23:44:13 +0000486 return DBG_CONTINUE;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000487 }
488
489 std::vector<wchar_t> buffer(1);
490 DWORD required_size =
491 GetFinalPathNameByHandleW(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
492 if (required_size > 0) {
493 buffer.resize(required_size + 1);
494 required_size = GetFinalPathNameByHandleW(info.hFile, &buffer[0],
495 required_size, VOLUME_NAME_DOS);
496 std::string path_str_utf8;
497 llvm::convertWideToUTF8(buffer.data(), path_str_utf8);
498 llvm::StringRef path_str = path_str_utf8;
499 const char *path = path_str.data();
500 if (path_str.startswith("\\\\?\\"))
501 path += 4;
502
503 FileSpec file_spec(path, false);
504 ModuleSpec module_spec(file_spec);
505 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll);
506
507 WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL "
508 "'%s' loaded at address 0x%p...",
509 m_process.GetProcessId(), path, info.lpBaseOfDll);
510
511 m_debug_delegate->OnLoadDll(module_spec, load_addr);
512 } else {
513 WINERR_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent Error "
514 "%u occurred calling "
515 "GetFinalPathNameByHandle",
516 m_process.GetProcessId(), ::GetLastError());
517 }
518 // Windows does not automatically close info.hFile, so we need to do it.
519 ::CloseHandle(info.hFile);
520 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000521}
522
523DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000524DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info,
525 DWORD thread_id) {
526 WINLOG_IFALL(WINDOWS_LOG_EVENT,
527 "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.",
528 m_process.GetProcessId(), info.lpBaseOfDll);
Zachary Turner610e5292015-05-07 21:39:33 +0000529
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530 m_debug_delegate->OnUnloadDll(
531 reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll));
532 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000533}
534
535DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000536DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info,
537 DWORD thread_id) {
538 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000539}
540
541DWORD
Kate Stoneb9c1b512016-09-06 20:57:50 +0000542DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id) {
543 WINERR_IFALL(WINDOWS_LOG_EVENT, "HandleRipEvent encountered error %u "
544 "(type=%u) in process %I64u thread %u",
545 info.dwError, info.dwType, m_process.GetProcessId(), thread_id);
Zachary Turner610e5292015-05-07 21:39:33 +0000546
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547 Error error(info.dwError, eErrorTypeWin32);
548 m_debug_delegate->OnDebuggerError(error, info.dwType);
Zachary Turner02862bc2014-11-07 23:44:13 +0000549
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550 return DBG_CONTINUE;
Zachary Turner02862bc2014-11-07 23:44:13 +0000551}