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