blob: df75bf722063d5dd4b0231dd810588c71c3aefc0 [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"
25
Zachary Turnera32d2ce2014-11-12 19:31:56 +000026#include "llvm/ADT/STLExtras.h"
Zachary Turner02862bc2014-11-07 23:44:13 +000027#include "llvm/Support/raw_ostream.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
32namespace
33{
34struct DebugLaunchContext
35{
36 DebugLaunchContext(DebuggerThread *thread, const ProcessLaunchInfo &launch_info)
37 : m_thread(thread)
38 , m_launch_info(launch_info)
39 {
40 }
41 DebuggerThread *m_thread;
42 ProcessLaunchInfo m_launch_info;
43};
44}
45
46DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
47 : m_debug_delegate(debug_delegate)
48 , m_image_file(nullptr)
Zachary Turner02862bc2014-11-07 23:44:13 +000049{
Zachary Turner02862bc2014-11-07 23:44:13 +000050}
51
52DebuggerThread::~DebuggerThread()
53{
Zachary Turner02862bc2014-11-07 23:44:13 +000054}
55
Zachary Turner3985f892014-11-10 22:32:18 +000056Error
Zachary Turner02862bc2014-11-07 23:44:13 +000057DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info)
58{
59 Error error;
60
61 DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
62 HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebuggerThreadRoutine, context, &error));
Zachary Turner02862bc2014-11-07 23:44:13 +000063
Zachary Turner3985f892014-11-10 22:32:18 +000064 return error;
Zachary Turner02862bc2014-11-07 23:44:13 +000065}
66
67lldb::thread_result_t
68DebuggerThread::DebuggerThreadRoutine(void *data)
69{
70 DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
71 lldb::thread_result_t result = context->m_thread->DebuggerThreadRoutine(context->m_launch_info);
72 delete context;
73 return result;
74}
75
76lldb::thread_result_t
77DebuggerThread::DebuggerThreadRoutine(const ProcessLaunchInfo &launch_info)
78{
79 // Grab a shared_ptr reference to this so that we know it won't get deleted until after the
80 // thread routine has exited.
81 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
Zachary Turner02862bc2014-11-07 23:44:13 +000082
83 Error error;
84 ProcessLauncherWindows launcher;
85 HostProcess process(launcher.LaunchProcess(launch_info, error));
86 // If we couldn't create the process, notify waiters immediately. Otherwise enter the debug
87 // loop and wait until we get the create process debug notification. Note that if the process
88 // was created successfully, we can throw away the process handle we got from CreateProcess
89 // because Windows will give us another (potentially more useful?) handle when it sends us the
90 // CREATE_PROCESS_DEBUG_EVENT.
91 if (error.Success())
92 DebugLoop();
93 else
Zachary Turnerd6a7b632014-11-12 19:31:39 +000094 m_debug_delegate->OnDebuggerError(error, 0);
Zachary Turner02862bc2014-11-07 23:44:13 +000095
96 return 0;
97}
98
Zachary Turnerc6a66532014-12-03 22:04:18 +000099Error
100DebuggerThread::StopDebugging(bool terminate)
101{
102 Error error;
103
104 if (terminate)
105 {
106 // Make a copy of the process, since the termination sequence will reset DebuggerThread's
107 // internal copy and it needs to remain open for us to perform the Wait operation.
108 HostProcess process_copy = m_process;
109 lldb::process_t handle = process_copy.GetNativeProcess().GetSystemHandle();
110
111 // Initiate the termination before continuing the exception, so that the next debug event
112 // we get is the exit process event, and not some other event.
113 BOOL terminate_suceeded = TerminateProcess(handle, 0);
114
115 // If we're stuck waiting for an exception to continue, continue it now. But only
116 // AFTER setting the termination event, to make sure that we don't race and enter
117 // another wait for another debug event.
118 if (m_active_exception.get())
119 ContinueAsyncException(ExceptionResult::MaskException);
120
121 // Don't return until the process has exited.
122 if (terminate_suceeded)
123 {
124 DWORD wait_result = ::WaitForSingleObject(handle, 5000);
125 if (wait_result != WAIT_OBJECT_0)
126 terminate_suceeded = false;
127 }
128
129 if (!terminate_suceeded)
130 error.SetError(GetLastError(), eErrorTypeWin32);
131 }
132 else
133 {
134 error.SetErrorString("Detach not yet supported on Windows.");
135 // TODO: Implement detach.
136 }
137 return error;
138}
139
Zachary Turner02862bc2014-11-07 23:44:13 +0000140void
Zachary Turnerdcd80372014-11-11 00:00:14 +0000141DebuggerThread::ContinueAsyncException(ExceptionResult result)
142{
Zachary Turnerc6a66532014-12-03 22:04:18 +0000143 if (!m_active_exception.get())
144 return;
145
146 m_active_exception.reset();
147 m_exception_pred.SetValue(result, eBroadcastAlways);
148}
149
150void
151DebuggerThread::FreeProcessHandles()
152{
153 m_process = HostProcess();
154 m_main_thread = HostThread();
155 if (m_image_file)
156 {
157 ::CloseHandle(m_image_file);
158 m_image_file = nullptr;
159 }
Zachary Turnerdcd80372014-11-11 00:00:14 +0000160}
161
162void
Zachary Turner02862bc2014-11-07 23:44:13 +0000163DebuggerThread::DebugLoop()
164{
165 DEBUG_EVENT dbe = {0};
Zachary Turnerbe5e1e52014-12-04 22:07:02 +0000166 bool should_debug = true;
167 while (should_debug && WaitForDebugEvent(&dbe, INFINITE))
Zachary Turner02862bc2014-11-07 23:44:13 +0000168 {
169 DWORD continue_status = DBG_CONTINUE;
170 switch (dbe.dwDebugEventCode)
171 {
172 case EXCEPTION_DEBUG_EVENT:
Zachary Turnerdcd80372014-11-11 00:00:14 +0000173 {
174 ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
Zachary Turnerdcd80372014-11-11 00:00:14 +0000175
Zachary Turner10196952014-11-17 21:31:30 +0000176 if (status == ExceptionResult::MaskException)
Zachary Turnerdcd80372014-11-11 00:00:14 +0000177 continue_status = DBG_CONTINUE;
Zachary Turner10196952014-11-17 21:31:30 +0000178 else if (status == ExceptionResult::SendToApplication)
Zachary Turnerdcd80372014-11-11 00:00:14 +0000179 continue_status = DBG_EXCEPTION_NOT_HANDLED;
Zachary Turner02862bc2014-11-07 23:44:13 +0000180 break;
Zachary Turnerdcd80372014-11-11 00:00:14 +0000181 }
Zachary Turner02862bc2014-11-07 23:44:13 +0000182 case CREATE_THREAD_DEBUG_EVENT:
183 continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
184 break;
185 case CREATE_PROCESS_DEBUG_EVENT:
186 continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId);
187 break;
188 case EXIT_THREAD_DEBUG_EVENT:
189 continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId);
190 break;
191 case EXIT_PROCESS_DEBUG_EVENT:
192 continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000193 should_debug = false;
Zachary Turner02862bc2014-11-07 23:44:13 +0000194 break;
195 case LOAD_DLL_DEBUG_EVENT:
196 continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId);
197 break;
198 case UNLOAD_DLL_DEBUG_EVENT:
199 continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId);
200 break;
201 case OUTPUT_DEBUG_STRING_EVENT:
202 continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId);
203 break;
204 case RIP_EVENT:
205 continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId);
206 if (dbe.u.RipInfo.dwType == SLE_ERROR)
Zachary Turnerc6a66532014-12-03 22:04:18 +0000207 should_debug = false;
Zachary Turner02862bc2014-11-07 23:44:13 +0000208 break;
209 }
210
211 ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);
212 }
Zachary Turnerc6a66532014-12-03 22:04:18 +0000213 FreeProcessHandles();
Zachary Turner02862bc2014-11-07 23:44:13 +0000214}
215
Zachary Turnerdcd80372014-11-11 00:00:14 +0000216ExceptionResult
Zachary Turner02862bc2014-11-07 23:44:13 +0000217DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
218{
Zachary Turnerdcd80372014-11-11 00:00:14 +0000219 bool first_chance = (info.dwFirstChance != 0);
Zachary Turnerc6a66532014-12-03 22:04:18 +0000220
221 m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord));
222
223 ExceptionResult result = m_debug_delegate->OnDebugException(first_chance, *m_active_exception);
224 m_exception_pred.SetValue(result, eBroadcastNever);
225 m_exception_pred.WaitForValueNotEqualTo(ExceptionResult::BreakInDebugger, result);
226
227 return result;
Zachary Turner02862bc2014-11-07 23:44:13 +0000228}
229
230DWORD
231DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id)
232{
233 return DBG_CONTINUE;
234}
235
236DWORD
237DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id)
238{
239 std::string thread_name;
240 llvm::raw_string_ostream name_stream(thread_name);
241 name_stream << "lldb.plugin.process-windows.slave[" << m_process.GetProcessId() << "]";
242 name_stream.flush();
243 ThisThread::SetName(thread_name.c_str());
244
245 // info.hProcess and info.hThread are closed automatically by Windows when
246 // EXIT_PROCESS_DEBUG_EVENT is received.
247 m_process = HostProcess(info.hProcess);
248 ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false);
249 m_main_thread = HostThread(info.hThread);
Zachary Turnerc3018992014-11-17 22:42:57 +0000250 m_main_thread.GetNativeThread().SetOwnsHandle(false);
Zachary Turner02862bc2014-11-07 23:44:13 +0000251 m_image_file = info.hFile;
252
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000253 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfImage);
254 m_debug_delegate->OnDebuggerConnected(load_addr);
Zachary Turner02862bc2014-11-07 23:44:13 +0000255
256 return DBG_CONTINUE;
257}
258
259DWORD
260DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id)
261{
262 return DBG_CONTINUE;
263}
264
265DWORD
266DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id)
267{
Zachary Turnerc6a66532014-12-03 22:04:18 +0000268 FreeProcessHandles();
Zachary Turner02862bc2014-11-07 23:44:13 +0000269
Zachary Turnerc6a66532014-12-03 22:04:18 +0000270 m_debug_delegate->OnExitProcess(info.dwExitCode);
Zachary Turner02862bc2014-11-07 23:44:13 +0000271 return DBG_CONTINUE;
272}
273
274DWORD
275DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
276{
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000277 if (info.hFile == nullptr)
278 {
279 // Not sure what this is, so just ignore it.
280 return DBG_CONTINUE;
281 }
282
283 std::vector<char> buffer(1);
284 DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
285 if (required_size > 0)
286 {
287 buffer.resize(required_size + 1);
288 required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS);
289 llvm::StringRef path_str(&buffer[0]);
290 const char *path = path_str.data();
291 if (path_str.startswith("\\\\?\\"))
292 path += 4;
293
294 FileSpec file_spec(path, false);
295 ModuleSpec module_spec(file_spec);
296 lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll);
297 m_debug_delegate->OnLoadDll(module_spec, load_addr);
298 }
299 else
300 {
301 // An unknown error occurred getting the path name.
302 }
303 // Windows does not automatically close info.hFile, so we need to do it.
Zachary Turner02862bc2014-11-07 23:44:13 +0000304 ::CloseHandle(info.hFile);
305 return DBG_CONTINUE;
306}
307
308DWORD
309DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
310{
Zachary Turnera32d2ce2014-11-12 19:31:56 +0000311 m_debug_delegate->OnUnloadDll(reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll));
Zachary Turner02862bc2014-11-07 23:44:13 +0000312 return DBG_CONTINUE;
313}
314
315DWORD
316DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id)
317{
318 return DBG_CONTINUE;
319}
320
321DWORD
322DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id)
323{
324 Error error(info.dwError, eErrorTypeWin32);
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000325 m_debug_delegate->OnDebuggerError(error, info.dwType);
Zachary Turner02862bc2014-11-07 23:44:13 +0000326
327 return DBG_CONTINUE;
328}