blob: 1e63aac2deb308aaeb37af40213ba3ce8d7885c2 [file] [log] [blame]
Zachary Turner02862bc2014-11-07 23:44:13 +00001//===-- 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"
Zachary Turnerdcd80372014-11-11 00:00:14 +000011#include "ExceptionRecord.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000012#include "IDebugDelegate.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000013
14#include "lldb/Core/Error.h"
15#include "lldb/Core/Log.h"
Zachary Turnera32d2ce2014-11-12 19:31:56 +000016#include "lldb/Core/ModuleSpec.h"
17#include "lldb/Host/FileSpec.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000018#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"
Zachary Turnerc62733b2015-05-20 18:31:17 +000025#include "lldb/Target/Process.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000026
Zachary Turner610e5292015-05-07 21:39:33 +000027#include "Plugins/Process/Windows/ProcessWindowsLog.h"
28
Zachary Turnera32d2ce2014-11-12 19:31:56 +000029#include "llvm/ADT/STLExtras.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000030#include "llvm/Support/raw_ostream.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
35namespace
36{
37struct DebugLaunchContext
38{
39 DebugLaunchContext(DebuggerThread *thread, const ProcessLaunchInfo &launch_info)
40 : m_thread(thread)
41 , m_launch_info(launch_info)
42 {
43 }
44 DebuggerThread *m_thread;
45 ProcessLaunchInfo m_launch_info;
46};
Zachary Turnerc62733b2015-05-20 18:31:17 +000047
48struct DebugAttachContext
49{
50 DebugAttachContext(DebuggerThread *thread, lldb::pid_t pid, const ProcessAttachInfo &attach_info)
51 : m_thread(thread)
52 , m_pid(pid)
53 , m_attach_info(attach_info)
54 {
55 }
56 DebuggerThread *m_thread;
57 lldb::pid_t m_pid;
58 ProcessAttachInfo m_attach_info;
59};
Zachary Turner02862bc2014-11-07 23:44:13 +000060}
61
62DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
63 : m_debug_delegate(debug_delegate)
64 , m_image_file(nullptr)
Zachary Turner3c1c5b92015-05-21 19:56:26 +000065 , m_debugging_ended_event(nullptr)
Adrian McCarthya59a7212015-06-19 18:26:53 +000066 , m_pid_to_detach(0)
67 , m_detached(false)
Zachary Turner02862bc2014-11-07 23:44:13 +000068{
Zachary Turner3c1c5b92015-05-21 19:56:26 +000069 m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
Zachary Turner02862bc2014-11-07 23:44:13 +000070}
71
72DebuggerThread::~DebuggerThread()
73{
Zachary Turner3c1c5b92015-05-21 19:56:26 +000074 ::CloseHandle(m_debugging_ended_event);
Zachary Turner02862bc2014-11-07 23:44:13 +000075}
76
Zachary Turner3985f892014-11-10 22:32:18 +000077Error
Zachary Turner02862bc2014-11-07 23:44:13 +000078DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info)
79{
Zachary Turner610e5292015-05-07 21:39:33 +000080 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
81 "DebuggerThread::DebugLaunch launching '%s'", launch_info.GetExecutableFile().GetPath().c_str());
Zachary Turner02862bc2014-11-07 23:44:13 +000082
Zachary Turner610e5292015-05-07 21:39:33 +000083 Error error;
Zachary Turner02862bc2014-11-07 23:44:13 +000084 DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
Zachary Turner610e5292015-05-07 21:39:33 +000085 HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]",
Zachary Turnerc62733b2015-05-20 18:31:17 +000086 DebuggerThreadLaunchRoutine, context, &error));
Zachary Turner610e5292015-05-07 21:39:33 +000087
88 if (!error.Success())
89 {
90 WINERR_IFALL(WINDOWS_LOG_PROCESS,
91 "DebugLaunch couldn't launch debugger thread. %s", error.AsCString());
92 }
Zachary Turner02862bc2014-11-07 23:44:13 +000093
Zachary Turner3985f892014-11-10 22:32:18 +000094 return error;
Zachary Turner02862bc2014-11-07 23:44:13 +000095}
96
Zachary Turnerc62733b2015-05-20 18:31:17 +000097Error
98DebuggerThread::DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info)
99{
100 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid);
101
102 Error error;
103 DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info);
104 HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]",
105 DebuggerThreadAttachRoutine, context, &error));
106
107 if (!error.Success())
108 {
109 WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid,
110 error.AsCString());
111 }
112
113 return error;
114}
115
Zachary Turner02862bc2014-11-07 23:44:13 +0000116lldb::thread_result_t
Zachary Turnerc62733b2015-05-20 18:31:17 +0000117DebuggerThread::DebuggerThreadLaunchRoutine(void *data)
Zachary Turner02862bc2014-11-07 23:44:13 +0000118{
119 DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
Zachary Turnerc62733b2015-05-20 18:31:17 +0000120 lldb::thread_result_t result = context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info);
Zachary Turner02862bc2014-11-07 23:44:13 +0000121 delete context;
122 return result;
123}
124
125lldb::thread_result_t
Zachary Turnerc62733b2015-05-20 18:31:17 +0000126DebuggerThread::DebuggerThreadAttachRoutine(void *data)
127{
128 DebugAttachContext *context = static_cast<DebugAttachContext *>(data);
129 lldb::thread_result_t result =
130 context->m_thread->DebuggerThreadAttachRoutine(context->m_pid, context->m_attach_info);
131 delete context;
132 return result;
133}
134
135lldb::thread_result_t
136DebuggerThread::DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info)
Zachary Turner02862bc2014-11-07 23:44:13 +0000137{
138 // Grab a shared_ptr reference to this so that we know it won't get deleted until after the
139 // thread routine has exited.
140 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
Zachary Turner02862bc2014-11-07 23:44:13 +0000141
Zachary Turnerc62733b2015-05-20 18:31:17 +0000142 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to launch '%s' on background thread.",
143 launch_info.GetExecutableFile().GetPath().c_str());
Zachary Turner610e5292015-05-07 21:39:33 +0000144
Zachary Turner02862bc2014-11-07 23:44:13 +0000145 Error error;
146 ProcessLauncherWindows launcher;
147 HostProcess process(launcher.LaunchProcess(launch_info, error));
148 // If we couldn't create the process, notify waiters immediately. Otherwise enter the debug
149 // loop and wait until we get the create process debug notification. Note that if the process
150 // was created successfully, we can throw away the process handle we got from CreateProcess
151 // because Windows will give us another (potentially more useful?) handle when it sends us the
152 // CREATE_PROCESS_DEBUG_EVENT.
153 if (error.Success())
154 DebugLoop();
155 else
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000156 m_debug_delegate->OnDebuggerError(error, 0);
Zachary Turner02862bc2014-11-07 23:44:13 +0000157
158 return 0;
159}
160
Zachary Turnerc62733b2015-05-20 18:31:17 +0000161lldb::thread_result_t
162DebuggerThread::DebuggerThreadAttachRoutine(lldb::pid_t pid, const ProcessAttachInfo &attach_info)
163{
164 // Grab a shared_ptr reference to this so that we know it won't get deleted until after the
165 // thread routine has exited.
166 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
167
168 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to process '%u' on background thread.",
169 (DWORD)pid);
170
171 if (!DebugActiveProcess((DWORD)pid))
172 {
173 Error error(::GetLastError(), eErrorTypeWin32);
174 m_debug_delegate->OnDebuggerError(error, 0);
175 return 0;
176 }
177
178 // The attach was successful, enter the debug loop. From here on out, this is no different than
179 // a create process operation, so all the same comments in DebugLaunch should apply from this
180 // point out.
181 DebugLoop();
182
183 return 0;
184}
185
Zachary Turnerc6a66532014-12-03 22:04:18 +0000186Error
187DebuggerThread::StopDebugging(bool terminate)
188{
189 Error error;
190
Zachary Turner610e5292015-05-07 21:39:33 +0000191 lldb::pid_t pid = m_process.GetProcessId();
192
193 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
194 "StopDebugging('%s') called (inferior=%I64u).",
195 (terminate ? "true" : "false"), pid);
196
Adrian McCarthya59a7212015-06-19 18:26:53 +0000197 // Make a copy of the process, since the termination sequence will reset
198 // DebuggerThread's internal copy and it needs to remain open for the Wait operation.
199 HostProcess process_copy = m_process;
200 lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle();
201
Zachary Turnerc6a66532014-12-03 22:04:18 +0000202 if (terminate)
203 {
Zachary Turner610e5292015-05-07 21:39:33 +0000204 // Initiate the termination before continuing the exception, so that the next debug
205 // event we get is the exit process event, and not some other event.
Zachary Turnerc6a66532014-12-03 22:04:18 +0000206 BOOL terminate_suceeded = TerminateProcess(handle, 0);
Zachary Turner610e5292015-05-07 21:39:33 +0000207 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
208 "StopDebugging called TerminateProcess(0x%p, 0) (inferior=%I64u), success='%s'",
209 handle, pid, (terminate_suceeded ? "true" : "false"));
Adrian McCarthya59a7212015-06-19 18:26:53 +0000210 }
Zachary Turner610e5292015-05-07 21:39:33 +0000211
Adrian McCarthya59a7212015-06-19 18:26:53 +0000212 // If we're stuck waiting for an exception to continue (e.g. the user is at a breakpoint
213 // messing around in the debugger), continue it now. But only AFTER calling TerminateProcess
214 // to make sure that the very next call to WaitForDebugEvent is an exit process event.
215 if (m_active_exception.get())
216 {
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 {
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 thread.
229 if (!::DebugBreakProcess(GetProcess().GetNativeProcess().GetSystemHandle()))
Zachary Turner610e5292015-05-07 21:39:33 +0000230 {
Adrian McCarthya59a7212015-06-19 18:26:53 +0000231 error.SetError(::GetLastError(), eErrorTypeWin32);
Zachary Turner610e5292015-05-07 21:39:33 +0000232 }
Adrian McCarthya59a7212015-06-19 18:26:53 +0000233 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000234
Adrian McCarthya59a7212015-06-19 18:26:53 +0000235 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging waiting for detach from process %u to complete.", pid);
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000236
Adrian McCarthya59a7212015-06-19 18:26:53 +0000237 DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000);
238 if (wait_result != WAIT_OBJECT_0)
239 {
240 error.SetError(GetLastError(), eErrorTypeWin32);
241 WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u",
242 m_debugging_ended_event, wait_result);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000243 }
244 else
245 {
Adrian McCarthya59a7212015-06-19 18:26:53 +0000246 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging detach from process %u completed successfully.", pid);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000247 }
Zachary Turner610e5292015-05-07 21:39:33 +0000248
249 if (!error.Success())
250 {
251 WINERR_IFALL(WINDOWS_LOG_PROCESS,
Adrian McCarthya59a7212015-06-19 18:26:53 +0000252 "StopDebugging encountered an error while trying to stop process %u. %s",
Zachary Turner610e5292015-05-07 21:39:33 +0000253 pid, error.AsCString());
254 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000255 return error;
256}
257
Zachary Turner02862bc2014-11-07 23:44:13 +0000258void
Zachary Turnerdcd80372014-11-11 00:00:14 +0000259DebuggerThread::ContinueAsyncException(ExceptionResult result)
260{
Zachary Turnerc6a66532014-12-03 22:04:18 +0000261 if (!m_active_exception.get())
262 return;
263
Zachary Turner610e5292015-05-07 21:39:33 +0000264 WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION,
265 "ContinueAsyncException called for inferior process %I64u, broadcasting.",
266 m_process.GetProcessId());
267
Zachary Turnerc6a66532014-12-03 22:04:18 +0000268 m_active_exception.reset();
269 m_exception_pred.SetValue(result, eBroadcastAlways);
270}
271
272void
273DebuggerThread::FreeProcessHandles()
274{
275 m_process = HostProcess();
276 m_main_thread = HostThread();
277 if (m_image_file)
278 {
279 ::CloseHandle(m_image_file);
280 m_image_file = nullptr;
281 }
Zachary Turnerdcd80372014-11-11 00:00:14 +0000282}
283
284void
Zachary Turner02862bc2014-11-07 23:44:13 +0000285DebuggerThread::DebugLoop()
286{
287 DEBUG_EVENT dbe = {0};
Zachary Turnerbe5e1e52014-12-04 22:07:02 +0000288 bool should_debug = true;
Zachary Turner610e5292015-05-07 21:39:33 +0000289 WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop");
290 while (should_debug)
Zachary Turner02862bc2014-11-07 23:44:13 +0000291 {
Zachary Turner610e5292015-05-07 21:39:33 +0000292 WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent");
293 BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE);
294 if (wait_result)
Zachary Turner02862bc2014-11-07 23:44:13 +0000295 {
Zachary Turner610e5292015-05-07 21:39:33 +0000296 DWORD continue_status = DBG_CONTINUE;
297 switch (dbe.dwDebugEventCode)
Zachary Turnerdcd80372014-11-11 00:00:14 +0000298 {
Zachary Turner610e5292015-05-07 21:39:33 +0000299 case EXCEPTION_DEBUG_EVENT:
300 {
301 ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
Zachary Turnerdcd80372014-11-11 00:00:14 +0000302
Zachary Turner610e5292015-05-07 21:39:33 +0000303 if (status == ExceptionResult::MaskException)
304 continue_status = DBG_CONTINUE;
305 else if (status == ExceptionResult::SendToApplication)
306 continue_status = DBG_EXCEPTION_NOT_HANDLED;
307 break;
308 }
309 case CREATE_THREAD_DEBUG_EVENT:
310 continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
311 break;
312 case CREATE_PROCESS_DEBUG_EVENT:
313 continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId);
314 break;
315 case EXIT_THREAD_DEBUG_EVENT:
316 continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId);
317 break;
318 case EXIT_PROCESS_DEBUG_EVENT:
319 continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000320 should_debug = false;
Zachary Turner610e5292015-05-07 21:39:33 +0000321 break;
322 case LOAD_DLL_DEBUG_EVENT:
323 continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId);
324 break;
325 case UNLOAD_DLL_DEBUG_EVENT:
326 continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId);
327 break;
328 case OUTPUT_DEBUG_STRING_EVENT:
329 continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId);
330 break;
331 case RIP_EVENT:
332 continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId);
333 if (dbe.u.RipInfo.dwType == SLE_ERROR)
334 should_debug = false;
335 break;
336 }
Zachary Turner02862bc2014-11-07 23:44:13 +0000337
Zachary Turner610e5292015-05-07 21:39:33 +0000338 WINLOGD_IFALL(WINDOWS_LOG_EVENT, "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.",
339 dbe.dwProcessId, dbe.dwThreadId, continue_status, ::GetCurrentThreadId());
340
341 ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);
Adrian McCarthya59a7212015-06-19 18:26:53 +0000342
343 if (m_detached)
344 {
345 should_debug = false;
346 }
Zachary Turner610e5292015-05-07 21:39:33 +0000347 }
348 else
349 {
350 WINERR_IFALL(WINDOWS_LOG_EVENT,
351 "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u",
352 ::GetCurrentThreadId(), ::GetLastError());
353
354 should_debug = false;
355 }
Zachary Turner02862bc2014-11-07 23:44:13 +0000356 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000357 FreeProcessHandles();
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000358
359 WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting.");
Adrian McCarthya59a7212015-06-19 18:26:53 +0000360 SetEvent(m_debugging_ended_event);
Zachary Turner02862bc2014-11-07 23:44:13 +0000361}
362
Zachary Turnerdcd80372014-11-11 00:00:14 +0000363ExceptionResult
Zachary Turner02862bc2014-11-07 23:44:13 +0000364DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
365{
Zachary Turnerdcd80372014-11-11 00:00:14 +0000366 bool first_chance = (info.dwFirstChance != 0);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000367
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000368 m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord, thread_id));
Zachary Turner610e5292015-05-07 21:39:33 +0000369 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION,
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000370 "HandleExceptionEvent encountered %s chance exception 0x%x on thread 0x%x",
Zachary Turner610e5292015-05-07 21:39:33 +0000371 first_chance ? "first" : "second", info.ExceptionRecord.ExceptionCode, thread_id);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000372
Adrian McCarthya59a7212015-06-19 18:26:53 +0000373 if (m_pid_to_detach != 0 && m_active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT) {
374 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_PROCESS,
375 "Breakpoint exception is cue to detach from process 0x%x",
376 m_pid_to_detach);
377 if (::DebugActiveProcessStop(m_pid_to_detach)) {
378 m_detached = true;
379 return ExceptionResult::MaskException;
380 } else {
381 WINLOG_IFANY(WINDOWS_LOG_PROCESS, "Failed to detach, treating as a regular breakpoint");
382 }
383 }
384
Zachary Turner610e5292015-05-07 21:39:33 +0000385 ExceptionResult result = m_debug_delegate->OnDebugException(first_chance,
386 *m_active_exception);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000387 m_exception_pred.SetValue(result, eBroadcastNever);
Zachary Turner610e5292015-05-07 21:39:33 +0000388
389 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION,
390 "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred != BreakInDebugger");
391
Zachary Turnerc6a66532014-12-03 22:04:18 +0000392 m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, result);
393
Zachary Turner610e5292015-05-07 21:39:33 +0000394 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION,
395 "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u",
396 m_exception_pred.GetValue());
397
Zachary Turnerc6a66532014-12-03 22:04:18 +0000398 return result;
Zachary Turner02862bc2014-11-07 23:44:13 +0000399}
400
401DWORD
402DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id)
403{
Zachary Turner610e5292015-05-07 21:39:33 +0000404 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000405 "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u",
406 thread_id, m_process.GetProcessId());
407 HostThread thread(info.hThread);
408 thread.GetNativeThread().SetOwnsHandle(false);
409 m_debug_delegate->OnCreateThread(thread);
Zachary Turner02862bc2014-11-07 23:44:13 +0000410 return DBG_CONTINUE;
411}
412
413DWORD
414DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id)
415{
Zachary Turner610e5292015-05-07 21:39:33 +0000416 uint32_t process_id = ::GetProcessId(info.hProcess);
417
418 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, "HandleCreateProcessEvent process %u spawned", process_id);
419
Zachary Turner02862bc2014-11-07 23:44:13 +0000420 std::string thread_name;
421 llvm::raw_string_ostream name_stream(thread_name);
Zachary Turner610e5292015-05-07 21:39:33 +0000422 name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]";
Zachary Turner02862bc2014-11-07 23:44:13 +0000423 name_stream.flush();
424 ThisThread::SetName(thread_name.c_str());
425
426 // info.hProcess and info.hThread are closed automatically by Windows when
427 // EXIT_PROCESS_DEBUG_EVENT is received.
428 m_process = HostProcess(info.hProcess);
429 ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false);
430 m_main_thread = HostThread(info.hThread);
Zachary Turnerc3018992014-11-17 22:42:57 +0000431 m_main_thread.GetNativeThread().SetOwnsHandle(false);
Zachary Turner02862bc2014-11-07 23:44:13 +0000432 m_image_file = info.hFile;
433
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000434 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage);
435 m_debug_delegate->OnDebuggerConnected(load_addr);
Zachary Turner02862bc2014-11-07 23:44:13 +0000436
437 return DBG_CONTINUE;
438}
439
440DWORD
441DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id)
442{
Zachary Turner610e5292015-05-07 21:39:33 +0000443 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
444 "HandleExitThreadEvent Thread %u exited with code %u in process %I64u",
445 thread_id, info.dwExitCode, m_process.GetProcessId());
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000446 m_debug_delegate->OnExitThread(thread_id, info.dwExitCode);
Zachary Turner02862bc2014-11-07 23:44:13 +0000447 return DBG_CONTINUE;
448}
449
450DWORD
451DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id)
452{
Zachary Turner610e5292015-05-07 21:39:33 +0000453 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
454 "HandleExitProcessEvent process %I64u exited with code %u",
455 m_process.GetProcessId(), info.dwExitCode);
456
Oleksiy Vyalov9953f082015-05-15 02:05:10 +0000457 m_debug_delegate->OnExitProcess(info.dwExitCode);
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000458
459 FreeProcessHandles();
Zachary Turner02862bc2014-11-07 23:44:13 +0000460 return DBG_CONTINUE;
461}
462
463DWORD
464DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
465{
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000466 if (info.hFile == nullptr)
467 {
468 // Not sure what this is, so just ignore it.
Zachary Turner610e5292015-05-07 21:39:33 +0000469 WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has a NULL file handle, returning...",
470 m_process.GetProcessId());
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000471 return DBG_CONTINUE;
472 }
473
474 std::vector<char> buffer(1);
475 DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
476 if (required_size > 0)
477 {
478 buffer.resize(required_size + 1);
479 required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS);
480 llvm::StringRef path_str(&buffer[0]);
481 const char *path = path_str.data();
482 if (path_str.startswith("\\\\?\\"))
483 path += 4;
484
485 FileSpec file_spec(path, false);
486 ModuleSpec module_spec(file_spec);
487 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll);
Zachary Turner610e5292015-05-07 21:39:33 +0000488
489 WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL '%s' loaded at address 0x%p...",
490 m_process.GetProcessId(), path, info.lpBaseOfDll);
491
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000492 m_debug_delegate->OnLoadDll(module_spec, load_addr);
493 }
494 else
495 {
Zachary Turner610e5292015-05-07 21:39:33 +0000496 WINERR_IFALL(WINDOWS_LOG_EVENT,
497 "Inferior %I64u - HandleLoadDllEvent Error %u occurred calling GetFinalPathNameByHandle",
498 m_process.GetProcessId(), ::GetLastError());
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000499 }
500 // Windows does not automatically close info.hFile, so we need to do it.
Zachary Turner02862bc2014-11-07 23:44:13 +0000501 ::CloseHandle(info.hFile);
502 return DBG_CONTINUE;
503}
504
505DWORD
506DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
507{
Zachary Turner610e5292015-05-07 21:39:33 +0000508 WINLOG_IFALL(WINDOWS_LOG_EVENT,
509 "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.",
510 m_process.GetProcessId(), info.lpBaseOfDll);
511
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000512 m_debug_delegate->OnUnloadDll(reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll));
Zachary Turner02862bc2014-11-07 23:44:13 +0000513 return DBG_CONTINUE;
514}
515
516DWORD
517DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id)
518{
519 return DBG_CONTINUE;
520}
521
522DWORD
523DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id)
524{
Zachary Turner610e5292015-05-07 21:39:33 +0000525 WINERR_IFALL(WINDOWS_LOG_EVENT,
526 "HandleRipEvent encountered error %u (type=%u) in process %I64u thread %u",
527 info.dwError, info.dwType, m_process.GetProcessId(), thread_id);
528
Zachary Turner02862bc2014-11-07 23:44:13 +0000529 Error error(info.dwError, eErrorTypeWin32);
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000530 m_debug_delegate->OnDebuggerError(error, info.dwType);
Zachary Turner02862bc2014-11-07 23:44:13 +0000531
532 return DBG_CONTINUE;
533}