118a9135dSAdrian McCarthy //===-- ProcessWindows.cpp --------------------------------------*- C++ -*-===//
218a9135dSAdrian McCarthy //
318a9135dSAdrian McCarthy //                     The LLVM Compiler Infrastructure
418a9135dSAdrian McCarthy //
518a9135dSAdrian McCarthy // This file is distributed under the University of Illinois Open Source
618a9135dSAdrian McCarthy // License. See LICENSE.TXT for details.
718a9135dSAdrian McCarthy //
818a9135dSAdrian McCarthy //===----------------------------------------------------------------------===//
918a9135dSAdrian McCarthy 
1018a9135dSAdrian McCarthy #include "ProcessWindows.h"
1118a9135dSAdrian McCarthy 
12*4ad5def9SAdrian McCarthy // Windows includes
13*4ad5def9SAdrian McCarthy #include "lldb/Host/windows/windows.h"
14*4ad5def9SAdrian McCarthy #include <psapi.h>
15*4ad5def9SAdrian McCarthy 
1618a9135dSAdrian McCarthy // Other libraries and framework includes
1718a9135dSAdrian McCarthy #include "lldb/Core/Module.h"
1818a9135dSAdrian McCarthy #include "lldb/Core/ModuleSpec.h"
1918a9135dSAdrian McCarthy #include "lldb/Core/PluginManager.h"
2018a9135dSAdrian McCarthy #include "lldb/Core/Section.h"
2118a9135dSAdrian McCarthy #include "lldb/Core/State.h"
22*4ad5def9SAdrian McCarthy #include "lldb/Host/HostNativeProcessBase.h"
23*4ad5def9SAdrian McCarthy #include "lldb/Host/HostProcess.h"
24*4ad5def9SAdrian McCarthy #include "lldb/Host/windows/HostThreadWindows.h"
250c35cde9SAdrian McCarthy #include "lldb/Host/windows/windows.h"
2618a9135dSAdrian McCarthy #include "lldb/Target/DynamicLoader.h"
2718a9135dSAdrian McCarthy #include "lldb/Target/MemoryRegionInfo.h"
28*4ad5def9SAdrian McCarthy #include "lldb/Target/StopInfo.h"
2918a9135dSAdrian McCarthy #include "lldb/Target/Target.h"
3018a9135dSAdrian McCarthy 
31*4ad5def9SAdrian McCarthy #include "llvm/Support/ConvertUTF.h"
32*4ad5def9SAdrian McCarthy #include "llvm/Support/Format.h"
33*4ad5def9SAdrian McCarthy #include "llvm/Support/raw_ostream.h"
34*4ad5def9SAdrian McCarthy 
35*4ad5def9SAdrian McCarthy #include "DebuggerThread.h"
36*4ad5def9SAdrian McCarthy #include "ExceptionRecord.h"
37*4ad5def9SAdrian McCarthy #include "ForwardDecl.h"
38*4ad5def9SAdrian McCarthy #include "LocalDebugDelegate.h"
39*4ad5def9SAdrian McCarthy #include "ProcessWindowsLog.h"
40*4ad5def9SAdrian McCarthy #include "TargetThreadWindows.h"
41*4ad5def9SAdrian McCarthy 
4218a9135dSAdrian McCarthy using namespace lldb;
4318a9135dSAdrian McCarthy using namespace lldb_private;
4418a9135dSAdrian McCarthy 
45*4ad5def9SAdrian McCarthy namespace {
46*4ad5def9SAdrian McCarthy std::string GetProcessExecutableName(HANDLE process_handle) {
47*4ad5def9SAdrian McCarthy   std::vector<wchar_t> file_name;
48*4ad5def9SAdrian McCarthy   DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit
49*4ad5def9SAdrian McCarthy   DWORD copied = 0;
50*4ad5def9SAdrian McCarthy   do {
51*4ad5def9SAdrian McCarthy     file_name_size *= 2;
52*4ad5def9SAdrian McCarthy     file_name.resize(file_name_size);
53*4ad5def9SAdrian McCarthy     copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(),
54*4ad5def9SAdrian McCarthy                                     file_name_size);
55*4ad5def9SAdrian McCarthy   } while (copied >= file_name_size);
56*4ad5def9SAdrian McCarthy   file_name.resize(copied);
57*4ad5def9SAdrian McCarthy   std::string result;
58*4ad5def9SAdrian McCarthy   llvm::convertWideToUTF8(file_name.data(), result);
59*4ad5def9SAdrian McCarthy   return result;
60*4ad5def9SAdrian McCarthy }
61*4ad5def9SAdrian McCarthy 
62*4ad5def9SAdrian McCarthy std::string GetProcessExecutableName(DWORD pid) {
63*4ad5def9SAdrian McCarthy   std::string file_name;
64*4ad5def9SAdrian McCarthy   HANDLE process_handle =
65*4ad5def9SAdrian McCarthy       ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
66*4ad5def9SAdrian McCarthy   if (process_handle != NULL) {
67*4ad5def9SAdrian McCarthy     file_name = GetProcessExecutableName(process_handle);
68*4ad5def9SAdrian McCarthy     ::CloseHandle(process_handle);
69*4ad5def9SAdrian McCarthy   }
70*4ad5def9SAdrian McCarthy   return file_name;
71*4ad5def9SAdrian McCarthy }
72*4ad5def9SAdrian McCarthy 
73*4ad5def9SAdrian McCarthy } // anonymous namespace
74*4ad5def9SAdrian McCarthy 
75b9c1b51eSKate Stone namespace lldb_private {
7618a9135dSAdrian McCarthy 
77*4ad5def9SAdrian McCarthy // We store a pointer to this class in the ProcessWindows, so that we don't
78*4ad5def9SAdrian McCarthy // expose Windows-specific types and implementation details from a public header
79*4ad5def9SAdrian McCarthy // file.
80*4ad5def9SAdrian McCarthy class ProcessWindowsData {
81*4ad5def9SAdrian McCarthy public:
82*4ad5def9SAdrian McCarthy   ProcessWindowsData(bool stop_at_entry) : m_stop_at_entry(stop_at_entry) {
83*4ad5def9SAdrian McCarthy     m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
84*4ad5def9SAdrian McCarthy   }
85*4ad5def9SAdrian McCarthy 
86*4ad5def9SAdrian McCarthy   ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); }
87*4ad5def9SAdrian McCarthy 
88*4ad5def9SAdrian McCarthy   Error m_launch_error;
89*4ad5def9SAdrian McCarthy   DebuggerThreadSP m_debugger;
90*4ad5def9SAdrian McCarthy   StopInfoSP m_pending_stop_info;
91*4ad5def9SAdrian McCarthy   HANDLE m_initial_stop_event = nullptr;
92*4ad5def9SAdrian McCarthy   bool m_initial_stop_received = false;
93*4ad5def9SAdrian McCarthy   bool m_stop_at_entry;
94*4ad5def9SAdrian McCarthy   std::map<lldb::tid_t, HostThread> m_new_threads;
95*4ad5def9SAdrian McCarthy   std::set<lldb::tid_t> m_exited_threads;
96*4ad5def9SAdrian McCarthy };
97*4ad5def9SAdrian McCarthy 
98*4ad5def9SAdrian McCarthy ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp,
99*4ad5def9SAdrian McCarthy                                          lldb::ListenerSP listener_sp,
100*4ad5def9SAdrian McCarthy                                          const FileSpec *) {
101*4ad5def9SAdrian McCarthy   return ProcessSP(new ProcessWindows(target_sp, listener_sp));
102*4ad5def9SAdrian McCarthy }
103*4ad5def9SAdrian McCarthy 
104*4ad5def9SAdrian McCarthy void ProcessWindows::Initialize() {
105*4ad5def9SAdrian McCarthy   static std::once_flag g_once_flag;
106*4ad5def9SAdrian McCarthy 
107*4ad5def9SAdrian McCarthy   std::call_once(g_once_flag, []() {
108*4ad5def9SAdrian McCarthy     PluginManager::RegisterPlugin(GetPluginNameStatic(),
109*4ad5def9SAdrian McCarthy                                   GetPluginDescriptionStatic(), CreateInstance);
110*4ad5def9SAdrian McCarthy   });
111*4ad5def9SAdrian McCarthy }
112*4ad5def9SAdrian McCarthy 
113*4ad5def9SAdrian McCarthy void ProcessWindows::Terminate() {}
114*4ad5def9SAdrian McCarthy 
115*4ad5def9SAdrian McCarthy lldb_private::ConstString ProcessWindows::GetPluginNameStatic() {
116*4ad5def9SAdrian McCarthy   static ConstString g_name("windows");
117*4ad5def9SAdrian McCarthy   return g_name;
118*4ad5def9SAdrian McCarthy }
119*4ad5def9SAdrian McCarthy 
120*4ad5def9SAdrian McCarthy const char *ProcessWindows::GetPluginDescriptionStatic() {
121*4ad5def9SAdrian McCarthy   return "Process plugin for Windows";
122*4ad5def9SAdrian McCarthy }
123*4ad5def9SAdrian McCarthy 
12418a9135dSAdrian McCarthy //------------------------------------------------------------------------------
12518a9135dSAdrian McCarthy // Constructors and destructors.
12618a9135dSAdrian McCarthy 
127b9c1b51eSKate Stone ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
128b9c1b51eSKate Stone                                lldb::ListenerSP listener_sp)
129b9c1b51eSKate Stone     : lldb_private::Process(target_sp, listener_sp) {}
13018a9135dSAdrian McCarthy 
131b9c1b51eSKate Stone ProcessWindows::~ProcessWindows() {}
13218a9135dSAdrian McCarthy 
133b9c1b51eSKate Stone size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error) {
13418a9135dSAdrian McCarthy   error.SetErrorString("GetSTDOUT unsupported on Windows");
13518a9135dSAdrian McCarthy   return 0;
13618a9135dSAdrian McCarthy }
13718a9135dSAdrian McCarthy 
138b9c1b51eSKate Stone size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error) {
13918a9135dSAdrian McCarthy   error.SetErrorString("GetSTDERR unsupported on Windows");
14018a9135dSAdrian McCarthy   return 0;
14118a9135dSAdrian McCarthy }
14218a9135dSAdrian McCarthy 
143b9c1b51eSKate Stone size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,
144b9c1b51eSKate Stone                                 Error &error) {
14518a9135dSAdrian McCarthy   error.SetErrorString("PutSTDIN unsupported on Windows");
14618a9135dSAdrian McCarthy   return 0;
14718a9135dSAdrian McCarthy }
14818a9135dSAdrian McCarthy 
14918a9135dSAdrian McCarthy //------------------------------------------------------------------------------
15018a9135dSAdrian McCarthy // ProcessInterface protocol.
15118a9135dSAdrian McCarthy 
152*4ad5def9SAdrian McCarthy lldb_private::ConstString ProcessWindows::GetPluginName() {
153*4ad5def9SAdrian McCarthy   return GetPluginNameStatic();
154*4ad5def9SAdrian McCarthy }
155*4ad5def9SAdrian McCarthy 
156*4ad5def9SAdrian McCarthy uint32_t ProcessWindows::GetPluginVersion() { return 1; }
157*4ad5def9SAdrian McCarthy 
158*4ad5def9SAdrian McCarthy Error ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {
159*4ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS,
160*4ad5def9SAdrian McCarthy                "EnableBreakpointSite called with bp_site 0x%p "
161*4ad5def9SAdrian McCarthy                "(id=%d, addr=0x%llx)",
162*4ad5def9SAdrian McCarthy                bp_site, bp_site->GetID(), bp_site->GetLoadAddress());
163*4ad5def9SAdrian McCarthy 
164*4ad5def9SAdrian McCarthy   Error error = EnableSoftwareBreakpoint(bp_site);
165*4ad5def9SAdrian McCarthy   if (!error.Success()) {
166*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "EnableBreakpointSite failed.  %s",
167*4ad5def9SAdrian McCarthy                  error.AsCString());
168*4ad5def9SAdrian McCarthy   }
169*4ad5def9SAdrian McCarthy   return error;
170*4ad5def9SAdrian McCarthy }
171*4ad5def9SAdrian McCarthy 
172*4ad5def9SAdrian McCarthy Error ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) {
173*4ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS,
174*4ad5def9SAdrian McCarthy                "DisableBreakpointSite called with bp_site 0x%p "
175*4ad5def9SAdrian McCarthy                "(id=%d, addr=0x%llx)",
176*4ad5def9SAdrian McCarthy                bp_site, bp_site->GetID(), bp_site->GetLoadAddress());
177*4ad5def9SAdrian McCarthy 
178*4ad5def9SAdrian McCarthy   Error error = DisableSoftwareBreakpoint(bp_site);
179*4ad5def9SAdrian McCarthy 
180*4ad5def9SAdrian McCarthy   if (!error.Success()) {
181*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_BREAKPOINTS, "DisableBreakpointSite failed.  %s",
182*4ad5def9SAdrian McCarthy                  error.AsCString());
183*4ad5def9SAdrian McCarthy   }
184*4ad5def9SAdrian McCarthy   return error;
185*4ad5def9SAdrian McCarthy }
186*4ad5def9SAdrian McCarthy 
187*4ad5def9SAdrian McCarthy Error ProcessWindows::DoDetach(bool keep_stopped) {
188*4ad5def9SAdrian McCarthy   DebuggerThreadSP debugger_thread;
189*4ad5def9SAdrian McCarthy   StateType private_state;
190*4ad5def9SAdrian McCarthy   {
191*4ad5def9SAdrian McCarthy     // Acquire the lock only long enough to get the DebuggerThread.
192*4ad5def9SAdrian McCarthy     // StopDebugging() will trigger a call back into ProcessWindows which
193*4ad5def9SAdrian McCarthy     // will also acquire the lock.  Thus we have to release the lock before
194*4ad5def9SAdrian McCarthy     // calling StopDebugging().
195*4ad5def9SAdrian McCarthy     llvm::sys::ScopedLock lock(m_mutex);
196*4ad5def9SAdrian McCarthy 
197*4ad5def9SAdrian McCarthy     private_state = GetPrivateState();
198*4ad5def9SAdrian McCarthy 
199*4ad5def9SAdrian McCarthy     if (!m_session_data) {
200*4ad5def9SAdrian McCarthy       WINWARN_IFALL(
201*4ad5def9SAdrian McCarthy           WINDOWS_LOG_PROCESS,
202*4ad5def9SAdrian McCarthy           "DoDetach called while state = %u, but there is no active session.",
203*4ad5def9SAdrian McCarthy           private_state);
204*4ad5def9SAdrian McCarthy       return Error();
205*4ad5def9SAdrian McCarthy     }
206*4ad5def9SAdrian McCarthy 
207*4ad5def9SAdrian McCarthy     debugger_thread = m_session_data->m_debugger;
208*4ad5def9SAdrian McCarthy   }
209*4ad5def9SAdrian McCarthy 
210*4ad5def9SAdrian McCarthy   Error error;
211*4ad5def9SAdrian McCarthy   if (private_state != eStateExited && private_state != eStateDetached) {
212*4ad5def9SAdrian McCarthy     WINLOG_IFALL(
213*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
214*4ad5def9SAdrian McCarthy         "DoDetach called for process %p while state = %d.  Detaching...",
215*4ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
216*4ad5def9SAdrian McCarthy         private_state);
217*4ad5def9SAdrian McCarthy     error = debugger_thread->StopDebugging(false);
218*4ad5def9SAdrian McCarthy     if (error.Success()) {
219*4ad5def9SAdrian McCarthy       SetPrivateState(eStateDetached);
220*4ad5def9SAdrian McCarthy     }
221*4ad5def9SAdrian McCarthy 
222*4ad5def9SAdrian McCarthy     // By the time StopDebugging returns, there is no more debugger thread, so
223*4ad5def9SAdrian McCarthy     // we can be assured that no other thread will race for the session data.
224*4ad5def9SAdrian McCarthy     m_session_data.reset();
225*4ad5def9SAdrian McCarthy   } else {
226*4ad5def9SAdrian McCarthy     WINERR_IFALL(
227*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS, "DoDetach called for process %p while state = "
228*4ad5def9SAdrian McCarthy                              "%d, but cannot destroy in this state.",
229*4ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
230*4ad5def9SAdrian McCarthy         private_state);
231*4ad5def9SAdrian McCarthy   }
232*4ad5def9SAdrian McCarthy 
233*4ad5def9SAdrian McCarthy   return error;
234*4ad5def9SAdrian McCarthy }
235*4ad5def9SAdrian McCarthy 
236*4ad5def9SAdrian McCarthy Error ProcessWindows::DoLaunch(Module *exe_module,
237*4ad5def9SAdrian McCarthy                                ProcessLaunchInfo &launch_info) {
238*4ad5def9SAdrian McCarthy   // Even though m_session_data is accessed here, it is before a debugger thread
239*4ad5def9SAdrian McCarthy   // has been
240*4ad5def9SAdrian McCarthy   // kicked off.  So there's no race conditions, and it shouldn't be necessary
241*4ad5def9SAdrian McCarthy   // to acquire
242*4ad5def9SAdrian McCarthy   // the mutex.
243*4ad5def9SAdrian McCarthy 
244*4ad5def9SAdrian McCarthy   Error result;
245*4ad5def9SAdrian McCarthy   if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
246*4ad5def9SAdrian McCarthy     StreamString stream;
247*4ad5def9SAdrian McCarthy     stream.Printf("ProcessWindows unable to launch '%s'.  ProcessWindows can "
248*4ad5def9SAdrian McCarthy                   "only be used for debug launches.",
249*4ad5def9SAdrian McCarthy                   launch_info.GetExecutableFile().GetPath().c_str());
250*4ad5def9SAdrian McCarthy     std::string message = stream.GetString();
251*4ad5def9SAdrian McCarthy     result.SetErrorString(message.c_str());
252*4ad5def9SAdrian McCarthy 
253*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "%s", message.c_str());
254*4ad5def9SAdrian McCarthy     return result;
255*4ad5def9SAdrian McCarthy   }
256*4ad5def9SAdrian McCarthy 
257*4ad5def9SAdrian McCarthy   bool stop_at_entry = launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
258*4ad5def9SAdrian McCarthy   m_session_data.reset(new ProcessWindowsData(stop_at_entry));
259*4ad5def9SAdrian McCarthy 
260*4ad5def9SAdrian McCarthy   SetPrivateState(eStateLaunching);
261*4ad5def9SAdrian McCarthy   DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
262*4ad5def9SAdrian McCarthy   m_session_data->m_debugger.reset(new DebuggerThread(delegate));
263*4ad5def9SAdrian McCarthy   DebuggerThreadSP debugger = m_session_data->m_debugger;
264*4ad5def9SAdrian McCarthy 
265*4ad5def9SAdrian McCarthy   // Kick off the DebugLaunch asynchronously and wait for it to complete.
266*4ad5def9SAdrian McCarthy   result = debugger->DebugLaunch(launch_info);
267*4ad5def9SAdrian McCarthy   if (result.Fail()) {
268*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'.  %s",
269*4ad5def9SAdrian McCarthy                  launch_info.GetExecutableFile().GetPath().c_str(),
270*4ad5def9SAdrian McCarthy                  result.AsCString());
271*4ad5def9SAdrian McCarthy     return result;
272*4ad5def9SAdrian McCarthy   }
273*4ad5def9SAdrian McCarthy 
274*4ad5def9SAdrian McCarthy   HostProcess process;
275*4ad5def9SAdrian McCarthy   Error error = WaitForDebuggerConnection(debugger, process);
276*4ad5def9SAdrian McCarthy   if (error.Fail()) {
277*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch failed launching '%s'.  %s",
278*4ad5def9SAdrian McCarthy                  launch_info.GetExecutableFile().GetPath().c_str(),
279*4ad5def9SAdrian McCarthy                  error.AsCString());
280*4ad5def9SAdrian McCarthy     return error;
281*4ad5def9SAdrian McCarthy   }
282*4ad5def9SAdrian McCarthy 
283*4ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoLaunch successfully launched '%s'",
284*4ad5def9SAdrian McCarthy                launch_info.GetExecutableFile().GetPath().c_str());
285*4ad5def9SAdrian McCarthy 
286*4ad5def9SAdrian McCarthy   // We've hit the initial stop.  If eLaunchFlagsStopAtEntry was specified, the
287*4ad5def9SAdrian McCarthy   // private state
288*4ad5def9SAdrian McCarthy   // should already be set to eStateStopped as a result of hitting the initial
289*4ad5def9SAdrian McCarthy   // breakpoint.  If
290*4ad5def9SAdrian McCarthy   // it was not set, the breakpoint should have already been resumed from and
291*4ad5def9SAdrian McCarthy   // the private state
292*4ad5def9SAdrian McCarthy   // should already be eStateRunning.
293*4ad5def9SAdrian McCarthy   launch_info.SetProcessID(process.GetProcessId());
294*4ad5def9SAdrian McCarthy   SetID(process.GetProcessId());
295*4ad5def9SAdrian McCarthy 
296*4ad5def9SAdrian McCarthy   return result;
297*4ad5def9SAdrian McCarthy }
298*4ad5def9SAdrian McCarthy 
299*4ad5def9SAdrian McCarthy Error ProcessWindows::DoAttachToProcessWithID(
300*4ad5def9SAdrian McCarthy     lldb::pid_t pid, const ProcessAttachInfo &attach_info) {
301*4ad5def9SAdrian McCarthy   m_session_data.reset(
302*4ad5def9SAdrian McCarthy       new ProcessWindowsData(!attach_info.GetContinueOnceAttached()));
303*4ad5def9SAdrian McCarthy 
304*4ad5def9SAdrian McCarthy   DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
305*4ad5def9SAdrian McCarthy   DebuggerThreadSP debugger(new DebuggerThread(delegate));
306*4ad5def9SAdrian McCarthy 
307*4ad5def9SAdrian McCarthy   m_session_data->m_debugger = debugger;
308*4ad5def9SAdrian McCarthy 
309*4ad5def9SAdrian McCarthy   DWORD process_id = static_cast<DWORD>(pid);
310*4ad5def9SAdrian McCarthy   Error error = debugger->DebugAttach(process_id, attach_info);
311*4ad5def9SAdrian McCarthy   if (error.Fail()) {
312*4ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an "
313*4ad5def9SAdrian McCarthy                                       "error occurred initiating the "
314*4ad5def9SAdrian McCarthy                                       "asynchronous attach.  %s",
315*4ad5def9SAdrian McCarthy                  error.AsCString());
316*4ad5def9SAdrian McCarthy     return error;
317*4ad5def9SAdrian McCarthy   }
318*4ad5def9SAdrian McCarthy 
319*4ad5def9SAdrian McCarthy   HostProcess process;
320*4ad5def9SAdrian McCarthy   error = WaitForDebuggerConnection(debugger, process);
321*4ad5def9SAdrian McCarthy   if (error.Fail()) {
322*4ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_PROCESS, "DoAttachToProcessWithID encountered an "
323*4ad5def9SAdrian McCarthy                                       "error waiting for the debugger to "
324*4ad5def9SAdrian McCarthy                                       "connect.  %s",
325*4ad5def9SAdrian McCarthy                  error.AsCString());
326*4ad5def9SAdrian McCarthy     return error;
327*4ad5def9SAdrian McCarthy   }
328*4ad5def9SAdrian McCarthy 
329*4ad5def9SAdrian McCarthy   WINLOG_IFALL(
330*4ad5def9SAdrian McCarthy       WINDOWS_LOG_PROCESS,
331*4ad5def9SAdrian McCarthy       "DoAttachToProcessWithID successfully attached to process with pid=%lu",
332*4ad5def9SAdrian McCarthy       process_id);
333*4ad5def9SAdrian McCarthy 
334*4ad5def9SAdrian McCarthy   // We've hit the initial stop.  If eLaunchFlagsStopAtEntry was specified, the
335*4ad5def9SAdrian McCarthy   // private state
336*4ad5def9SAdrian McCarthy   // should already be set to eStateStopped as a result of hitting the initial
337*4ad5def9SAdrian McCarthy   // breakpoint.  If
338*4ad5def9SAdrian McCarthy   // it was not set, the breakpoint should have already been resumed from and
339*4ad5def9SAdrian McCarthy   // the private state
340*4ad5def9SAdrian McCarthy   // should already be eStateRunning.
341*4ad5def9SAdrian McCarthy   SetID(process.GetProcessId());
342*4ad5def9SAdrian McCarthy   return error;
343*4ad5def9SAdrian McCarthy }
344*4ad5def9SAdrian McCarthy 
345*4ad5def9SAdrian McCarthy Error ProcessWindows::DoResume() {
346*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
347*4ad5def9SAdrian McCarthy   Error error;
348*4ad5def9SAdrian McCarthy 
349*4ad5def9SAdrian McCarthy   StateType private_state = GetPrivateState();
350*4ad5def9SAdrian McCarthy   if (private_state == eStateStopped || private_state == eStateCrashed) {
351*4ad5def9SAdrian McCarthy     WINLOG_IFALL(
352*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
353*4ad5def9SAdrian McCarthy         "DoResume called for process %I64u while state is %u.  Resuming...",
354*4ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetProcess().GetProcessId(),
355*4ad5def9SAdrian McCarthy         GetPrivateState());
356*4ad5def9SAdrian McCarthy 
357*4ad5def9SAdrian McCarthy     ExceptionRecordSP active_exception =
358*4ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetActiveException().lock();
359*4ad5def9SAdrian McCarthy     if (active_exception) {
360*4ad5def9SAdrian McCarthy       // Resume the process and continue processing debug events.  Mask
361*4ad5def9SAdrian McCarthy       // the exception so that from the process's view, there is no
362*4ad5def9SAdrian McCarthy       // indication that anything happened.
363*4ad5def9SAdrian McCarthy       m_session_data->m_debugger->ContinueAsyncException(
364*4ad5def9SAdrian McCarthy           ExceptionResult::MaskException);
365*4ad5def9SAdrian McCarthy     }
366*4ad5def9SAdrian McCarthy 
367*4ad5def9SAdrian McCarthy     WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_THREAD,
368*4ad5def9SAdrian McCarthy                  "DoResume resuming %u threads.", m_thread_list.GetSize());
369*4ad5def9SAdrian McCarthy 
370*4ad5def9SAdrian McCarthy     for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
371*4ad5def9SAdrian McCarthy       auto thread = std::static_pointer_cast<TargetThreadWindows>(
372*4ad5def9SAdrian McCarthy           m_thread_list.GetThreadAtIndex(i));
373*4ad5def9SAdrian McCarthy       thread->DoResume();
374*4ad5def9SAdrian McCarthy     }
375*4ad5def9SAdrian McCarthy 
376*4ad5def9SAdrian McCarthy     SetPrivateState(eStateRunning);
377*4ad5def9SAdrian McCarthy   } else {
378*4ad5def9SAdrian McCarthy     WINERR_IFALL(
379*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
380*4ad5def9SAdrian McCarthy         "DoResume called for process %I64u but state is %u.  Returning...",
381*4ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetProcess().GetProcessId(),
382*4ad5def9SAdrian McCarthy         GetPrivateState());
383*4ad5def9SAdrian McCarthy   }
384*4ad5def9SAdrian McCarthy   return error;
385*4ad5def9SAdrian McCarthy }
386*4ad5def9SAdrian McCarthy 
387*4ad5def9SAdrian McCarthy Error ProcessWindows::DoDestroy() {
388*4ad5def9SAdrian McCarthy   DebuggerThreadSP debugger_thread;
389*4ad5def9SAdrian McCarthy   StateType private_state;
390*4ad5def9SAdrian McCarthy   {
391*4ad5def9SAdrian McCarthy     // Acquire this lock inside an inner scope, only long enough to get the
392*4ad5def9SAdrian McCarthy     // DebuggerThread.
393*4ad5def9SAdrian McCarthy     // StopDebugging() will trigger a call back into ProcessWindows which will
394*4ad5def9SAdrian McCarthy     // acquire the lock
395*4ad5def9SAdrian McCarthy     // again, so we need to not deadlock.
396*4ad5def9SAdrian McCarthy     llvm::sys::ScopedLock lock(m_mutex);
397*4ad5def9SAdrian McCarthy 
398*4ad5def9SAdrian McCarthy     private_state = GetPrivateState();
399*4ad5def9SAdrian McCarthy 
400*4ad5def9SAdrian McCarthy     if (!m_session_data) {
401*4ad5def9SAdrian McCarthy       WINWARN_IFALL(
402*4ad5def9SAdrian McCarthy           WINDOWS_LOG_PROCESS,
403*4ad5def9SAdrian McCarthy           "DoDestroy called while state = %u, but there is no active session.",
404*4ad5def9SAdrian McCarthy           private_state);
405*4ad5def9SAdrian McCarthy       return Error();
406*4ad5def9SAdrian McCarthy     }
407*4ad5def9SAdrian McCarthy 
408*4ad5def9SAdrian McCarthy     debugger_thread = m_session_data->m_debugger;
409*4ad5def9SAdrian McCarthy   }
410*4ad5def9SAdrian McCarthy 
411*4ad5def9SAdrian McCarthy   Error error;
412*4ad5def9SAdrian McCarthy   if (private_state != eStateExited && private_state != eStateDetached) {
413*4ad5def9SAdrian McCarthy     WINLOG_IFALL(
414*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = "
415*4ad5def9SAdrian McCarthy                              "%u.  Shutting down...",
416*4ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
417*4ad5def9SAdrian McCarthy         private_state);
418*4ad5def9SAdrian McCarthy     error = debugger_thread->StopDebugging(true);
419*4ad5def9SAdrian McCarthy 
420*4ad5def9SAdrian McCarthy     // By the time StopDebugging returns, there is no more debugger thread, so
421*4ad5def9SAdrian McCarthy     // we can be assured that no other thread will race for the session data.
422*4ad5def9SAdrian McCarthy     m_session_data.reset();
423*4ad5def9SAdrian McCarthy   } else {
424*4ad5def9SAdrian McCarthy     WINERR_IFALL(
425*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS, "DoDestroy called for process %p while state = "
426*4ad5def9SAdrian McCarthy                              "%d, but cannot destroy in this state.",
427*4ad5def9SAdrian McCarthy         debugger_thread->GetProcess().GetNativeProcess().GetSystemHandle(),
428*4ad5def9SAdrian McCarthy         private_state);
429*4ad5def9SAdrian McCarthy   }
430*4ad5def9SAdrian McCarthy 
431*4ad5def9SAdrian McCarthy   return error;
432*4ad5def9SAdrian McCarthy }
433*4ad5def9SAdrian McCarthy 
434*4ad5def9SAdrian McCarthy Error ProcessWindows::DoHalt(bool &caused_stop) {
435*4ad5def9SAdrian McCarthy   Error error;
436*4ad5def9SAdrian McCarthy   StateType state = GetPrivateState();
437*4ad5def9SAdrian McCarthy   if (state == eStateStopped)
438*4ad5def9SAdrian McCarthy     caused_stop = false;
439*4ad5def9SAdrian McCarthy   else {
440*4ad5def9SAdrian McCarthy     llvm::sys::ScopedLock lock(m_mutex);
441*4ad5def9SAdrian McCarthy     caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess()
442*4ad5def9SAdrian McCarthy                                           .GetNativeProcess()
443*4ad5def9SAdrian McCarthy                                           .GetSystemHandle());
444*4ad5def9SAdrian McCarthy     if (!caused_stop) {
445*4ad5def9SAdrian McCarthy       error.SetError(::GetLastError(), eErrorTypeWin32);
446*4ad5def9SAdrian McCarthy       WINERR_IFALL(
447*4ad5def9SAdrian McCarthy           WINDOWS_LOG_PROCESS,
448*4ad5def9SAdrian McCarthy           "DoHalt called DebugBreakProcess, but it failed with error %u",
449*4ad5def9SAdrian McCarthy           error.GetError());
450*4ad5def9SAdrian McCarthy     }
451*4ad5def9SAdrian McCarthy   }
452*4ad5def9SAdrian McCarthy   return error;
453*4ad5def9SAdrian McCarthy }
454*4ad5def9SAdrian McCarthy 
455*4ad5def9SAdrian McCarthy void ProcessWindows::DidLaunch() {
456*4ad5def9SAdrian McCarthy   ArchSpec arch_spec;
457*4ad5def9SAdrian McCarthy   DidAttach(arch_spec);
458*4ad5def9SAdrian McCarthy }
459*4ad5def9SAdrian McCarthy 
460*4ad5def9SAdrian McCarthy void ProcessWindows::DidAttach(ArchSpec &arch_spec) {
461*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
462*4ad5def9SAdrian McCarthy 
463*4ad5def9SAdrian McCarthy   // The initial stop won't broadcast the state change event, so account for
464*4ad5def9SAdrian McCarthy   // that here.
465*4ad5def9SAdrian McCarthy   if (m_session_data && GetPrivateState() == eStateStopped &&
466*4ad5def9SAdrian McCarthy       m_session_data->m_stop_at_entry)
467*4ad5def9SAdrian McCarthy     RefreshStateAfterStop();
468*4ad5def9SAdrian McCarthy }
469*4ad5def9SAdrian McCarthy 
470*4ad5def9SAdrian McCarthy void ProcessWindows::RefreshStateAfterStop() {
471*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
472*4ad5def9SAdrian McCarthy 
473*4ad5def9SAdrian McCarthy   if (!m_session_data) {
474*4ad5def9SAdrian McCarthy     WINWARN_IFALL(
475*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
476*4ad5def9SAdrian McCarthy         "RefreshStateAfterStop called with no active session.  Returning...");
477*4ad5def9SAdrian McCarthy     return;
478*4ad5def9SAdrian McCarthy   }
479*4ad5def9SAdrian McCarthy 
480*4ad5def9SAdrian McCarthy   m_thread_list.RefreshStateAfterStop();
481*4ad5def9SAdrian McCarthy 
482*4ad5def9SAdrian McCarthy   std::weak_ptr<ExceptionRecord> exception_record =
483*4ad5def9SAdrian McCarthy       m_session_data->m_debugger->GetActiveException();
484*4ad5def9SAdrian McCarthy   ExceptionRecordSP active_exception = exception_record.lock();
485*4ad5def9SAdrian McCarthy   if (!active_exception) {
486*4ad5def9SAdrian McCarthy     WINERR_IFALL(
487*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
488*4ad5def9SAdrian McCarthy         "RefreshStateAfterStop called for process %I64u but there is no "
489*4ad5def9SAdrian McCarthy         "active exception.  Why is the process stopped?",
490*4ad5def9SAdrian McCarthy         m_session_data->m_debugger->GetProcess().GetProcessId());
491*4ad5def9SAdrian McCarthy     return;
492*4ad5def9SAdrian McCarthy   }
493*4ad5def9SAdrian McCarthy 
494*4ad5def9SAdrian McCarthy   StopInfoSP stop_info;
495*4ad5def9SAdrian McCarthy   m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
496*4ad5def9SAdrian McCarthy   ThreadSP stop_thread = m_thread_list.GetSelectedThread();
497*4ad5def9SAdrian McCarthy   if (!stop_thread)
498*4ad5def9SAdrian McCarthy     return;
499*4ad5def9SAdrian McCarthy 
500*4ad5def9SAdrian McCarthy   switch (active_exception->GetExceptionCode()) {
501*4ad5def9SAdrian McCarthy   case EXCEPTION_SINGLE_STEP: {
502*4ad5def9SAdrian McCarthy     RegisterContextSP register_context = stop_thread->GetRegisterContext();
503*4ad5def9SAdrian McCarthy     const uint64_t pc = register_context->GetPC();
504*4ad5def9SAdrian McCarthy     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
505*4ad5def9SAdrian McCarthy     if (site && site->ValidForThisThread(stop_thread.get())) {
506*4ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION |
507*4ad5def9SAdrian McCarthy                        WINDOWS_LOG_STEP,
508*4ad5def9SAdrian McCarthy                    "Single-stepped onto a breakpoint in process %I64u at "
509*4ad5def9SAdrian McCarthy                    "address 0x%I64x with breakpoint site %d",
510*4ad5def9SAdrian McCarthy                    m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
511*4ad5def9SAdrian McCarthy                    site->GetID());
512*4ad5def9SAdrian McCarthy       stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
513*4ad5def9SAdrian McCarthy                                                                  site->GetID());
514*4ad5def9SAdrian McCarthy       stop_thread->SetStopInfo(stop_info);
515*4ad5def9SAdrian McCarthy     } else {
516*4ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP,
517*4ad5def9SAdrian McCarthy                    "RefreshStateAfterStop single stepping thread %llu",
518*4ad5def9SAdrian McCarthy                    stop_thread->GetID());
519*4ad5def9SAdrian McCarthy       stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
520*4ad5def9SAdrian McCarthy       stop_thread->SetStopInfo(stop_info);
521*4ad5def9SAdrian McCarthy     }
522*4ad5def9SAdrian McCarthy     return;
523*4ad5def9SAdrian McCarthy   }
524*4ad5def9SAdrian McCarthy 
525*4ad5def9SAdrian McCarthy   case EXCEPTION_BREAKPOINT: {
526*4ad5def9SAdrian McCarthy     RegisterContextSP register_context = stop_thread->GetRegisterContext();
527*4ad5def9SAdrian McCarthy 
528*4ad5def9SAdrian McCarthy     // The current EIP is AFTER the BP opcode, which is one byte.
529*4ad5def9SAdrian McCarthy     uint64_t pc = register_context->GetPC() - 1;
530*4ad5def9SAdrian McCarthy 
531*4ad5def9SAdrian McCarthy     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
532*4ad5def9SAdrian McCarthy     if (site) {
533*4ad5def9SAdrian McCarthy       WINLOG_IFANY(
534*4ad5def9SAdrian McCarthy           WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
535*4ad5def9SAdrian McCarthy           "RefreshStateAfterStop detected breakpoint in process %I64u at "
536*4ad5def9SAdrian McCarthy           "address 0x%I64x with breakpoint site %d",
537*4ad5def9SAdrian McCarthy           m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
538*4ad5def9SAdrian McCarthy           site->GetID());
539*4ad5def9SAdrian McCarthy 
540*4ad5def9SAdrian McCarthy       if (site->ValidForThisThread(stop_thread.get())) {
541*4ad5def9SAdrian McCarthy         WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
542*4ad5def9SAdrian McCarthy                      "Breakpoint site %d is valid for this thread (0x%I64x), "
543*4ad5def9SAdrian McCarthy                      "creating stop info.",
544*4ad5def9SAdrian McCarthy                      site->GetID(), stop_thread->GetID());
545*4ad5def9SAdrian McCarthy 
546*4ad5def9SAdrian McCarthy         stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
547*4ad5def9SAdrian McCarthy             *stop_thread, site->GetID());
548*4ad5def9SAdrian McCarthy         register_context->SetPC(pc);
549*4ad5def9SAdrian McCarthy       } else {
550*4ad5def9SAdrian McCarthy         WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
551*4ad5def9SAdrian McCarthy                      "Breakpoint site %d is not valid for this thread, "
552*4ad5def9SAdrian McCarthy                      "creating empty stop info.",
553*4ad5def9SAdrian McCarthy                      site->GetID());
554*4ad5def9SAdrian McCarthy       }
555*4ad5def9SAdrian McCarthy       stop_thread->SetStopInfo(stop_info);
556*4ad5def9SAdrian McCarthy       return;
557*4ad5def9SAdrian McCarthy     } else {
558*4ad5def9SAdrian McCarthy       // The thread hit a hard-coded breakpoint like an `int 3` or
559*4ad5def9SAdrian McCarthy       // `__debugbreak()`.
560*4ad5def9SAdrian McCarthy       WINLOG_IFALL(
561*4ad5def9SAdrian McCarthy           WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
562*4ad5def9SAdrian McCarthy           "No breakpoint site matches for this thread. __debugbreak()?  "
563*4ad5def9SAdrian McCarthy           "Creating stop info with the exception.");
564*4ad5def9SAdrian McCarthy       // FALLTHROUGH:  We'll treat this as a generic exception record in the
565*4ad5def9SAdrian McCarthy       // default case.
566*4ad5def9SAdrian McCarthy     }
567*4ad5def9SAdrian McCarthy   }
568*4ad5def9SAdrian McCarthy 
569*4ad5def9SAdrian McCarthy   default: {
570*4ad5def9SAdrian McCarthy     std::string desc;
571*4ad5def9SAdrian McCarthy     llvm::raw_string_ostream desc_stream(desc);
572*4ad5def9SAdrian McCarthy     desc_stream << "Exception "
573*4ad5def9SAdrian McCarthy                 << llvm::format_hex(active_exception->GetExceptionCode(), 8)
574*4ad5def9SAdrian McCarthy                 << " encountered at address "
575*4ad5def9SAdrian McCarthy                 << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
576*4ad5def9SAdrian McCarthy     stop_info = StopInfo::CreateStopReasonWithException(
577*4ad5def9SAdrian McCarthy         *stop_thread, desc_stream.str().c_str());
578*4ad5def9SAdrian McCarthy     stop_thread->SetStopInfo(stop_info);
579*4ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, "%s", desc_stream.str().c_str());
580*4ad5def9SAdrian McCarthy     return;
581*4ad5def9SAdrian McCarthy   }
582*4ad5def9SAdrian McCarthy   }
583*4ad5def9SAdrian McCarthy }
584*4ad5def9SAdrian McCarthy 
585*4ad5def9SAdrian McCarthy bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
586*4ad5def9SAdrian McCarthy                               bool plugin_specified_by_name) {
587*4ad5def9SAdrian McCarthy   if (plugin_specified_by_name)
588*4ad5def9SAdrian McCarthy     return true;
589*4ad5def9SAdrian McCarthy 
590*4ad5def9SAdrian McCarthy   // For now we are just making sure the file exists for a given module
591*4ad5def9SAdrian McCarthy   ModuleSP exe_module_sp(target_sp->GetExecutableModule());
592*4ad5def9SAdrian McCarthy   if (exe_module_sp.get())
593*4ad5def9SAdrian McCarthy     return exe_module_sp->GetFileSpec().Exists();
594*4ad5def9SAdrian McCarthy   // However, if there is no executable module, we return true since we might be
595*4ad5def9SAdrian McCarthy   // preparing to attach.
596*4ad5def9SAdrian McCarthy   return true;
597*4ad5def9SAdrian McCarthy }
598*4ad5def9SAdrian McCarthy 
599*4ad5def9SAdrian McCarthy bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list,
600*4ad5def9SAdrian McCarthy                                       ThreadList &new_thread_list) {
601*4ad5def9SAdrian McCarthy   // Add all the threads that were previously running and for which we did not
602*4ad5def9SAdrian McCarthy   // detect a thread exited event.
603*4ad5def9SAdrian McCarthy   int new_size = 0;
604*4ad5def9SAdrian McCarthy   int continued_threads = 0;
605*4ad5def9SAdrian McCarthy   int exited_threads = 0;
606*4ad5def9SAdrian McCarthy   int new_threads = 0;
607*4ad5def9SAdrian McCarthy 
608*4ad5def9SAdrian McCarthy   for (ThreadSP old_thread : old_thread_list.Threads()) {
609*4ad5def9SAdrian McCarthy     lldb::tid_t old_thread_id = old_thread->GetID();
610*4ad5def9SAdrian McCarthy     auto exited_thread_iter =
611*4ad5def9SAdrian McCarthy         m_session_data->m_exited_threads.find(old_thread_id);
612*4ad5def9SAdrian McCarthy     if (exited_thread_iter == m_session_data->m_exited_threads.end()) {
613*4ad5def9SAdrian McCarthy       new_thread_list.AddThread(old_thread);
614*4ad5def9SAdrian McCarthy       ++new_size;
615*4ad5def9SAdrian McCarthy       ++continued_threads;
616*4ad5def9SAdrian McCarthy       WINLOGV_IFALL(
617*4ad5def9SAdrian McCarthy           WINDOWS_LOG_THREAD,
618*4ad5def9SAdrian McCarthy           "UpdateThreadList - Thread %llu was running and is still running.",
619*4ad5def9SAdrian McCarthy           old_thread_id);
620*4ad5def9SAdrian McCarthy     } else {
621*4ad5def9SAdrian McCarthy       WINLOGV_IFALL(
622*4ad5def9SAdrian McCarthy           WINDOWS_LOG_THREAD,
623*4ad5def9SAdrian McCarthy           "UpdateThreadList - Thread %llu was running and has exited.",
624*4ad5def9SAdrian McCarthy           old_thread_id);
625*4ad5def9SAdrian McCarthy       ++exited_threads;
626*4ad5def9SAdrian McCarthy     }
627*4ad5def9SAdrian McCarthy   }
628*4ad5def9SAdrian McCarthy 
629*4ad5def9SAdrian McCarthy   // Also add all the threads that are new since the last time we broke into the
630*4ad5def9SAdrian McCarthy   // debugger.
631*4ad5def9SAdrian McCarthy   for (const auto &thread_info : m_session_data->m_new_threads) {
632*4ad5def9SAdrian McCarthy     ThreadSP thread(new TargetThreadWindows(*this, thread_info.second));
633*4ad5def9SAdrian McCarthy     thread->SetID(thread_info.first);
634*4ad5def9SAdrian McCarthy     new_thread_list.AddThread(thread);
635*4ad5def9SAdrian McCarthy     ++new_size;
636*4ad5def9SAdrian McCarthy     ++new_threads;
637*4ad5def9SAdrian McCarthy     WINLOGV_IFALL(WINDOWS_LOG_THREAD,
638*4ad5def9SAdrian McCarthy                   "UpdateThreadList - Thread %llu is new since last update.",
639*4ad5def9SAdrian McCarthy                   thread_info.first);
640*4ad5def9SAdrian McCarthy   }
641*4ad5def9SAdrian McCarthy 
642*4ad5def9SAdrian McCarthy   WINLOG_IFALL(
643*4ad5def9SAdrian McCarthy       WINDOWS_LOG_THREAD,
644*4ad5def9SAdrian McCarthy       "UpdateThreadList - %d new threads, %d old threads, %d exited threads.",
645*4ad5def9SAdrian McCarthy       new_threads, continued_threads, exited_threads);
646*4ad5def9SAdrian McCarthy 
647*4ad5def9SAdrian McCarthy   m_session_data->m_new_threads.clear();
648*4ad5def9SAdrian McCarthy   m_session_data->m_exited_threads.clear();
649*4ad5def9SAdrian McCarthy 
650*4ad5def9SAdrian McCarthy   return new_size > 0;
651*4ad5def9SAdrian McCarthy }
652*4ad5def9SAdrian McCarthy 
653*4ad5def9SAdrian McCarthy bool ProcessWindows::IsAlive() {
654*4ad5def9SAdrian McCarthy   StateType state = GetPrivateState();
655*4ad5def9SAdrian McCarthy   switch (state) {
656*4ad5def9SAdrian McCarthy   case eStateCrashed:
657*4ad5def9SAdrian McCarthy   case eStateDetached:
658*4ad5def9SAdrian McCarthy   case eStateUnloaded:
659*4ad5def9SAdrian McCarthy   case eStateExited:
660*4ad5def9SAdrian McCarthy   case eStateInvalid:
661*4ad5def9SAdrian McCarthy     return false;
662*4ad5def9SAdrian McCarthy   default:
663*4ad5def9SAdrian McCarthy     return true;
664*4ad5def9SAdrian McCarthy   }
665*4ad5def9SAdrian McCarthy }
666*4ad5def9SAdrian McCarthy 
667*4ad5def9SAdrian McCarthy size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,
668*4ad5def9SAdrian McCarthy                                     size_t size, Error &error) {
669*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
670*4ad5def9SAdrian McCarthy 
671*4ad5def9SAdrian McCarthy   if (!m_session_data)
672*4ad5def9SAdrian McCarthy     return 0;
673*4ad5def9SAdrian McCarthy 
674*4ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_MEMORY,
675*4ad5def9SAdrian McCarthy                "DoReadMemory attempting to read %u bytes from address 0x%I64x",
676*4ad5def9SAdrian McCarthy                size, vm_addr);
677*4ad5def9SAdrian McCarthy 
678*4ad5def9SAdrian McCarthy   HostProcess process = m_session_data->m_debugger->GetProcess();
679*4ad5def9SAdrian McCarthy   void *addr = reinterpret_cast<void *>(vm_addr);
680*4ad5def9SAdrian McCarthy   SIZE_T bytes_read = 0;
681*4ad5def9SAdrian McCarthy   if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr,
682*4ad5def9SAdrian McCarthy                          buf, size, &bytes_read)) {
683*4ad5def9SAdrian McCarthy     error.SetError(GetLastError(), eErrorTypeWin32);
684*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_MEMORY, "DoReadMemory failed with error code %u",
685*4ad5def9SAdrian McCarthy                  error.GetError());
686*4ad5def9SAdrian McCarthy   }
687*4ad5def9SAdrian McCarthy   return bytes_read;
688*4ad5def9SAdrian McCarthy }
689*4ad5def9SAdrian McCarthy 
690*4ad5def9SAdrian McCarthy size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
691*4ad5def9SAdrian McCarthy                                      size_t size, Error &error) {
692*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
693*4ad5def9SAdrian McCarthy   WINLOG_IFALL(
694*4ad5def9SAdrian McCarthy       WINDOWS_LOG_MEMORY,
695*4ad5def9SAdrian McCarthy       "DoWriteMemory attempting to write %u bytes into address 0x%I64x", size,
696*4ad5def9SAdrian McCarthy       vm_addr);
697*4ad5def9SAdrian McCarthy 
698*4ad5def9SAdrian McCarthy   if (!m_session_data) {
699*4ad5def9SAdrian McCarthy     WINERR_IFANY(
700*4ad5def9SAdrian McCarthy         WINDOWS_LOG_MEMORY,
701*4ad5def9SAdrian McCarthy         "DoWriteMemory cannot write, there is no active debugger connection.");
702*4ad5def9SAdrian McCarthy     return 0;
703*4ad5def9SAdrian McCarthy   }
704*4ad5def9SAdrian McCarthy 
705*4ad5def9SAdrian McCarthy   HostProcess process = m_session_data->m_debugger->GetProcess();
706*4ad5def9SAdrian McCarthy   void *addr = reinterpret_cast<void *>(vm_addr);
707*4ad5def9SAdrian McCarthy   SIZE_T bytes_written = 0;
708*4ad5def9SAdrian McCarthy   lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
709*4ad5def9SAdrian McCarthy   if (WriteProcessMemory(handle, addr, buf, size, &bytes_written))
710*4ad5def9SAdrian McCarthy     FlushInstructionCache(handle, addr, bytes_written);
711*4ad5def9SAdrian McCarthy   else {
712*4ad5def9SAdrian McCarthy     error.SetError(GetLastError(), eErrorTypeWin32);
713*4ad5def9SAdrian McCarthy     WINLOG_IFALL(WINDOWS_LOG_MEMORY, "DoWriteMemory failed with error code %u",
714*4ad5def9SAdrian McCarthy                  error.GetError());
715*4ad5def9SAdrian McCarthy   }
716*4ad5def9SAdrian McCarthy   return bytes_written;
717*4ad5def9SAdrian McCarthy }
718*4ad5def9SAdrian McCarthy 
719*4ad5def9SAdrian McCarthy #define BOOL_STR(b) ((b) ? "true" : "false")
720*4ad5def9SAdrian McCarthy 
721*4ad5def9SAdrian McCarthy Error ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
722*4ad5def9SAdrian McCarthy                                           MemoryRegionInfo &info) {
723*4ad5def9SAdrian McCarthy   Error error;
724*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
725*4ad5def9SAdrian McCarthy   info.Clear();
726*4ad5def9SAdrian McCarthy 
727*4ad5def9SAdrian McCarthy   if (!m_session_data) {
728*4ad5def9SAdrian McCarthy     error.SetErrorString(
729*4ad5def9SAdrian McCarthy         "GetMemoryRegionInfo called with no debugging session.");
730*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString());
731*4ad5def9SAdrian McCarthy     return error;
732*4ad5def9SAdrian McCarthy   }
733*4ad5def9SAdrian McCarthy   HostProcess process = m_session_data->m_debugger->GetProcess();
734*4ad5def9SAdrian McCarthy   lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
735*4ad5def9SAdrian McCarthy   if (handle == nullptr || handle == LLDB_INVALID_PROCESS) {
736*4ad5def9SAdrian McCarthy     error.SetErrorString(
737*4ad5def9SAdrian McCarthy         "GetMemoryRegionInfo called with an invalid target process.");
738*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_MEMORY, "%s", error.AsCString());
739*4ad5def9SAdrian McCarthy     return error;
740*4ad5def9SAdrian McCarthy   }
741*4ad5def9SAdrian McCarthy 
742*4ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_MEMORY,
743*4ad5def9SAdrian McCarthy                "GetMemoryRegionInfo getting info for address 0x%I64x", vm_addr);
744*4ad5def9SAdrian McCarthy 
745*4ad5def9SAdrian McCarthy   void *addr = reinterpret_cast<void *>(vm_addr);
746*4ad5def9SAdrian McCarthy   MEMORY_BASIC_INFORMATION mem_info = {};
747*4ad5def9SAdrian McCarthy   SIZE_T result = ::VirtualQueryEx(handle, addr, &mem_info, sizeof(mem_info));
748*4ad5def9SAdrian McCarthy   if (result == 0) {
749*4ad5def9SAdrian McCarthy     if (::GetLastError() == ERROR_INVALID_PARAMETER) {
750*4ad5def9SAdrian McCarthy       // ERROR_INVALID_PARAMETER is returned if VirtualQueryEx is called with an
751*4ad5def9SAdrian McCarthy       // address
752*4ad5def9SAdrian McCarthy       // past the highest accessible address. We should return a range from the
753*4ad5def9SAdrian McCarthy       // vm_addr
754*4ad5def9SAdrian McCarthy       // to LLDB_INVALID_ADDRESS
755*4ad5def9SAdrian McCarthy       info.GetRange().SetRangeBase(vm_addr);
756*4ad5def9SAdrian McCarthy       info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
757*4ad5def9SAdrian McCarthy       info.SetReadable(MemoryRegionInfo::eNo);
758*4ad5def9SAdrian McCarthy       info.SetExecutable(MemoryRegionInfo::eNo);
759*4ad5def9SAdrian McCarthy       info.SetWritable(MemoryRegionInfo::eNo);
760*4ad5def9SAdrian McCarthy       info.SetMapped(MemoryRegionInfo::eNo);
761*4ad5def9SAdrian McCarthy       return error;
762*4ad5def9SAdrian McCarthy     } else {
763*4ad5def9SAdrian McCarthy       error.SetError(::GetLastError(), eErrorTypeWin32);
764*4ad5def9SAdrian McCarthy       WINERR_IFALL(WINDOWS_LOG_MEMORY, "VirtualQueryEx returned error %u while "
765*4ad5def9SAdrian McCarthy                                        "getting memory region info for address "
766*4ad5def9SAdrian McCarthy                                        "0x%I64x",
767*4ad5def9SAdrian McCarthy                    error.GetError(), vm_addr);
768*4ad5def9SAdrian McCarthy       return error;
769*4ad5def9SAdrian McCarthy     }
770*4ad5def9SAdrian McCarthy   }
771*4ad5def9SAdrian McCarthy 
772*4ad5def9SAdrian McCarthy   // Protect bits are only valid for MEM_COMMIT regions.
773*4ad5def9SAdrian McCarthy   if (mem_info.State == MEM_COMMIT) {
774*4ad5def9SAdrian McCarthy     const bool readable = IsPageReadable(mem_info.Protect);
775*4ad5def9SAdrian McCarthy     const bool executable = IsPageExecutable(mem_info.Protect);
776*4ad5def9SAdrian McCarthy     const bool writable = IsPageWritable(mem_info.Protect);
777*4ad5def9SAdrian McCarthy     info.SetReadable(readable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
778*4ad5def9SAdrian McCarthy     info.SetExecutable(executable ? MemoryRegionInfo::eYes
779*4ad5def9SAdrian McCarthy                                   : MemoryRegionInfo::eNo);
780*4ad5def9SAdrian McCarthy     info.SetWritable(writable ? MemoryRegionInfo::eYes : MemoryRegionInfo::eNo);
781*4ad5def9SAdrian McCarthy   } else {
782*4ad5def9SAdrian McCarthy     info.SetReadable(MemoryRegionInfo::eNo);
783*4ad5def9SAdrian McCarthy     info.SetExecutable(MemoryRegionInfo::eNo);
784*4ad5def9SAdrian McCarthy     info.SetWritable(MemoryRegionInfo::eNo);
785*4ad5def9SAdrian McCarthy   }
786*4ad5def9SAdrian McCarthy 
787*4ad5def9SAdrian McCarthy   // AllocationBase is defined for MEM_COMMIT and MEM_RESERVE but not MEM_FREE.
788*4ad5def9SAdrian McCarthy   if (mem_info.State != MEM_FREE) {
789*4ad5def9SAdrian McCarthy     info.GetRange().SetRangeBase(
790*4ad5def9SAdrian McCarthy         reinterpret_cast<addr_t>(mem_info.AllocationBase));
791*4ad5def9SAdrian McCarthy     info.GetRange().SetRangeEnd(reinterpret_cast<addr_t>(mem_info.BaseAddress) +
792*4ad5def9SAdrian McCarthy                                 mem_info.RegionSize);
793*4ad5def9SAdrian McCarthy     info.SetMapped(MemoryRegionInfo::eYes);
794*4ad5def9SAdrian McCarthy   } else {
795*4ad5def9SAdrian McCarthy     // In the unmapped case we need to return the distance to the next block of
796*4ad5def9SAdrian McCarthy     // memory.
797*4ad5def9SAdrian McCarthy     // VirtualQueryEx nearly does that except that it gives the distance from
798*4ad5def9SAdrian McCarthy     // the start
799*4ad5def9SAdrian McCarthy     // of the page containing vm_addr.
800*4ad5def9SAdrian McCarthy     SYSTEM_INFO data;
801*4ad5def9SAdrian McCarthy     GetSystemInfo(&data);
802*4ad5def9SAdrian McCarthy     DWORD page_offset = vm_addr % data.dwPageSize;
803*4ad5def9SAdrian McCarthy     info.GetRange().SetRangeBase(vm_addr);
804*4ad5def9SAdrian McCarthy     info.GetRange().SetByteSize(mem_info.RegionSize - page_offset);
805*4ad5def9SAdrian McCarthy     info.SetMapped(MemoryRegionInfo::eNo);
806*4ad5def9SAdrian McCarthy   }
807*4ad5def9SAdrian McCarthy 
808*4ad5def9SAdrian McCarthy   error.SetError(::GetLastError(), eErrorTypeWin32);
809*4ad5def9SAdrian McCarthy   WINLOGV_IFALL(WINDOWS_LOG_MEMORY, "Memory region info for address %llu: "
810*4ad5def9SAdrian McCarthy                                     "readable=%s, executable=%s, writable=%s",
811*4ad5def9SAdrian McCarthy                 vm_addr, BOOL_STR(info.GetReadable()),
812*4ad5def9SAdrian McCarthy                 BOOL_STR(info.GetExecutable()), BOOL_STR(info.GetWritable()));
813*4ad5def9SAdrian McCarthy   return error;
814*4ad5def9SAdrian McCarthy }
815*4ad5def9SAdrian McCarthy 
816b9c1b51eSKate Stone lldb::addr_t ProcessWindows::GetImageInfoAddress() {
81718a9135dSAdrian McCarthy   Target &target = GetTarget();
81818a9135dSAdrian McCarthy   ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();
81918a9135dSAdrian McCarthy   Address addr = obj_file->GetImageInfoAddress(&target);
82018a9135dSAdrian McCarthy   if (addr.IsValid())
82118a9135dSAdrian McCarthy     return addr.GetLoadAddress(&target);
82218a9135dSAdrian McCarthy   else
82318a9135dSAdrian McCarthy     return LLDB_INVALID_ADDRESS;
82418a9135dSAdrian McCarthy }
82518a9135dSAdrian McCarthy 
826*4ad5def9SAdrian McCarthy void ProcessWindows::OnExitProcess(uint32_t exit_code) {
827*4ad5def9SAdrian McCarthy   // No need to acquire the lock since m_session_data isn't accessed.
828*4ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_PROCESS, "Process %llu exited with code %u", GetID(),
829*4ad5def9SAdrian McCarthy                exit_code);
830*4ad5def9SAdrian McCarthy 
831*4ad5def9SAdrian McCarthy   TargetSP target = m_target_sp.lock();
832*4ad5def9SAdrian McCarthy   if (target) {
833*4ad5def9SAdrian McCarthy     ModuleSP executable_module = target->GetExecutableModule();
834*4ad5def9SAdrian McCarthy     ModuleList unloaded_modules;
835*4ad5def9SAdrian McCarthy     unloaded_modules.Append(executable_module);
836*4ad5def9SAdrian McCarthy     target->ModulesDidUnload(unloaded_modules, true);
837*4ad5def9SAdrian McCarthy   }
838*4ad5def9SAdrian McCarthy 
839*4ad5def9SAdrian McCarthy   SetProcessExitStatus(GetID(), true, 0, exit_code);
840*4ad5def9SAdrian McCarthy   SetPrivateState(eStateExited);
841*4ad5def9SAdrian McCarthy }
842*4ad5def9SAdrian McCarthy 
843*4ad5def9SAdrian McCarthy void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
844*4ad5def9SAdrian McCarthy   DebuggerThreadSP debugger = m_session_data->m_debugger;
845*4ad5def9SAdrian McCarthy 
846*4ad5def9SAdrian McCarthy   WINLOG_IFALL(WINDOWS_LOG_PROCESS,
847*4ad5def9SAdrian McCarthy                "Debugger connected to process %I64u.  Image base = 0x%I64x",
848*4ad5def9SAdrian McCarthy                debugger->GetProcess().GetProcessId(), image_base);
849*4ad5def9SAdrian McCarthy 
850*4ad5def9SAdrian McCarthy   ModuleSP module = GetTarget().GetExecutableModule();
851*4ad5def9SAdrian McCarthy   if (!module) {
852*4ad5def9SAdrian McCarthy     // During attach, we won't have the executable module, so find it now.
853*4ad5def9SAdrian McCarthy     const DWORD pid = debugger->GetProcess().GetProcessId();
854*4ad5def9SAdrian McCarthy     const std::string file_name = GetProcessExecutableName(pid);
855*4ad5def9SAdrian McCarthy     if (file_name.empty()) {
856*4ad5def9SAdrian McCarthy       return;
857*4ad5def9SAdrian McCarthy     }
858*4ad5def9SAdrian McCarthy 
859*4ad5def9SAdrian McCarthy     FileSpec executable_file(file_name, true);
860*4ad5def9SAdrian McCarthy     ModuleSpec module_spec(executable_file);
861*4ad5def9SAdrian McCarthy     Error error;
862*4ad5def9SAdrian McCarthy     module = GetTarget().GetSharedModule(module_spec, &error);
863*4ad5def9SAdrian McCarthy     if (!module) {
864*4ad5def9SAdrian McCarthy       return;
865*4ad5def9SAdrian McCarthy     }
866*4ad5def9SAdrian McCarthy 
867*4ad5def9SAdrian McCarthy     GetTarget().SetExecutableModule(module, false);
868*4ad5def9SAdrian McCarthy   }
869*4ad5def9SAdrian McCarthy 
870*4ad5def9SAdrian McCarthy   bool load_addr_changed;
871*4ad5def9SAdrian McCarthy   module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed);
872*4ad5def9SAdrian McCarthy 
873*4ad5def9SAdrian McCarthy   ModuleList loaded_modules;
874*4ad5def9SAdrian McCarthy   loaded_modules.Append(module);
875*4ad5def9SAdrian McCarthy   GetTarget().ModulesDidLoad(loaded_modules);
876*4ad5def9SAdrian McCarthy 
877*4ad5def9SAdrian McCarthy   // Add the main executable module to the list of pending module loads.  We
878*4ad5def9SAdrian McCarthy   // can't call
879*4ad5def9SAdrian McCarthy   // GetTarget().ModulesDidLoad() here because we still haven't returned from
880*4ad5def9SAdrian McCarthy   // DoLaunch() / DoAttach() yet
881*4ad5def9SAdrian McCarthy   // so the target may not have set the process instance to `this` yet.
882*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
883*4ad5def9SAdrian McCarthy   const HostThreadWindows &wmain_thread =
884*4ad5def9SAdrian McCarthy       debugger->GetMainThread().GetNativeThread();
885*4ad5def9SAdrian McCarthy   m_session_data->m_new_threads[wmain_thread.GetThreadId()] =
886*4ad5def9SAdrian McCarthy       debugger->GetMainThread();
887*4ad5def9SAdrian McCarthy }
888*4ad5def9SAdrian McCarthy 
889*4ad5def9SAdrian McCarthy ExceptionResult
890*4ad5def9SAdrian McCarthy ProcessWindows::OnDebugException(bool first_chance,
891*4ad5def9SAdrian McCarthy                                  const ExceptionRecord &record) {
892*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
893*4ad5def9SAdrian McCarthy 
894*4ad5def9SAdrian McCarthy   // FIXME: Without this check, occasionally when running the test suite there
895*4ad5def9SAdrian McCarthy   // is
896*4ad5def9SAdrian McCarthy   // an issue where m_session_data can be null.  It's not clear how this could
897*4ad5def9SAdrian McCarthy   // happen
898*4ad5def9SAdrian McCarthy   // but it only surfaces while running the test suite.  In order to properly
899*4ad5def9SAdrian McCarthy   // diagnose
900*4ad5def9SAdrian McCarthy   // this, we probably need to first figure allow the test suite to print out
901*4ad5def9SAdrian McCarthy   // full
902*4ad5def9SAdrian McCarthy   // lldb logs, and then add logging to the process plugin.
903*4ad5def9SAdrian McCarthy   if (!m_session_data) {
904*4ad5def9SAdrian McCarthy     WINERR_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception "
905*4ad5def9SAdrian McCarthy                                         "0x%lx at address 0x%llu, but there is "
906*4ad5def9SAdrian McCarthy                                         "no session.",
907*4ad5def9SAdrian McCarthy                  record.GetExceptionCode(), record.GetExceptionAddress());
908*4ad5def9SAdrian McCarthy     return ExceptionResult::SendToApplication;
909*4ad5def9SAdrian McCarthy   }
910*4ad5def9SAdrian McCarthy 
911*4ad5def9SAdrian McCarthy   if (!first_chance) {
912*4ad5def9SAdrian McCarthy     // Any second chance exception is an application crash by definition.
913*4ad5def9SAdrian McCarthy     SetPrivateState(eStateCrashed);
914*4ad5def9SAdrian McCarthy   }
915*4ad5def9SAdrian McCarthy 
916*4ad5def9SAdrian McCarthy   ExceptionResult result = ExceptionResult::SendToApplication;
917*4ad5def9SAdrian McCarthy   switch (record.GetExceptionCode()) {
918*4ad5def9SAdrian McCarthy   case EXCEPTION_BREAKPOINT:
919*4ad5def9SAdrian McCarthy     // Handle breakpoints at the first chance.
920*4ad5def9SAdrian McCarthy     result = ExceptionResult::BreakInDebugger;
921*4ad5def9SAdrian McCarthy 
922*4ad5def9SAdrian McCarthy     if (!m_session_data->m_initial_stop_received) {
923*4ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS, "Hit loader breakpoint at address "
924*4ad5def9SAdrian McCarthy                                             "0x%I64x, setting initial stop "
925*4ad5def9SAdrian McCarthy                                             "event.",
926*4ad5def9SAdrian McCarthy                    record.GetExceptionAddress());
927*4ad5def9SAdrian McCarthy       m_session_data->m_initial_stop_received = true;
928*4ad5def9SAdrian McCarthy       ::SetEvent(m_session_data->m_initial_stop_event);
929*4ad5def9SAdrian McCarthy     } else {
930*4ad5def9SAdrian McCarthy       WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS,
931*4ad5def9SAdrian McCarthy                    "Hit non-loader breakpoint at address 0x%I64x.",
932*4ad5def9SAdrian McCarthy                    record.GetExceptionAddress());
933*4ad5def9SAdrian McCarthy     }
934*4ad5def9SAdrian McCarthy     SetPrivateState(eStateStopped);
935*4ad5def9SAdrian McCarthy     break;
936*4ad5def9SAdrian McCarthy   case EXCEPTION_SINGLE_STEP:
937*4ad5def9SAdrian McCarthy     result = ExceptionResult::BreakInDebugger;
938*4ad5def9SAdrian McCarthy     SetPrivateState(eStateStopped);
939*4ad5def9SAdrian McCarthy     break;
940*4ad5def9SAdrian McCarthy   default:
941*4ad5def9SAdrian McCarthy     WINLOG_IFANY(WINDOWS_LOG_EXCEPTION, "Debugger thread reported exception "
942*4ad5def9SAdrian McCarthy                                         "0x%lx at address 0x%llx "
943*4ad5def9SAdrian McCarthy                                         "(first_chance=%s)",
944*4ad5def9SAdrian McCarthy                  record.GetExceptionCode(), record.GetExceptionAddress(),
945*4ad5def9SAdrian McCarthy                  BOOL_STR(first_chance));
946*4ad5def9SAdrian McCarthy     // For non-breakpoints, give the application a chance to handle the
947*4ad5def9SAdrian McCarthy     // exception first.
948*4ad5def9SAdrian McCarthy     if (first_chance)
949*4ad5def9SAdrian McCarthy       result = ExceptionResult::SendToApplication;
950*4ad5def9SAdrian McCarthy     else
951*4ad5def9SAdrian McCarthy       result = ExceptionResult::BreakInDebugger;
952*4ad5def9SAdrian McCarthy   }
953*4ad5def9SAdrian McCarthy 
954*4ad5def9SAdrian McCarthy   return result;
955*4ad5def9SAdrian McCarthy }
956*4ad5def9SAdrian McCarthy 
957*4ad5def9SAdrian McCarthy void ProcessWindows::OnCreateThread(const HostThread &new_thread) {
958*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
959*4ad5def9SAdrian McCarthy   const HostThreadWindows &wnew_thread = new_thread.GetNativeThread();
960*4ad5def9SAdrian McCarthy   m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread;
961*4ad5def9SAdrian McCarthy }
962*4ad5def9SAdrian McCarthy 
963*4ad5def9SAdrian McCarthy void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
964*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
965*4ad5def9SAdrian McCarthy 
966*4ad5def9SAdrian McCarthy   // On a forced termination, we may get exit thread events after the session
967*4ad5def9SAdrian McCarthy   // data has been cleaned up.
968*4ad5def9SAdrian McCarthy   if (!m_session_data)
969*4ad5def9SAdrian McCarthy     return;
970*4ad5def9SAdrian McCarthy 
971*4ad5def9SAdrian McCarthy   // A thread may have started and exited before the debugger stopped allowing a
972*4ad5def9SAdrian McCarthy   // refresh.
973*4ad5def9SAdrian McCarthy   // Just remove it from the new threads list in that case.
974*4ad5def9SAdrian McCarthy   auto iter = m_session_data->m_new_threads.find(thread_id);
975*4ad5def9SAdrian McCarthy   if (iter != m_session_data->m_new_threads.end())
976*4ad5def9SAdrian McCarthy     m_session_data->m_new_threads.erase(iter);
977*4ad5def9SAdrian McCarthy   else
978*4ad5def9SAdrian McCarthy     m_session_data->m_exited_threads.insert(thread_id);
979*4ad5def9SAdrian McCarthy }
980*4ad5def9SAdrian McCarthy 
981*4ad5def9SAdrian McCarthy void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
982*4ad5def9SAdrian McCarthy                                lldb::addr_t module_addr) {
983*4ad5def9SAdrian McCarthy   // Confusingly, there is no Target::AddSharedModule.  Instead, calling
984*4ad5def9SAdrian McCarthy   // GetSharedModule() with
985*4ad5def9SAdrian McCarthy   // a new module will add it to the module list and return a corresponding
986*4ad5def9SAdrian McCarthy   // ModuleSP.
987*4ad5def9SAdrian McCarthy   Error error;
988*4ad5def9SAdrian McCarthy   ModuleSP module = GetTarget().GetSharedModule(module_spec, &error);
989*4ad5def9SAdrian McCarthy   bool load_addr_changed = false;
990*4ad5def9SAdrian McCarthy   module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed);
991*4ad5def9SAdrian McCarthy 
992*4ad5def9SAdrian McCarthy   ModuleList loaded_modules;
993*4ad5def9SAdrian McCarthy   loaded_modules.Append(module);
994*4ad5def9SAdrian McCarthy   GetTarget().ModulesDidLoad(loaded_modules);
995*4ad5def9SAdrian McCarthy }
996*4ad5def9SAdrian McCarthy 
997*4ad5def9SAdrian McCarthy void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
998*4ad5def9SAdrian McCarthy   Address resolved_addr;
999*4ad5def9SAdrian McCarthy   if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr)) {
1000*4ad5def9SAdrian McCarthy     ModuleSP module = resolved_addr.GetModule();
1001*4ad5def9SAdrian McCarthy     if (module) {
1002*4ad5def9SAdrian McCarthy       ModuleList unloaded_modules;
1003*4ad5def9SAdrian McCarthy       unloaded_modules.Append(module);
1004*4ad5def9SAdrian McCarthy       GetTarget().ModulesDidUnload(unloaded_modules, false);
1005*4ad5def9SAdrian McCarthy     }
1006*4ad5def9SAdrian McCarthy   }
1007*4ad5def9SAdrian McCarthy }
1008*4ad5def9SAdrian McCarthy 
1009*4ad5def9SAdrian McCarthy void ProcessWindows::OnDebugString(const std::string &string) {}
1010*4ad5def9SAdrian McCarthy 
1011*4ad5def9SAdrian McCarthy void ProcessWindows::OnDebuggerError(const Error &error, uint32_t type) {
1012*4ad5def9SAdrian McCarthy   llvm::sys::ScopedLock lock(m_mutex);
1013*4ad5def9SAdrian McCarthy 
1014*4ad5def9SAdrian McCarthy   if (m_session_data->m_initial_stop_received) {
1015*4ad5def9SAdrian McCarthy     // This happened while debugging.  Do we shutdown the debugging session, try
1016*4ad5def9SAdrian McCarthy     // to continue,
1017*4ad5def9SAdrian McCarthy     // or do something else?
1018*4ad5def9SAdrian McCarthy     WINERR_IFALL(WINDOWS_LOG_PROCESS, "Error %u occurred during debugging.  "
1019*4ad5def9SAdrian McCarthy                                       "Unexpected behavior may result.  %s",
1020*4ad5def9SAdrian McCarthy                  error.GetError(), error.AsCString());
1021*4ad5def9SAdrian McCarthy   } else {
1022*4ad5def9SAdrian McCarthy     // If we haven't actually launched the process yet, this was an error
1023*4ad5def9SAdrian McCarthy     // launching the
1024*4ad5def9SAdrian McCarthy     // process.  Set the internal error and signal the initial stop event so
1025*4ad5def9SAdrian McCarthy     // that the DoLaunch
1026*4ad5def9SAdrian McCarthy     // method wakes up and returns a failure.
1027*4ad5def9SAdrian McCarthy     m_session_data->m_launch_error = error;
1028*4ad5def9SAdrian McCarthy     ::SetEvent(m_session_data->m_initial_stop_event);
1029*4ad5def9SAdrian McCarthy     WINERR_IFALL(
1030*4ad5def9SAdrian McCarthy         WINDOWS_LOG_PROCESS,
1031*4ad5def9SAdrian McCarthy         "Error %u occurred launching the process before the initial stop.  %s",
1032*4ad5def9SAdrian McCarthy         error.GetError(), error.AsCString());
1033*4ad5def9SAdrian McCarthy     return;
1034*4ad5def9SAdrian McCarthy   }
1035*4ad5def9SAdrian McCarthy }
1036*4ad5def9SAdrian McCarthy 
1037*4ad5def9SAdrian McCarthy Error ProcessWindows::WaitForDebuggerConnection(DebuggerThreadSP debugger,
1038*4ad5def9SAdrian McCarthy                                                 HostProcess &process) {
1039*4ad5def9SAdrian McCarthy   Error result;
1040*4ad5def9SAdrian McCarthy   WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS,
1041*4ad5def9SAdrian McCarthy                "WaitForDebuggerConnection Waiting for loader breakpoint.");
1042*4ad5def9SAdrian McCarthy 
1043*4ad5def9SAdrian McCarthy   // Block this function until we receive the initial stop from the process.
1044*4ad5def9SAdrian McCarthy   if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) ==
1045*4ad5def9SAdrian McCarthy       WAIT_OBJECT_0) {
1046*4ad5def9SAdrian McCarthy     WINLOG_IFANY(WINDOWS_LOG_PROCESS | WINDOWS_LOG_BREAKPOINTS,
1047*4ad5def9SAdrian McCarthy                  "WaitForDebuggerConnection hit loader breakpoint, returning.");
1048*4ad5def9SAdrian McCarthy 
1049*4ad5def9SAdrian McCarthy     process = debugger->GetProcess();
1050*4ad5def9SAdrian McCarthy     return m_session_data->m_launch_error;
1051*4ad5def9SAdrian McCarthy   } else
1052*4ad5def9SAdrian McCarthy     return Error(::GetLastError(), eErrorTypeWin32);
1053*4ad5def9SAdrian McCarthy }
1054*4ad5def9SAdrian McCarthy 
1055b9c1b51eSKate Stone // The Windows page protection bits are NOT independent masks that can be
1056*4ad5def9SAdrian McCarthy // bitwise-ORed together.  For example, PAGE_EXECUTE_READ is not
1057*4ad5def9SAdrian McCarthy // (PAGE_EXECUTE | PAGE_READ).  To test for an access type, it's necessary to
1058*4ad5def9SAdrian McCarthy // test for any of the bits that provide that access type.
1059b9c1b51eSKate Stone bool ProcessWindows::IsPageReadable(uint32_t protect) {
10600c35cde9SAdrian McCarthy   return (protect & PAGE_NOACCESS) == 0;
10610c35cde9SAdrian McCarthy }
10620c35cde9SAdrian McCarthy 
1063b9c1b51eSKate Stone bool ProcessWindows::IsPageWritable(uint32_t protect) {
1064b9c1b51eSKate Stone   return (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY |
1065b9c1b51eSKate Stone                      PAGE_READWRITE | PAGE_WRITECOPY)) != 0;
10660c35cde9SAdrian McCarthy }
10670c35cde9SAdrian McCarthy 
1068b9c1b51eSKate Stone bool ProcessWindows::IsPageExecutable(uint32_t protect) {
1069b9c1b51eSKate Stone   return (protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE |
1070b9c1b51eSKate Stone                      PAGE_EXECUTE_WRITECOPY)) != 0;
10710c35cde9SAdrian McCarthy }
1072*4ad5def9SAdrian McCarthy 
1073*4ad5def9SAdrian McCarthy } // namespace lldb_private
1074