blob: f67438c3127a2c8ad4ea8732e44a801d8e8dcff9 [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"
16#include "lldb/Host/Predicate.h"
17#include "lldb/Host/ThisThread.h"
18#include "lldb/Host/ThreadLauncher.h"
19#include "lldb/Host/windows/HostProcessWindows.h"
20#include "lldb/Host/windows/HostThreadWindows.h"
21#include "lldb/Host/windows/ProcessLauncherWindows.h"
22#include "lldb/Target/ProcessLaunchInfo.h"
23
24#include "llvm/Support/raw_ostream.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29namespace
30{
31struct DebugLaunchContext
32{
33 DebugLaunchContext(DebuggerThread *thread, const ProcessLaunchInfo &launch_info)
34 : m_thread(thread)
35 , m_launch_info(launch_info)
36 {
37 }
38 DebuggerThread *m_thread;
39 ProcessLaunchInfo m_launch_info;
40};
41}
42
43DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
44 : m_debug_delegate(debug_delegate)
45 , m_image_file(nullptr)
Zachary Turner02862bc2014-11-07 23:44:13 +000046{
Zachary Turner02862bc2014-11-07 23:44:13 +000047}
48
49DebuggerThread::~DebuggerThread()
50{
Zachary Turner02862bc2014-11-07 23:44:13 +000051}
52
Zachary Turner3985f892014-11-10 22:32:18 +000053Error
Zachary Turner02862bc2014-11-07 23:44:13 +000054DebuggerThread::DebugLaunch(const ProcessLaunchInfo &launch_info)
55{
56 Error error;
57
58 DebugLaunchContext *context = new DebugLaunchContext(this, launch_info);
59 HostThread slave_thread(ThreadLauncher::LaunchThread("lldb.plugin.process-windows.slave[?]", DebuggerThreadRoutine, context, &error));
Zachary Turner02862bc2014-11-07 23:44:13 +000060
Zachary Turner3985f892014-11-10 22:32:18 +000061 return error;
Zachary Turner02862bc2014-11-07 23:44:13 +000062}
63
64lldb::thread_result_t
65DebuggerThread::DebuggerThreadRoutine(void *data)
66{
67 DebugLaunchContext *context = static_cast<DebugLaunchContext *>(data);
68 lldb::thread_result_t result = context->m_thread->DebuggerThreadRoutine(context->m_launch_info);
69 delete context;
70 return result;
71}
72
73lldb::thread_result_t
74DebuggerThread::DebuggerThreadRoutine(const ProcessLaunchInfo &launch_info)
75{
76 // Grab a shared_ptr reference to this so that we know it won't get deleted until after the
77 // thread routine has exited.
78 std::shared_ptr<DebuggerThread> this_ref(shared_from_this());
79 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
80
81 Error error;
82 ProcessLauncherWindows launcher;
83 HostProcess process(launcher.LaunchProcess(launch_info, error));
84 // If we couldn't create the process, notify waiters immediately. Otherwise enter the debug
85 // loop and wait until we get the create process debug notification. Note that if the process
86 // was created successfully, we can throw away the process handle we got from CreateProcess
87 // because Windows will give us another (potentially more useful?) handle when it sends us the
88 // CREATE_PROCESS_DEBUG_EVENT.
89 if (error.Success())
90 DebugLoop();
91 else
Zachary Turnerd6a7b632014-11-12 19:31:39 +000092 m_debug_delegate->OnDebuggerError(error, 0);
Zachary Turner02862bc2014-11-07 23:44:13 +000093
94 return 0;
95}
96
97void
Zachary Turnerdcd80372014-11-11 00:00:14 +000098DebuggerThread::ContinueAsyncException(ExceptionResult result)
99{
100 m_exception.SetValue(result, eBroadcastAlways);
101}
102
103void
Zachary Turner02862bc2014-11-07 23:44:13 +0000104DebuggerThread::DebugLoop()
105{
106 DEBUG_EVENT dbe = {0};
107 bool exit = false;
108 while (!exit && WaitForDebugEvent(&dbe, INFINITE))
109 {
110 DWORD continue_status = DBG_CONTINUE;
111 switch (dbe.dwDebugEventCode)
112 {
113 case EXCEPTION_DEBUG_EVENT:
Zachary Turnerdcd80372014-11-11 00:00:14 +0000114 {
115 ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
116 m_exception.SetValue(status, eBroadcastNever);
117 m_exception.WaitForValueNotEqualTo(ExceptionResult::WillHandle, status);
118
119 if (status == ExceptionResult::Handled)
120 continue_status = DBG_CONTINUE;
121 else if (status == ExceptionResult::NotHandled)
122 continue_status = DBG_EXCEPTION_NOT_HANDLED;
Zachary Turner02862bc2014-11-07 23:44:13 +0000123 break;
Zachary Turnerdcd80372014-11-11 00:00:14 +0000124 }
Zachary Turner02862bc2014-11-07 23:44:13 +0000125 case CREATE_THREAD_DEBUG_EVENT:
126 continue_status = HandleCreateThreadEvent(dbe.u.CreateThread, dbe.dwThreadId);
127 break;
128 case CREATE_PROCESS_DEBUG_EVENT:
129 continue_status = HandleCreateProcessEvent(dbe.u.CreateProcessInfo, dbe.dwThreadId);
130 break;
131 case EXIT_THREAD_DEBUG_EVENT:
132 continue_status = HandleExitThreadEvent(dbe.u.ExitThread, dbe.dwThreadId);
133 break;
134 case EXIT_PROCESS_DEBUG_EVENT:
135 continue_status = HandleExitProcessEvent(dbe.u.ExitProcess, dbe.dwThreadId);
136 exit = true;
137 break;
138 case LOAD_DLL_DEBUG_EVENT:
139 continue_status = HandleLoadDllEvent(dbe.u.LoadDll, dbe.dwThreadId);
140 break;
141 case UNLOAD_DLL_DEBUG_EVENT:
142 continue_status = HandleUnloadDllEvent(dbe.u.UnloadDll, dbe.dwThreadId);
143 break;
144 case OUTPUT_DEBUG_STRING_EVENT:
145 continue_status = HandleODSEvent(dbe.u.DebugString, dbe.dwThreadId);
146 break;
147 case RIP_EVENT:
148 continue_status = HandleRipEvent(dbe.u.RipInfo, dbe.dwThreadId);
149 if (dbe.u.RipInfo.dwType == SLE_ERROR)
150 exit = true;
151 break;
152 }
153
154 ::ContinueDebugEvent(dbe.dwProcessId, dbe.dwThreadId, continue_status);
155 }
156}
157
Zachary Turnerdcd80372014-11-11 00:00:14 +0000158ExceptionResult
Zachary Turner02862bc2014-11-07 23:44:13 +0000159DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
160{
Zachary Turnerdcd80372014-11-11 00:00:14 +0000161 bool first_chance = (info.dwFirstChance != 0);
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000162 return m_debug_delegate->OnDebugException(first_chance, ExceptionRecord(info.ExceptionRecord));
Zachary Turner02862bc2014-11-07 23:44:13 +0000163}
164
165DWORD
166DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info, DWORD thread_id)
167{
168 return DBG_CONTINUE;
169}
170
171DWORD
172DebuggerThread::HandleCreateProcessEvent(const CREATE_PROCESS_DEBUG_INFO &info, DWORD thread_id)
173{
174 std::string thread_name;
175 llvm::raw_string_ostream name_stream(thread_name);
176 name_stream << "lldb.plugin.process-windows.slave[" << m_process.GetProcessId() << "]";
177 name_stream.flush();
178 ThisThread::SetName(thread_name.c_str());
179
180 // info.hProcess and info.hThread are closed automatically by Windows when
181 // EXIT_PROCESS_DEBUG_EVENT is received.
182 m_process = HostProcess(info.hProcess);
183 ((HostProcessWindows &)m_process.GetNativeProcess()).SetOwnsHandle(false);
184 m_main_thread = HostThread(info.hThread);
185 ((HostThreadWindows &)m_main_thread.GetNativeThread()).SetOwnsHandle(false);
186 m_image_file = info.hFile;
187
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000188 m_debug_delegate->OnDebuggerConnected();
Zachary Turner02862bc2014-11-07 23:44:13 +0000189
190 return DBG_CONTINUE;
191}
192
193DWORD
194DebuggerThread::HandleExitThreadEvent(const EXIT_THREAD_DEBUG_INFO &info, DWORD thread_id)
195{
196 return DBG_CONTINUE;
197}
198
199DWORD
200DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info, DWORD thread_id)
201{
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000202 m_debug_delegate->OnExitProcess(info.dwExitCode);
Zachary Turner02862bc2014-11-07 23:44:13 +0000203
204 m_process = HostProcess();
205 m_main_thread = HostThread();
206 ::CloseHandle(m_image_file);
207 m_image_file = nullptr;
208 return DBG_CONTINUE;
209}
210
211DWORD
212DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
213{
214 // Windows does not automatically close info.hFile when the DLL is unloaded.
215 ::CloseHandle(info.hFile);
216 return DBG_CONTINUE;
217}
218
219DWORD
220DebuggerThread::HandleUnloadDllEvent(const UNLOAD_DLL_DEBUG_INFO &info, DWORD thread_id)
221{
222 return DBG_CONTINUE;
223}
224
225DWORD
226DebuggerThread::HandleODSEvent(const OUTPUT_DEBUG_STRING_INFO &info, DWORD thread_id)
227{
228 return DBG_CONTINUE;
229}
230
231DWORD
232DebuggerThread::HandleRipEvent(const RIP_INFO &info, DWORD thread_id)
233{
234 Error error(info.dwError, eErrorTypeWin32);
Zachary Turnerd6a7b632014-11-12 19:31:39 +0000235 m_debug_delegate->OnDebuggerError(error, info.dwType);
Zachary Turner02862bc2014-11-07 23:44:13 +0000236
237 return DBG_CONTINUE;
238}