blob: 43afbec7513b722acabb62c55b2e58d0d8eb2867 [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)
Zachary Turner02862bc2014-11-07 23:44:13 +000066{
Zachary Turner3c1c5b92015-05-21 19:56:26 +000067 m_debugging_ended_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
Zachary Turner02862bc2014-11-07 23:44:13 +000068}
69
70DebuggerThread::~DebuggerThread()
71{
Zachary Turner3c1c5b92015-05-21 19:56:26 +000072 ::CloseHandle(m_debugging_ended_event);
Zachary Turner02862bc2014-11-07 23:44:13 +000073}
74
Zachary Turner3985f892014-11-10 22:32:18 +000075Error
Zachary Turner02862bc2014-11-07 23:44:13 +000076DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info)
77{
Zachary Turner610e5292015-05-07 21:39:33 +000078 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
79 "DebuggerThread::DebugLaunch launching '%s'", launch_info.GetExecutableFile().GetPath().c_str());
Zachary Turner02862bc2014-11-07 23:44:13 +000080
Zachary Turner610e5292015-05-07 21:39:33 +000081 Error error;
Zachary Turner02862bc2014-11-07 23:44:13 +000082 DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
Zachary Turner610e5292015-05-07 21:39:33 +000083 HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]",
Zachary Turnerc62733b2015-05-20 18:31:17 +000084 DebuggerThreadLaunchRoutine, context, &error));
Zachary Turner610e5292015-05-07 21:39:33 +000085
86 if (!error.Success())
87 {
88 WINERR_IFALL(WINDOWS_LOG_PROCESS,
89 "DebugLaunch couldn't launch debugger thread. %s", error.AsCString());
90 }
Zachary Turner02862bc2014-11-07 23:44:13 +000091
Zachary Turner3985f892014-11-10 22:32:18 +000092 return error;
Zachary Turner02862bc2014-11-07 23:44:13 +000093}
94
Zachary Turnerc62733b2015-05-20 18:31:17 +000095Error
96DebuggerThread::DebugAttach(lldb::pid_t pid, const ProcessAttachInfo &attach_info)
97{
98 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread::DebugAttach attaching to '%u'", (DWORD)pid);
99
100 Error error;
101 DebugAttachContext *context = new DebugAttachContext(this, pid, attach_info);
102 HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]",
103 DebuggerThreadAttachRoutine, context, &error));
104
105 if (!error.Success())
106 {
107 WINERR_IFALL(WINDOWS_LOG_PROCESS, "DebugAttach couldn't attach to process '%u'. %s", (DWORD)pid,
108 error.AsCString());
109 }
110
111 return error;
112}
113
Zachary Turner02862bc2014-11-07 23:44:13 +0000114lldb::thread_result_t
Zachary Turnerc62733b2015-05-20 18:31:17 +0000115DebuggerThread::DebuggerThreadLaunchRoutine(void *data)
Zachary Turner02862bc2014-11-07 23:44:13 +0000116{
117 DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
Zachary Turnerc62733b2015-05-20 18:31:17 +0000118 lldb::thread_result_t result = context->m_thread->DebuggerThreadLaunchRoutine(context->m_launch_info);
Zachary Turner02862bc2014-11-07 23:44:13 +0000119 delete context;
120 return result;
121}
122
123lldb::thread_result_t
Zachary Turnerc62733b2015-05-20 18:31:17 +0000124DebuggerThread::DebuggerThreadAttachRoutine(void *data)
125{
126 DebugAttachContext *context = static_cast<DebugAttachContext *>(data);
127 lldb::thread_result_t result =
128 context->m_thread->DebuggerThreadAttachRoutine(context->m_pid, context->m_attach_info);
129 delete context;
130 return result;
131}
132
133lldb::thread_result_t
134DebuggerThread::DebuggerThreadLaunchRoutine(const ProcessLaunchInfo &launch_info)
Zachary Turner02862bc2014-11-07 23:44:13 +0000135{
136 // Grab a shared_ptr reference to this so that we know it won't get deleted until after the
137 // thread routine has exited.
138 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
Zachary Turner02862bc2014-11-07 23:44:13 +0000139
Zachary Turnerc62733b2015-05-20 18:31:17 +0000140 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to launch '%s' on background thread.",
141 launch_info.GetExecutableFile().GetPath().c_str());
Zachary Turner610e5292015-05-07 21:39:33 +0000142
Zachary Turner02862bc2014-11-07 23:44:13 +0000143 Error error;
144 ProcessLauncherWindows launcher;
145 HostProcess process(launcher.LaunchProcess(launch_info, error));
146 // If we couldn't create the process, notify waiters immediately. Otherwise enter the debug
147 // loop and wait until we get the create process debug notification. Note that if the process
148 // was created successfully, we can throw away the process handle we got from CreateProcess
149 // because Windows will give us another (potentially more useful?) handle when it sends us the
150 // CREATE_PROCESS_DEBUG_EVENT.
151 if (error.Success())
152 DebugLoop();
153 else
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000154 m_debug_delegate->OnDebuggerError(error, 0);
Zachary Turner02862bc2014-11-07 23:44:13 +0000155
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000156 SetEvent(m_debugging_ended_event);
Zachary Turner02862bc2014-11-07 23:44:13 +0000157 return 0;
158}
159
Zachary Turnerc62733b2015-05-20 18:31:17 +0000160lldb::thread_result_t
161DebuggerThread::DebuggerThreadAttachRoutine(lldb::pid_t pid, const ProcessAttachInfo &attach_info)
162{
163 // Grab a shared_ptr reference to this so that we know it won't get deleted until after the
164 // thread routine has exited.
165 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
166
167 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DebuggerThread preparing to attach to process '%u' on background thread.",
168 (DWORD)pid);
169
170 if (!DebugActiveProcess((DWORD)pid))
171 {
172 Error error(::GetLastError(), eErrorTypeWin32);
173 m_debug_delegate->OnDebuggerError(error, 0);
174 return 0;
175 }
176
177 // The attach was successful, enter the debug loop. From here on out, this is no different than
178 // a create process operation, so all the same comments in DebugLaunch should apply from this
179 // point out.
180 DebugLoop();
181
182 return 0;
183}
184
Zachary Turnerc6a66532014-12-03 22:04:18 +0000185Error
186DebuggerThread::StopDebugging(bool terminate)
187{
188 Error error;
189
Zachary Turner610e5292015-05-07 21:39:33 +0000190 lldb::pid_t pid = m_process.GetProcessId();
191
192 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
193 "StopDebugging('%s') called (inferior=%I64u).",
194 (terminate ? "true" : "false"), pid);
195
Zachary Turnerc6a66532014-12-03 22:04:18 +0000196 if (terminate)
197 {
Zachary Turner610e5292015-05-07 21:39:33 +0000198 // Make a copy of the process, since the termination sequence will reset
199 // DebuggerThread's internal copy and it needs to remain open for the Wait operation.
Zachary Turnerc6a66532014-12-03 22:04:18 +0000200 HostProcess process_copy = m_process;
Zachary Turner610e5292015-05-07 21:39:33 +0000201 lldb::process_t handle = m_process.GetNativeProcess().GetSystemHandle();
Zachary Turnerc6a66532014-12-03 22:04:18 +0000202
Zachary Turner610e5292015-05-07 21:39:33 +0000203 // Initiate the termination before continuing the exception, so that the next debug
204 // event we get is the exit process event, and not some other event.
Zachary Turnerc6a66532014-12-03 22:04:18 +0000205 BOOL terminate_suceeded = TerminateProcess(handle, 0);
Zachary Turner610e5292015-05-07 21:39:33 +0000206 WINLOG_IFALL(WINDOWS_LOG_PROCESS,
207 "StopDebugging called TerminateProcess(0x%p, 0) (inferior=%I64u), success='%s'",
208 handle, pid, (terminate_suceeded ? "true" : "false"));
209
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000210 // If we're stuck waiting for an exception to continue (e.g. the user is at a breakpoint
211 // messing around in the debugger), continue it now. But only AFTER calling TerminateProcess
212 // to make sure that the very next call to WaitForDebugEvent is an exit process event.
Zachary Turnerc6a66532014-12-03 22:04:18 +0000213 if (m_active_exception.get())
Zachary Turner610e5292015-05-07 21:39:33 +0000214 {
215 WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION,
216 "StopDebugging masking active exception");
217
Zachary Turnerc6a66532014-12-03 22:04:18 +0000218 ContinueAsyncException(ExceptionResult::MaskException);
Zachary Turner610e5292015-05-07 21:39:33 +0000219 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000220
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000221 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging waiting for detach from process %u to complete.", pid);
222
223 DWORD wait_result = WaitForSingleObject(m_debugging_ended_event, 5000);
224 if (wait_result != WAIT_OBJECT_0)
Zachary Turnerc6a66532014-12-03 22:04:18 +0000225 {
Zachary Turnerc6a66532014-12-03 22:04:18 +0000226 error.SetError(GetLastError(), eErrorTypeWin32);
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000227 WINERR_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging WaitForSingleObject(0x%p, 5000) returned %u",
228 m_debugging_ended_event, wait_result);
229 }
230 else
231 {
232 WINLOG_IFALL(WINDOWS_LOG_PROCESS, "StopDebugging detach from process %u completed successfully.", pid);
233 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000234 }
235 else
236 {
237 error.SetErrorString("Detach not yet supported on Windows.");
238 // TODO: Implement detach.
239 }
Zachary Turner610e5292015-05-07 21:39:33 +0000240
241 if (!error.Success())
242 {
243 WINERR_IFALL(WINDOWS_LOG_PROCESS,
244 "StopDebugging encountered an error while trying to stop process %u. %s",
245 pid, error.AsCString());
246 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000247 return error;
248}
249
Zachary Turner02862bc2014-11-07 23:44:13 +0000250void
Zachary Turnerdcd80372014-11-11 00:00:14 +0000251DebuggerThread::ContinueAsyncException(ExceptionResult result)
252{
Zachary Turnerc6a66532014-12-03 22:04:18 +0000253 if (!m_active_exception.get())
254 return;
255
Zachary Turner610e5292015-05-07 21:39:33 +0000256 WINLOG_IFANY(WINDOWS_LOG_PROCESS|WINDOWS_LOG_EXCEPTION,
257 "ContinueAsyncException called for inferior process %I64u, broadcasting.",
258 m_process.GetProcessId());
259
Zachary Turnerc6a66532014-12-03 22:04:18 +0000260 m_active_exception.reset();
261 m_exception_pred.SetValue(result, eBroadcastAlways);
262}
263
264void
265DebuggerThread::FreeProcessHandles()
266{
267 m_process = HostProcess();
268 m_main_thread = HostThread();
269 if (m_image_file)
270 {
271 ::CloseHandle(m_image_file);
272 m_image_file = nullptr;
273 }
Zachary Turnerdcd80372014-11-11 00:00:14 +0000274}
275
276void
Zachary Turner02862bc2014-11-07 23:44:13 +0000277DebuggerThread::DebugLoop()
278{
279 DEBUG_EVENT dbe = {0};
Zachary Turnerbe5e1e52014-12-04 22:07:02 +0000280 bool should_debug = true;
Zachary Turner610e5292015-05-07 21:39:33 +0000281 WINLOG_IFALL(WINDOWS_LOG_EVENT, "Entering WaitForDebugEvent loop");
282 while (should_debug)
Zachary Turner02862bc2014-11-07 23:44:13 +0000283 {
Zachary Turner610e5292015-05-07 21:39:33 +0000284 WINLOGD_IFALL(WINDOWS_LOG_EVENT, "Calling WaitForDebugEvent");
285 BOOL wait_result = WaitForDebugEvent(&dbe, INFINITE);
286 if (wait_result)
Zachary Turner02862bc2014-11-07 23:44:13 +0000287 {
Zachary Turner610e5292015-05-07 21:39:33 +0000288 DWORD continue_status = DBG_CONTINUE;
289 switch (dbe.dwDebugEventCode)
Zachary Turnerdcd80372014-11-11 00:00:14 +0000290 {
Zachary Turner610e5292015-05-07 21:39:33 +0000291 case EXCEPTION_DEBUG_EVENT:
292 {
293 ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
Zachary Turnerdcd80372014-11-11 00:00:14 +0000294
Zachary Turner610e5292015-05-07 21:39:33 +0000295 if (status == ExceptionResult::MaskException)
296 continue_status = DBG_CONTINUE;
297 else if (status == ExceptionResult::SendToApplication)
298 continue_status = DBG_EXCEPTION_NOT_HANDLED;
299 break;
300 }
301 case CREATE_THREAD_DEBUG_EVENT:
302 continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
303 break;
304 case CREATE_PROCESS_DEBUG_EVENT:
305 continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId);
306 break;
307 case EXIT_THREAD_DEBUG_EVENT:
308 continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId);
309 break;
310 case EXIT_PROCESS_DEBUG_EVENT:
311 continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000312 should_debug = false;
Zachary Turner610e5292015-05-07 21:39:33 +0000313 break;
314 case LOAD_DLL_DEBUG_EVENT:
315 continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId);
316 break;
317 case UNLOAD_DLL_DEBUG_EVENT:
318 continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId);
319 break;
320 case OUTPUT_DEBUG_STRING_EVENT:
321 continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId);
322 break;
323 case RIP_EVENT:
324 continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId);
325 if (dbe.u.RipInfo.dwType == SLE_ERROR)
326 should_debug = false;
327 break;
328 }
Zachary Turner02862bc2014-11-07 23:44:13 +0000329
Zachary Turner610e5292015-05-07 21:39:33 +0000330 WINLOGD_IFALL(WINDOWS_LOG_EVENT, "DebugLoop calling ContinueDebugEvent(%u, %u, %u) on thread %u.",
331 dbe.dwProcessId, dbe.dwThreadId, continue_status, ::GetCurrentThreadId());
332
333 ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);
334 }
335 else
336 {
337 WINERR_IFALL(WINDOWS_LOG_EVENT,
338 "DebugLoop returned FALSE from WaitForDebugEvent. Error = %u",
339 ::GetCurrentThreadId(), ::GetLastError());
340
341 should_debug = false;
342 }
Zachary Turner02862bc2014-11-07 23:44:13 +0000343 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000344 FreeProcessHandles();
Zachary Turner3c1c5b92015-05-21 19:56:26 +0000345
346 WINLOG_IFALL(WINDOWS_LOG_EVENT, "WaitForDebugEvent loop completed, exiting.");
Zachary Turner02862bc2014-11-07 23:44:13 +0000347}
348
Zachary Turnerdcd80372014-11-11 00:00:14 +0000349ExceptionResult
Zachary Turner02862bc2014-11-07 23:44:13 +0000350DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
351{
Zachary Turnerdcd80372014-11-11 00:00:14 +0000352 bool first_chance = (info.dwFirstChance != 0);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000353
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000354 m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord, thread_id));
Zachary Turner610e5292015-05-07 21:39:33 +0000355 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION,
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000356 "HandleExceptionEvent encountered %s chance exception 0x%x on thread 0x%x",
Zachary Turner610e5292015-05-07 21:39:33 +0000357 first_chance ? "first" : "second", info.ExceptionRecord.ExceptionCode, thread_id);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000358
Zachary Turner610e5292015-05-07 21:39:33 +0000359 ExceptionResult result = m_debug_delegate->OnDebugException(first_chance,
360 *m_active_exception);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000361 m_exception_pred.SetValue(result, eBroadcastNever);
Zachary Turner610e5292015-05-07 21:39:33 +0000362
363 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION,
364 "DebuggerThread::HandleExceptionEvent waiting for ExceptionPred != BreakInDebugger");
365
Zachary Turnerc6a66532014-12-03 22:04:18 +0000366 m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, result);
367
Zachary Turner610e5292015-05-07 21:39:33 +0000368 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_EXCEPTION,
369 "DebuggerThread::HandleExceptionEvent got ExceptionPred = %u",
370 m_exception_pred.GetValue());
371
Zachary Turnerc6a66532014-12-03 22:04:18 +0000372 return result;
Zachary Turner02862bc2014-11-07 23:44:13 +0000373}
374
375DWORD
376DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id)
377{
Zachary Turner610e5292015-05-07 21:39:33 +0000378 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000379 "HandleCreateThreadEvent Thread 0x%x spawned in process %I64u",
380 thread_id, m_process.GetProcessId());
381 HostThread thread(info.hThread);
382 thread.GetNativeThread().SetOwnsHandle(false);
383 m_debug_delegate->OnCreateThread(thread);
Zachary Turner02862bc2014-11-07 23:44:13 +0000384 return DBG_CONTINUE;
385}
386
387DWORD
388DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id)
389{
Zachary Turner610e5292015-05-07 21:39:33 +0000390 uint32_t process_id = ::GetProcessId(info.hProcess);
391
392 WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_PROCESS, "HandleCreateProcessEvent process %u spawned", process_id);
393
Zachary Turner02862bc2014-11-07 23:44:13 +0000394 std::string thread_name;
395 llvm::raw_string_ostream name_stream(thread_name);
Zachary Turner610e5292015-05-07 21:39:33 +0000396 name_stream << "lldb.plugin.process-windows.slave[" << process_id << "]";
Zachary Turner02862bc2014-11-07 23:44:13 +0000397 name_stream.flush();
398 ThisThread::SetName(thread_name.c_str());
399
400 // info.hProcess and info.hThread are closed automatically by Windows when
401 // EXIT_PROCESS_DEBUG_EVENT is received.
402 m_process = HostProcess(info.hProcess);
403 ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false);
404 m_main_thread = HostThread(info.hThread);
Zachary Turnerc3018992014-11-17 22:42:57 +0000405 m_main_thread.GetNativeThread().SetOwnsHandle(false);
Zachary Turner02862bc2014-11-07 23:44:13 +0000406 m_image_file = info.hFile;
407
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000408 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage);
409 m_debug_delegate->OnDebuggerConnected(load_addr);
Zachary Turner02862bc2014-11-07 23:44:13 +0000410
411 return DBG_CONTINUE;
412}
413
414DWORD
415DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id)
416{
Zachary Turner610e5292015-05-07 21:39:33 +0000417 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
418 "HandleExitThreadEvent Thread %u exited with code %u in process %I64u",
419 thread_id, info.dwExitCode, m_process.GetProcessId());
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000420 m_debug_delegate->OnExitThread(thread_id, info.dwExitCode);
Zachary Turner02862bc2014-11-07 23:44:13 +0000421 return DBG_CONTINUE;
422}
423
424DWORD
425DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id)
426{
Zachary Turner610e5292015-05-07 21:39:33 +0000427 WINLOG_IFANY(WINDOWS_LOG_EVENT|WINDOWS_LOG_THREAD,
428 "HandleExitProcessEvent process %I64u exited with code %u",
429 m_process.GetProcessId(), info.dwExitCode);
430
Oleksiy Vyalov9953f082015-05-15 02:05:10 +0000431 m_debug_delegate->OnExitProcess(info.dwExitCode);
Adrian McCarthy2f8e4c32015-05-18 23:24:32 +0000432
433 FreeProcessHandles();
Zachary Turner02862bc2014-11-07 23:44:13 +0000434 return DBG_CONTINUE;
435}
436
437DWORD
438DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
439{
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000440 if (info.hFile == nullptr)
441 {
442 // Not sure what this is, so just ignore it.
Zachary Turner610e5292015-05-07 21:39:33 +0000443 WINWARN_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent has a NULL file handle, returning...",
444 m_process.GetProcessId());
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000445 return DBG_CONTINUE;
446 }
447
448 std::vector<char> buffer(1);
449 DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
450 if (required_size > 0)
451 {
452 buffer.resize(required_size + 1);
453 required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS);
454 llvm::StringRef path_str(&buffer[0]);
455 const char *path = path_str.data();
456 if (path_str.startswith("\\\\?\\"))
457 path += 4;
458
459 FileSpec file_spec(path, false);
460 ModuleSpec module_spec(file_spec);
461 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll);
Zachary Turner610e5292015-05-07 21:39:33 +0000462
463 WINLOG_IFALL(WINDOWS_LOG_EVENT, "Inferior %I64u - HandleLoadDllEvent DLL '%s' loaded at address 0x%p...",
464 m_process.GetProcessId(), path, info.lpBaseOfDll);
465
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000466 m_debug_delegate->OnLoadDll(module_spec, load_addr);
467 }
468 else
469 {
Zachary Turner610e5292015-05-07 21:39:33 +0000470 WINERR_IFALL(WINDOWS_LOG_EVENT,
471 "Inferior %I64u - HandleLoadDllEvent Error %u occurred calling GetFinalPathNameByHandle",
472 m_process.GetProcessId(), ::GetLastError());
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000473 }
474 // Windows does not automatically close info.hFile, so we need to do it.
Zachary Turner02862bc2014-11-07 23:44:13 +0000475 ::CloseHandle(info.hFile);
476 return DBG_CONTINUE;
477}
478
479DWORD
480DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
481{
Zachary Turner610e5292015-05-07 21:39:33 +0000482 WINLOG_IFALL(WINDOWS_LOG_EVENT,
483 "HandleUnloadDllEvent process %I64u unloading DLL at addr 0x%p.",
484 m_process.GetProcessId(), info.lpBaseOfDll);
485
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000486 m_debug_delegate->OnUnloadDll(reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll));
Zachary Turner02862bc2014-11-07 23:44:13 +0000487 return DBG_CONTINUE;
488}
489
490DWORD
491DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id)
492{
493 return DBG_CONTINUE;
494}
495
496DWORD
497DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id)
498{
Zachary Turner610e5292015-05-07 21:39:33 +0000499 WINERR_IFALL(WINDOWS_LOG_EVENT,
500 "HandleRipEvent encountered error %u (type=%u) in process %I64u thread %u",
501 info.dwError, info.dwType, m_process.GetProcessId(), thread_id);
502
Zachary Turner02862bc2014-11-07 23:44:13 +0000503 Error error(info.dwError, eErrorTypeWin32);
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000504 m_debug_delegate->OnDebuggerError(error, info.dwType);
Zachary Turner02862bc2014-11-07 23:44:13 +0000505
506 return DBG_CONTINUE;
507}