1 //===-- ProcessWindows.cpp --------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ProcessWindows.h"
10 
11 // Windows includes
12 #include "lldb/Host/windows/windows.h"
13 #include <psapi.h>
14 
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/ModuleSpec.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Section.h"
19 #include "lldb/Host/FileSystem.h"
20 #include "lldb/Host/HostNativeProcessBase.h"
21 #include "lldb/Host/HostProcess.h"
22 #include "lldb/Host/windows/HostThreadWindows.h"
23 #include "lldb/Host/windows/windows.h"
24 #include "lldb/Symbol/ObjectFile.h"
25 #include "lldb/Target/DynamicLoader.h"
26 #include "lldb/Target/MemoryRegionInfo.h"
27 #include "lldb/Target/StopInfo.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Utility/State.h"
30 
31 #include "llvm/Support/ConvertUTF.h"
32 #include "llvm/Support/Format.h"
33 #include "llvm/Support/Threading.h"
34 #include "llvm/Support/raw_ostream.h"
35 
36 #include "DebuggerThread.h"
37 #include "ExceptionRecord.h"
38 #include "ForwardDecl.h"
39 #include "LocalDebugDelegate.h"
40 #include "ProcessWindowsLog.h"
41 #include "TargetThreadWindows.h"
42 
43 using namespace lldb;
44 using namespace lldb_private;
45 
46 namespace {
47 std::string GetProcessExecutableName(HANDLE process_handle) {
48   std::vector<wchar_t> file_name;
49   DWORD file_name_size = MAX_PATH; // first guess, not an absolute limit
50   DWORD copied = 0;
51   do {
52     file_name_size *= 2;
53     file_name.resize(file_name_size);
54     copied = ::GetModuleFileNameExW(process_handle, NULL, file_name.data(),
55                                     file_name_size);
56   } while (copied >= file_name_size);
57   file_name.resize(copied);
58   std::string result;
59   llvm::convertWideToUTF8(file_name.data(), result);
60   return result;
61 }
62 
63 std::string GetProcessExecutableName(DWORD pid) {
64   std::string file_name;
65   HANDLE process_handle =
66       ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
67   if (process_handle != NULL) {
68     file_name = GetProcessExecutableName(process_handle);
69     ::CloseHandle(process_handle);
70   }
71   return file_name;
72 }
73 } // anonymous namespace
74 
75 namespace lldb_private {
76 
77 ProcessSP ProcessWindows::CreateInstance(lldb::TargetSP target_sp,
78                                          lldb::ListenerSP listener_sp,
79                                          const FileSpec *) {
80   return ProcessSP(new ProcessWindows(target_sp, listener_sp));
81 }
82 
83 void ProcessWindows::Initialize() {
84   static llvm::once_flag g_once_flag;
85 
86   llvm::call_once(g_once_flag, []() {
87     PluginManager::RegisterPlugin(GetPluginNameStatic(),
88                                   GetPluginDescriptionStatic(), CreateInstance);
89   });
90 }
91 
92 void ProcessWindows::Terminate() {}
93 
94 lldb_private::ConstString ProcessWindows::GetPluginNameStatic() {
95   static ConstString g_name("windows");
96   return g_name;
97 }
98 
99 const char *ProcessWindows::GetPluginDescriptionStatic() {
100   return "Process plugin for Windows";
101 }
102 
103 // Constructors and destructors.
104 
105 ProcessWindows::ProcessWindows(lldb::TargetSP target_sp,
106                                lldb::ListenerSP listener_sp)
107     : lldb_private::Process(target_sp, listener_sp) {}
108 
109 ProcessWindows::~ProcessWindows() {}
110 
111 size_t ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Status &error) {
112   error.SetErrorString("GetSTDOUT unsupported on Windows");
113   return 0;
114 }
115 
116 size_t ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Status &error) {
117   error.SetErrorString("GetSTDERR unsupported on Windows");
118   return 0;
119 }
120 
121 size_t ProcessWindows::PutSTDIN(const char *buf, size_t buf_size,
122                                 Status &error) {
123   error.SetErrorString("PutSTDIN unsupported on Windows");
124   return 0;
125 }
126 
127 // ProcessInterface protocol.
128 
129 lldb_private::ConstString ProcessWindows::GetPluginName() {
130   return GetPluginNameStatic();
131 }
132 
133 uint32_t ProcessWindows::GetPluginVersion() { return 1; }
134 
135 Status ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site) {
136   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS);
137   LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site,
138            bp_site->GetID(), bp_site->GetLoadAddress());
139 
140   Status error = EnableSoftwareBreakpoint(bp_site);
141   if (!error.Success())
142     LLDB_LOG(log, "error: {0}", error);
143   return error;
144 }
145 
146 Status ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site) {
147   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_BREAKPOINTS);
148   LLDB_LOG(log, "bp_site = {0:x}, id={1}, addr={2:x}", bp_site,
149            bp_site->GetID(), bp_site->GetLoadAddress());
150 
151   Status error = DisableSoftwareBreakpoint(bp_site);
152 
153   if (!error.Success())
154     LLDB_LOG(log, "error: {0}", error);
155   return error;
156 }
157 
158 Status ProcessWindows::DoDetach(bool keep_stopped) {
159   Status error;
160   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
161   StateType private_state = GetPrivateState();
162   if (private_state != eStateExited && private_state != eStateDetached) {
163     error = DetachProcess();
164     if (error.Success())
165       SetPrivateState(eStateDetached);
166     else
167       LLDB_LOG(log, "Detaching process error: {0}", error);
168   } else {
169     error.SetErrorStringWithFormat("error: process {0} in state = {1}, but "
170                                    "cannot detach it in this state.",
171                                    GetID(), private_state);
172     LLDB_LOG(log, "error: {0}", error);
173   }
174   return error;
175 }
176 
177 Status ProcessWindows::DoLaunch(Module *exe_module,
178                                 ProcessLaunchInfo &launch_info) {
179   Status error;
180   DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
181   error = LaunchProcess(launch_info, delegate);
182   if (error.Success())
183     SetID(launch_info.GetProcessID());
184   return error;
185 }
186 
187 Status
188 ProcessWindows::DoAttachToProcessWithID(lldb::pid_t pid,
189                                         const ProcessAttachInfo &attach_info) {
190   DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
191   Status error = AttachProcess(pid, attach_info, delegate);
192   if (error.Success())
193     SetID(GetDebuggedProcessId());
194   return error;
195 }
196 
197 Status ProcessWindows::DoResume() {
198   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
199   llvm::sys::ScopedLock lock(m_mutex);
200   Status error;
201 
202   StateType private_state = GetPrivateState();
203   if (private_state == eStateStopped || private_state == eStateCrashed) {
204     LLDB_LOG(log, "process {0} is in state {1}.  Resuming...",
205              m_session_data->m_debugger->GetProcess().GetProcessId(),
206              GetPrivateState());
207 
208     ExceptionRecordSP active_exception =
209         m_session_data->m_debugger->GetActiveException().lock();
210     if (active_exception) {
211       // Resume the process and continue processing debug events.  Mask the
212       // exception so that from the process's view, there is no indication that
213       // anything happened.
214       m_session_data->m_debugger->ContinueAsyncException(
215           ExceptionResult::MaskException);
216     }
217 
218     LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize());
219 
220     bool failed = false;
221     for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
222       auto thread = std::static_pointer_cast<TargetThreadWindows>(
223           m_thread_list.GetThreadAtIndex(i));
224       Status result = thread->DoResume();
225       if (result.Fail()) {
226         failed = true;
227         LLDB_LOG(
228             log,
229             "Trying to resume thread at index {0}, but failed with error {1}.",
230             i, result);
231       }
232     }
233 
234     if (failed) {
235       error.SetErrorString("ProcessWindows::DoResume failed");
236       return error;
237     } else {
238       SetPrivateState(eStateRunning);
239     }
240   } else {
241     LLDB_LOG(log, "error: process {0} is in state {1}.  Returning...",
242              m_session_data->m_debugger->GetProcess().GetProcessId(),
243              GetPrivateState());
244   }
245   return error;
246 }
247 
248 Status ProcessWindows::DoDestroy() {
249   StateType private_state = GetPrivateState();
250   return DestroyProcess(private_state);
251 }
252 
253 Status ProcessWindows::DoHalt(bool &caused_stop) {
254   StateType state = GetPrivateState();
255   if (state != eStateStopped)
256     return HaltProcess(caused_stop);
257   caused_stop = false;
258   return Status();
259 }
260 
261 void ProcessWindows::DidLaunch() {
262   ArchSpec arch_spec;
263   DidAttach(arch_spec);
264 }
265 
266 void ProcessWindows::DidAttach(ArchSpec &arch_spec) {
267   llvm::sys::ScopedLock lock(m_mutex);
268 
269   // The initial stop won't broadcast the state change event, so account for
270   // that here.
271   if (m_session_data && GetPrivateState() == eStateStopped &&
272       m_session_data->m_stop_at_entry)
273     RefreshStateAfterStop();
274 }
275 
276 static void
277 DumpAdditionalExceptionInformation(llvm::raw_ostream &stream,
278                                    const ExceptionRecordSP &exception) {
279   // Decode additional exception information for specific exception types based
280   // on
281   // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_record
282 
283   const int addr_min_width = 2 + 8; // "0x" + 4 address bytes
284 
285   const std::vector<ULONG_PTR> &args = exception->GetExceptionArguments();
286   switch (exception->GetExceptionCode()) {
287   case EXCEPTION_ACCESS_VIOLATION: {
288     if (args.size() < 2)
289       break;
290 
291     stream << ": ";
292     const int access_violation_code = args[0];
293     const lldb::addr_t access_violation_address = args[1];
294     switch (access_violation_code) {
295     case 0:
296       stream << "Access violation reading";
297       break;
298     case 1:
299       stream << "Access violation writing";
300       break;
301     case 8:
302       stream << "User-mode data execution prevention (DEP) violation at";
303       break;
304     default:
305       stream << "Unknown access violation (code " << access_violation_code
306              << ") at";
307       break;
308     }
309     stream << " location "
310            << llvm::format_hex(access_violation_address, addr_min_width);
311     break;
312   }
313   case EXCEPTION_IN_PAGE_ERROR: {
314     if (args.size() < 3)
315       break;
316 
317     stream << ": ";
318     const int page_load_error_code = args[0];
319     const lldb::addr_t page_load_error_address = args[1];
320     const DWORD underlying_code = args[2];
321     switch (page_load_error_code) {
322     case 0:
323       stream << "In page error reading";
324       break;
325     case 1:
326       stream << "In page error writing";
327       break;
328     case 8:
329       stream << "User-mode data execution prevention (DEP) violation at";
330       break;
331     default:
332       stream << "Unknown page loading error (code " << page_load_error_code
333              << ") at";
334       break;
335     }
336     stream << " location "
337            << llvm::format_hex(page_load_error_address, addr_min_width)
338            << " (status code " << llvm::format_hex(underlying_code, 8) << ")";
339     break;
340   }
341   }
342 }
343 
344 void ProcessWindows::RefreshStateAfterStop() {
345   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION);
346   llvm::sys::ScopedLock lock(m_mutex);
347 
348   if (!m_session_data) {
349     LLDB_LOG(log, "no active session.  Returning...");
350     return;
351   }
352 
353   m_thread_list.RefreshStateAfterStop();
354 
355   std::weak_ptr<ExceptionRecord> exception_record =
356       m_session_data->m_debugger->GetActiveException();
357   ExceptionRecordSP active_exception = exception_record.lock();
358   if (!active_exception) {
359     LLDB_LOG(log,
360              "there is no active exception in process {0}.  Why is the "
361              "process stopped?",
362              m_session_data->m_debugger->GetProcess().GetProcessId());
363     return;
364   }
365 
366   StopInfoSP stop_info;
367   m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
368   ThreadSP stop_thread = m_thread_list.GetSelectedThread();
369   if (!stop_thread)
370     return;
371 
372   switch (active_exception->GetExceptionCode()) {
373   case EXCEPTION_SINGLE_STEP: {
374     RegisterContextSP register_context = stop_thread->GetRegisterContext();
375     const uint64_t pc = register_context->GetPC();
376     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
377     if (site && site->ValidForThisThread(stop_thread.get())) {
378       LLDB_LOG(log,
379                "Single-stepped onto a breakpoint in process {0} at "
380                "address {1:x} with breakpoint site {2}",
381                m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
382                site->GetID());
383       stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
384                                                                  site->GetID());
385       stop_thread->SetStopInfo(stop_info);
386     } else {
387       LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID());
388       stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
389       stop_thread->SetStopInfo(stop_info);
390     }
391     return;
392   }
393 
394   case EXCEPTION_BREAKPOINT: {
395     RegisterContextSP register_context = stop_thread->GetRegisterContext();
396 
397     // The current EIP is AFTER the BP opcode, which is one byte.
398     uint64_t pc = register_context->GetPC() - 1;
399 
400     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
401     if (site) {
402       LLDB_LOG(log,
403                "detected breakpoint in process {0} at address {1:x} with "
404                "breakpoint site {2}",
405                m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
406                site->GetID());
407 
408       if (site->ValidForThisThread(stop_thread.get())) {
409         LLDB_LOG(log,
410                  "Breakpoint site {0} is valid for this thread ({1:x}), "
411                  "creating stop info.",
412                  site->GetID(), stop_thread->GetID());
413 
414         stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
415             *stop_thread, site->GetID());
416         register_context->SetPC(pc);
417       } else {
418         LLDB_LOG(log,
419                  "Breakpoint site {0} is not valid for this thread, "
420                  "creating empty stop info.",
421                  site->GetID());
422       }
423       stop_thread->SetStopInfo(stop_info);
424       return;
425     } else {
426       // The thread hit a hard-coded breakpoint like an `int 3` or
427       // `__debugbreak()`.
428       LLDB_LOG(log,
429                "No breakpoint site matches for this thread. __debugbreak()?  "
430                "Creating stop info with the exception.");
431       // FALLTHROUGH:  We'll treat this as a generic exception record in the
432       // default case.
433       LLVM_FALLTHROUGH;
434     }
435   }
436 
437   default: {
438     std::string desc;
439     llvm::raw_string_ostream desc_stream(desc);
440     desc_stream << "Exception "
441                 << llvm::format_hex(active_exception->GetExceptionCode(), 8)
442                 << " encountered at address "
443                 << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
444     DumpAdditionalExceptionInformation(desc_stream, active_exception);
445 
446     stop_info = StopInfo::CreateStopReasonWithException(
447         *stop_thread, desc_stream.str().c_str());
448     stop_thread->SetStopInfo(stop_info);
449     LLDB_LOG(log, "{0}", desc_stream.str());
450     return;
451   }
452   }
453 }
454 
455 bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
456                               bool plugin_specified_by_name) {
457   if (plugin_specified_by_name)
458     return true;
459 
460   // For now we are just making sure the file exists for a given module
461   ModuleSP exe_module_sp(target_sp->GetExecutableModule());
462   if (exe_module_sp.get())
463     return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());
464   // However, if there is no executable module, we return true since we might
465   // be preparing to attach.
466   return true;
467 }
468 
469 bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list,
470                                       ThreadList &new_thread_list) {
471   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_THREAD);
472   // Add all the threads that were previously running and for which we did not
473   // detect a thread exited event.
474   int new_size = 0;
475   int continued_threads = 0;
476   int exited_threads = 0;
477   int new_threads = 0;
478 
479   for (ThreadSP old_thread : old_thread_list.Threads()) {
480     lldb::tid_t old_thread_id = old_thread->GetID();
481     auto exited_thread_iter =
482         m_session_data->m_exited_threads.find(old_thread_id);
483     if (exited_thread_iter == m_session_data->m_exited_threads.end()) {
484       new_thread_list.AddThread(old_thread);
485       ++new_size;
486       ++continued_threads;
487       LLDB_LOGV(log, "Thread {0} was running and is still running.",
488                 old_thread_id);
489     } else {
490       LLDB_LOGV(log, "Thread {0} was running and has exited.", old_thread_id);
491       ++exited_threads;
492     }
493   }
494 
495   // Also add all the threads that are new since the last time we broke into
496   // the debugger.
497   for (const auto &thread_info : m_session_data->m_new_threads) {
498     ThreadSP thread(new TargetThreadWindows(*this, thread_info.second));
499     thread->SetID(thread_info.first);
500     new_thread_list.AddThread(thread);
501     ++new_size;
502     ++new_threads;
503     LLDB_LOGV(log, "Thread {0} is new since last update.", thread_info.first);
504   }
505 
506   LLDB_LOG(log, "{0} new threads, {1} old threads, {2} exited threads.",
507            new_threads, continued_threads, exited_threads);
508 
509   m_session_data->m_new_threads.clear();
510   m_session_data->m_exited_threads.clear();
511 
512   return new_size > 0;
513 }
514 
515 bool ProcessWindows::IsAlive() {
516   StateType state = GetPrivateState();
517   switch (state) {
518   case eStateCrashed:
519   case eStateDetached:
520   case eStateUnloaded:
521   case eStateExited:
522   case eStateInvalid:
523     return false;
524   default:
525     return true;
526   }
527 }
528 
529 size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,
530                                     size_t size, Status &error) {
531   size_t bytes_read = 0;
532   error = ProcessDebugger::ReadMemory(vm_addr, buf, size, bytes_read);
533   return bytes_read;
534 }
535 
536 size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
537                                      size_t size, Status &error) {
538   size_t bytes_written = 0;
539   error = ProcessDebugger::WriteMemory(vm_addr, buf, size, bytes_written);
540   return bytes_written;
541 }
542 
543 lldb::addr_t ProcessWindows::DoAllocateMemory(size_t size, uint32_t permissions,
544                                               Status &error) {
545   lldb::addr_t vm_addr = LLDB_INVALID_ADDRESS;
546   error = ProcessDebugger::AllocateMemory(size, permissions, vm_addr);
547   return vm_addr;
548 }
549 
550 Status ProcessWindows::DoDeallocateMemory(lldb::addr_t ptr) {
551   return ProcessDebugger::DeallocateMemory(ptr);
552 }
553 
554 Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
555                                            MemoryRegionInfo &info) {
556   return ProcessDebugger::GetMemoryRegionInfo(vm_addr, info);
557 }
558 
559 lldb::addr_t ProcessWindows::GetImageInfoAddress() {
560   Target &target = GetTarget();
561   ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();
562   Address addr = obj_file->GetImageInfoAddress(&target);
563   if (addr.IsValid())
564     return addr.GetLoadAddress(&target);
565   else
566     return LLDB_INVALID_ADDRESS;
567 }
568 
569 DynamicLoaderWindowsDYLD *ProcessWindows::GetDynamicLoader() {
570   if (m_dyld_up.get() == NULL)
571     m_dyld_up.reset(DynamicLoader::FindPlugin(
572         this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString()));
573   return static_cast<DynamicLoaderWindowsDYLD *>(m_dyld_up.get());
574 }
575 
576 void ProcessWindows::OnExitProcess(uint32_t exit_code) {
577   // No need to acquire the lock since m_session_data isn't accessed.
578   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
579   LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
580 
581   TargetSP target = CalculateTarget();
582   if (target) {
583     ModuleSP executable_module = target->GetExecutableModule();
584     ModuleList unloaded_modules;
585     unloaded_modules.Append(executable_module);
586     target->ModulesDidUnload(unloaded_modules, true);
587   }
588 
589   SetProcessExitStatus(GetID(), true, 0, exit_code);
590   SetPrivateState(eStateExited);
591 
592   // If the process exits before any initial stop then notify the debugger
593   // of the error otherwise WaitForDebuggerConnection() will be blocked.
594   // An example of this issue is when a process fails to load a dependent DLL.
595   if (m_session_data && !m_session_data->m_initial_stop_received) {
596     Status error(exit_code, eErrorTypeWin32);
597     OnDebuggerError(error, 0);
598   }
599 
600   // Reset the session.
601   m_session_data.reset();
602 }
603 
604 void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
605   DebuggerThreadSP debugger = m_session_data->m_debugger;
606   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
607   LLDB_LOG(log, "Debugger connected to process {0}.  Image base = {1:x}",
608            debugger->GetProcess().GetProcessId(), image_base);
609 
610   ModuleSP module = GetTarget().GetExecutableModule();
611   if (!module) {
612     // During attach, we won't have the executable module, so find it now.
613     const DWORD pid = debugger->GetProcess().GetProcessId();
614     const std::string file_name = GetProcessExecutableName(pid);
615     if (file_name.empty()) {
616       return;
617     }
618 
619     FileSpec executable_file(file_name);
620     FileSystem::Instance().Resolve(executable_file);
621     ModuleSpec module_spec(executable_file);
622     Status error;
623     module = GetTarget().GetOrCreateModule(module_spec,
624                                            true /* notify */, &error);
625     if (!module) {
626       return;
627     }
628 
629     GetTarget().SetExecutableModule(module, eLoadDependentsNo);
630   }
631 
632   if (auto dyld = GetDynamicLoader())
633     dyld->OnLoadModule(module, ModuleSpec(), image_base);
634 
635   // Add the main executable module to the list of pending module loads.  We
636   // can't call GetTarget().ModulesDidLoad() here because we still haven't
637   // returned from DoLaunch() / DoAttach() yet so the target may not have set
638   // the process instance to `this` yet.
639   llvm::sys::ScopedLock lock(m_mutex);
640   const HostThreadWindows &wmain_thread =
641       debugger->GetMainThread().GetNativeThread();
642   m_session_data->m_new_threads[wmain_thread.GetThreadId()] =
643       debugger->GetMainThread();
644 }
645 
646 ExceptionResult
647 ProcessWindows::OnDebugException(bool first_chance,
648                                  const ExceptionRecord &record) {
649   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION);
650   llvm::sys::ScopedLock lock(m_mutex);
651 
652   // FIXME: Without this check, occasionally when running the test suite there
653   // is
654   // an issue where m_session_data can be null.  It's not clear how this could
655   // happen but it only surfaces while running the test suite.  In order to
656   // properly diagnose this, we probably need to first figure allow the test
657   // suite to print out full lldb logs, and then add logging to the process
658   // plugin.
659   if (!m_session_data) {
660     LLDB_LOG(log,
661              "Debugger thread reported exception {0:x} at address {1:x}, "
662              "but there is no session.",
663              record.GetExceptionCode(), record.GetExceptionAddress());
664     return ExceptionResult::SendToApplication;
665   }
666 
667   if (!first_chance) {
668     // Not any second chance exception is an application crash by definition.
669     // It may be an expression evaluation crash.
670     SetPrivateState(eStateStopped);
671   }
672 
673   ExceptionResult result = ExceptionResult::SendToApplication;
674   switch (record.GetExceptionCode()) {
675   case EXCEPTION_BREAKPOINT:
676     // Handle breakpoints at the first chance.
677     result = ExceptionResult::BreakInDebugger;
678 
679     if (!m_session_data->m_initial_stop_received) {
680       LLDB_LOG(
681           log,
682           "Hit loader breakpoint at address {0:x}, setting initial stop event.",
683           record.GetExceptionAddress());
684       m_session_data->m_initial_stop_received = true;
685       ::SetEvent(m_session_data->m_initial_stop_event);
686     } else {
687       LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
688                record.GetExceptionAddress());
689     }
690     SetPrivateState(eStateStopped);
691     break;
692   case EXCEPTION_SINGLE_STEP:
693     result = ExceptionResult::BreakInDebugger;
694     SetPrivateState(eStateStopped);
695     break;
696   default:
697     LLDB_LOG(log,
698              "Debugger thread reported exception {0:x} at address {1:x} "
699              "(first_chance={2})",
700              record.GetExceptionCode(), record.GetExceptionAddress(),
701              first_chance);
702     // For non-breakpoints, give the application a chance to handle the
703     // exception first.
704     if (first_chance)
705       result = ExceptionResult::SendToApplication;
706     else
707       result = ExceptionResult::BreakInDebugger;
708   }
709 
710   return result;
711 }
712 
713 void ProcessWindows::OnCreateThread(const HostThread &new_thread) {
714   llvm::sys::ScopedLock lock(m_mutex);
715   const HostThreadWindows &wnew_thread = new_thread.GetNativeThread();
716   m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread;
717 }
718 
719 void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
720   llvm::sys::ScopedLock lock(m_mutex);
721 
722   // On a forced termination, we may get exit thread events after the session
723   // data has been cleaned up.
724   if (!m_session_data)
725     return;
726 
727   // A thread may have started and exited before the debugger stopped allowing a
728   // refresh.
729   // Just remove it from the new threads list in that case.
730   auto iter = m_session_data->m_new_threads.find(thread_id);
731   if (iter != m_session_data->m_new_threads.end())
732     m_session_data->m_new_threads.erase(iter);
733   else
734     m_session_data->m_exited_threads.insert(thread_id);
735 }
736 
737 void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
738                                lldb::addr_t module_addr) {
739   if (auto dyld = GetDynamicLoader())
740     dyld->OnLoadModule(nullptr, module_spec, module_addr);
741 }
742 
743 void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
744   if (auto dyld = GetDynamicLoader())
745     dyld->OnUnloadModule(module_addr);
746 }
747 
748 void ProcessWindows::OnDebugString(const std::string &string) {}
749 
750 void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) {
751   llvm::sys::ScopedLock lock(m_mutex);
752   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
753 
754   if (m_session_data->m_initial_stop_received) {
755     // This happened while debugging.  Do we shutdown the debugging session,
756     // try to continue, or do something else?
757     LLDB_LOG(log,
758              "Error {0} occurred during debugging.  Unexpected behavior "
759              "may result.  {1}",
760              error.GetError(), error);
761   } else {
762     // If we haven't actually launched the process yet, this was an error
763     // launching the process.  Set the internal error and signal the initial
764     // stop event so that the DoLaunch method wakes up and returns a failure.
765     m_session_data->m_launch_error = error;
766     ::SetEvent(m_session_data->m_initial_stop_event);
767     LLDB_LOG(
768         log,
769         "Error {0} occurred launching the process before the initial stop. {1}",
770         error.GetError(), error);
771     return;
772   }
773 }
774 } // namespace lldb_private
775