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     LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize());
209 
210     bool failed = false;
211     for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
212       auto thread = std::static_pointer_cast<TargetThreadWindows>(
213           m_thread_list.GetThreadAtIndex(i));
214       Status result = thread->DoResume();
215       if (result.Fail()) {
216         failed = true;
217         LLDB_LOG(
218             log,
219             "Trying to resume thread at index {0}, but failed with error {1}.",
220             i, result);
221       }
222     }
223 
224     if (failed) {
225       error.SetErrorString("ProcessWindows::DoResume failed");
226     } else {
227       SetPrivateState(eStateRunning);
228     }
229 
230     ExceptionRecordSP active_exception =
231         m_session_data->m_debugger->GetActiveException().lock();
232     if (active_exception) {
233       // Resume the process and continue processing debug events.  Mask the
234       // exception so that from the process's view, there is no indication that
235       // anything happened.
236       m_session_data->m_debugger->ContinueAsyncException(
237           ExceptionResult::MaskException);
238     }
239   } else {
240     LLDB_LOG(log, "error: process {0} is in state {1}.  Returning...",
241              m_session_data->m_debugger->GetProcess().GetProcessId(),
242              GetPrivateState());
243   }
244   return error;
245 }
246 
247 Status ProcessWindows::DoDestroy() {
248   StateType private_state = GetPrivateState();
249   return DestroyProcess(private_state);
250 }
251 
252 Status ProcessWindows::DoHalt(bool &caused_stop) {
253   StateType state = GetPrivateState();
254   if (state != eStateStopped)
255     return HaltProcess(caused_stop);
256   caused_stop = false;
257   return Status();
258 }
259 
260 void ProcessWindows::DidLaunch() {
261   ArchSpec arch_spec;
262   DidAttach(arch_spec);
263 }
264 
265 void ProcessWindows::DidAttach(ArchSpec &arch_spec) {
266   llvm::sys::ScopedLock lock(m_mutex);
267 
268   // The initial stop won't broadcast the state change event, so account for
269   // that here.
270   if (m_session_data && GetPrivateState() == eStateStopped &&
271       m_session_data->m_stop_at_entry)
272     RefreshStateAfterStop();
273 }
274 
275 static void
276 DumpAdditionalExceptionInformation(llvm::raw_ostream &stream,
277                                    const ExceptionRecordSP &exception) {
278   // Decode additional exception information for specific exception types based
279   // on
280   // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_record
281 
282   const int addr_min_width = 2 + 8; // "0x" + 4 address bytes
283 
284   const std::vector<ULONG_PTR> &args = exception->GetExceptionArguments();
285   switch (exception->GetExceptionCode()) {
286   case EXCEPTION_ACCESS_VIOLATION: {
287     if (args.size() < 2)
288       break;
289 
290     stream << ": ";
291     const int access_violation_code = args[0];
292     const lldb::addr_t access_violation_address = args[1];
293     switch (access_violation_code) {
294     case 0:
295       stream << "Access violation reading";
296       break;
297     case 1:
298       stream << "Access violation writing";
299       break;
300     case 8:
301       stream << "User-mode data execution prevention (DEP) violation at";
302       break;
303     default:
304       stream << "Unknown access violation (code " << access_violation_code
305              << ") at";
306       break;
307     }
308     stream << " location "
309            << llvm::format_hex(access_violation_address, addr_min_width);
310     break;
311   }
312   case EXCEPTION_IN_PAGE_ERROR: {
313     if (args.size() < 3)
314       break;
315 
316     stream << ": ";
317     const int page_load_error_code = args[0];
318     const lldb::addr_t page_load_error_address = args[1];
319     const DWORD underlying_code = args[2];
320     switch (page_load_error_code) {
321     case 0:
322       stream << "In page error reading";
323       break;
324     case 1:
325       stream << "In page error writing";
326       break;
327     case 8:
328       stream << "User-mode data execution prevention (DEP) violation at";
329       break;
330     default:
331       stream << "Unknown page loading error (code " << page_load_error_code
332              << ") at";
333       break;
334     }
335     stream << " location "
336            << llvm::format_hex(page_load_error_address, addr_min_width)
337            << " (status code " << llvm::format_hex(underlying_code, 8) << ")";
338     break;
339   }
340   }
341 }
342 
343 void ProcessWindows::RefreshStateAfterStop() {
344   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION);
345   llvm::sys::ScopedLock lock(m_mutex);
346 
347   if (!m_session_data) {
348     LLDB_LOG(log, "no active session.  Returning...");
349     return;
350   }
351 
352   m_thread_list.RefreshStateAfterStop();
353 
354   std::weak_ptr<ExceptionRecord> exception_record =
355       m_session_data->m_debugger->GetActiveException();
356   ExceptionRecordSP active_exception = exception_record.lock();
357   if (!active_exception) {
358     LLDB_LOG(log,
359              "there is no active exception in process {0}.  Why is the "
360              "process stopped?",
361              m_session_data->m_debugger->GetProcess().GetProcessId());
362     return;
363   }
364 
365   StopInfoSP stop_info;
366   m_thread_list.SetSelectedThreadByID(active_exception->GetThreadID());
367   ThreadSP stop_thread = m_thread_list.GetSelectedThread();
368   if (!stop_thread)
369     return;
370 
371   switch (active_exception->GetExceptionCode()) {
372   case EXCEPTION_SINGLE_STEP: {
373     RegisterContextSP register_context = stop_thread->GetRegisterContext();
374     const uint64_t pc = register_context->GetPC();
375     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
376     if (site && site->ValidForThisThread(stop_thread.get())) {
377       LLDB_LOG(log,
378                "Single-stepped onto a breakpoint in process {0} at "
379                "address {1:x} with breakpoint site {2}",
380                m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
381                site->GetID());
382       stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread,
383                                                                  site->GetID());
384       stop_thread->SetStopInfo(stop_info);
385     } else {
386       LLDB_LOG(log, "single stepping thread {0}", stop_thread->GetID());
387       stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
388       stop_thread->SetStopInfo(stop_info);
389     }
390     return;
391   }
392 
393   case EXCEPTION_BREAKPOINT: {
394     RegisterContextSP register_context = stop_thread->GetRegisterContext();
395 
396     // The current EIP is AFTER the BP opcode, which is one byte.
397     uint64_t pc = register_context->GetPC() - 1;
398 
399     BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
400     if (site) {
401       LLDB_LOG(log,
402                "detected breakpoint in process {0} at address {1:x} with "
403                "breakpoint site {2}",
404                m_session_data->m_debugger->GetProcess().GetProcessId(), pc,
405                site->GetID());
406 
407       if (site->ValidForThisThread(stop_thread.get())) {
408         LLDB_LOG(log,
409                  "Breakpoint site {0} is valid for this thread ({1:x}), "
410                  "creating stop info.",
411                  site->GetID(), stop_thread->GetID());
412 
413         stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
414             *stop_thread, site->GetID());
415         register_context->SetPC(pc);
416       } else {
417         LLDB_LOG(log,
418                  "Breakpoint site {0} is not valid for this thread, "
419                  "creating empty stop info.",
420                  site->GetID());
421       }
422       stop_thread->SetStopInfo(stop_info);
423       return;
424     } else {
425       // The thread hit a hard-coded breakpoint like an `int 3` or
426       // `__debugbreak()`.
427       LLDB_LOG(log,
428                "No breakpoint site matches for this thread. __debugbreak()?  "
429                "Creating stop info with the exception.");
430       // FALLTHROUGH:  We'll treat this as a generic exception record in the
431       // default case.
432       LLVM_FALLTHROUGH;
433     }
434   }
435 
436   default: {
437     std::string desc;
438     llvm::raw_string_ostream desc_stream(desc);
439     desc_stream << "Exception "
440                 << llvm::format_hex(active_exception->GetExceptionCode(), 8)
441                 << " encountered at address "
442                 << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
443     DumpAdditionalExceptionInformation(desc_stream, active_exception);
444 
445     stop_info = StopInfo::CreateStopReasonWithException(
446         *stop_thread, desc_stream.str().c_str());
447     stop_thread->SetStopInfo(stop_info);
448     LLDB_LOG(log, "{0}", desc_stream.str());
449     return;
450   }
451   }
452 }
453 
454 bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
455                               bool plugin_specified_by_name) {
456   if (plugin_specified_by_name)
457     return true;
458 
459   // For now we are just making sure the file exists for a given module
460   ModuleSP exe_module_sp(target_sp->GetExecutableModule());
461   if (exe_module_sp.get())
462     return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());
463   // However, if there is no executable module, we return true since we might
464   // be preparing to attach.
465   return true;
466 }
467 
468 bool ProcessWindows::UpdateThreadList(ThreadList &old_thread_list,
469                                       ThreadList &new_thread_list) {
470   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_THREAD);
471   // Add all the threads that were previously running and for which we did not
472   // detect a thread exited event.
473   int new_size = 0;
474   int continued_threads = 0;
475   int exited_threads = 0;
476   int new_threads = 0;
477 
478   for (ThreadSP old_thread : old_thread_list.Threads()) {
479     lldb::tid_t old_thread_id = old_thread->GetID();
480     auto exited_thread_iter =
481         m_session_data->m_exited_threads.find(old_thread_id);
482     if (exited_thread_iter == m_session_data->m_exited_threads.end()) {
483       new_thread_list.AddThread(old_thread);
484       ++new_size;
485       ++continued_threads;
486       LLDB_LOGV(log, "Thread {0} was running and is still running.",
487                 old_thread_id);
488     } else {
489       LLDB_LOGV(log, "Thread {0} was running and has exited.", old_thread_id);
490       ++exited_threads;
491     }
492   }
493 
494   // Also add all the threads that are new since the last time we broke into
495   // the debugger.
496   for (const auto &thread_info : m_session_data->m_new_threads) {
497     ThreadSP thread(new TargetThreadWindows(*this, thread_info.second));
498     thread->SetID(thread_info.first);
499     new_thread_list.AddThread(thread);
500     ++new_size;
501     ++new_threads;
502     LLDB_LOGV(log, "Thread {0} is new since last update.", thread_info.first);
503   }
504 
505   LLDB_LOG(log, "{0} new threads, {1} old threads, {2} exited threads.",
506            new_threads, continued_threads, exited_threads);
507 
508   m_session_data->m_new_threads.clear();
509   m_session_data->m_exited_threads.clear();
510 
511   return new_size > 0;
512 }
513 
514 bool ProcessWindows::IsAlive() {
515   StateType state = GetPrivateState();
516   switch (state) {
517   case eStateCrashed:
518   case eStateDetached:
519   case eStateUnloaded:
520   case eStateExited:
521   case eStateInvalid:
522     return false;
523   default:
524     return true;
525   }
526 }
527 
528 size_t ProcessWindows::DoReadMemory(lldb::addr_t vm_addr, void *buf,
529                                     size_t size, Status &error) {
530   size_t bytes_read = 0;
531   error = ProcessDebugger::ReadMemory(vm_addr, buf, size, bytes_read);
532   return bytes_read;
533 }
534 
535 size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
536                                      size_t size, Status &error) {
537   size_t bytes_written = 0;
538   error = ProcessDebugger::WriteMemory(vm_addr, buf, size, bytes_written);
539   return bytes_written;
540 }
541 
542 lldb::addr_t ProcessWindows::DoAllocateMemory(size_t size, uint32_t permissions,
543                                               Status &error) {
544   lldb::addr_t vm_addr = LLDB_INVALID_ADDRESS;
545   error = ProcessDebugger::AllocateMemory(size, permissions, vm_addr);
546   return vm_addr;
547 }
548 
549 Status ProcessWindows::DoDeallocateMemory(lldb::addr_t ptr) {
550   return ProcessDebugger::DeallocateMemory(ptr);
551 }
552 
553 Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
554                                            MemoryRegionInfo &info) {
555   return ProcessDebugger::GetMemoryRegionInfo(vm_addr, info);
556 }
557 
558 lldb::addr_t ProcessWindows::GetImageInfoAddress() {
559   Target &target = GetTarget();
560   ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();
561   Address addr = obj_file->GetImageInfoAddress(&target);
562   if (addr.IsValid())
563     return addr.GetLoadAddress(&target);
564   else
565     return LLDB_INVALID_ADDRESS;
566 }
567 
568 DynamicLoaderWindowsDYLD *ProcessWindows::GetDynamicLoader() {
569   if (m_dyld_up.get() == NULL)
570     m_dyld_up.reset(DynamicLoader::FindPlugin(
571         this, DynamicLoaderWindowsDYLD::GetPluginNameStatic().GetCString()));
572   return static_cast<DynamicLoaderWindowsDYLD *>(m_dyld_up.get());
573 }
574 
575 void ProcessWindows::OnExitProcess(uint32_t exit_code) {
576   // No need to acquire the lock since m_session_data isn't accessed.
577   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
578   LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
579 
580   TargetSP target = CalculateTarget();
581   if (target) {
582     ModuleSP executable_module = target->GetExecutableModule();
583     ModuleList unloaded_modules;
584     unloaded_modules.Append(executable_module);
585     target->ModulesDidUnload(unloaded_modules, true);
586   }
587 
588   SetProcessExitStatus(GetID(), true, 0, exit_code);
589   SetPrivateState(eStateExited);
590 
591   // If the process exits before any initial stop then notify the debugger
592   // of the error otherwise WaitForDebuggerConnection() will be blocked.
593   // An example of this issue is when a process fails to load a dependent DLL.
594   if (m_session_data && !m_session_data->m_initial_stop_received) {
595     Status error(exit_code, eErrorTypeWin32);
596     OnDebuggerError(error, 0);
597   }
598 
599   // Reset the session.
600   m_session_data.reset();
601 }
602 
603 void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
604   DebuggerThreadSP debugger = m_session_data->m_debugger;
605   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
606   LLDB_LOG(log, "Debugger connected to process {0}.  Image base = {1:x}",
607            debugger->GetProcess().GetProcessId(), image_base);
608 
609   ModuleSP module = GetTarget().GetExecutableModule();
610   if (!module) {
611     // During attach, we won't have the executable module, so find it now.
612     const DWORD pid = debugger->GetProcess().GetProcessId();
613     const std::string file_name = GetProcessExecutableName(pid);
614     if (file_name.empty()) {
615       return;
616     }
617 
618     FileSpec executable_file(file_name);
619     FileSystem::Instance().Resolve(executable_file);
620     ModuleSpec module_spec(executable_file);
621     Status error;
622     module = GetTarget().GetOrCreateModule(module_spec,
623                                            true /* notify */, &error);
624     if (!module) {
625       return;
626     }
627 
628     GetTarget().SetExecutableModule(module, eLoadDependentsNo);
629   }
630 
631   if (auto dyld = GetDynamicLoader())
632     dyld->OnLoadModule(module, ModuleSpec(), image_base);
633 
634   // Add the main executable module to the list of pending module loads.  We
635   // can't call GetTarget().ModulesDidLoad() here because we still haven't
636   // returned from DoLaunch() / DoAttach() yet so the target may not have set
637   // the process instance to `this` yet.
638   llvm::sys::ScopedLock lock(m_mutex);
639   const HostThreadWindows &wmain_thread =
640       debugger->GetMainThread().GetNativeThread();
641   m_session_data->m_new_threads[wmain_thread.GetThreadId()] =
642       debugger->GetMainThread();
643 }
644 
645 ExceptionResult
646 ProcessWindows::OnDebugException(bool first_chance,
647                                  const ExceptionRecord &record) {
648   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EXCEPTION);
649   llvm::sys::ScopedLock lock(m_mutex);
650 
651   // FIXME: Without this check, occasionally when running the test suite there
652   // is
653   // an issue where m_session_data can be null.  It's not clear how this could
654   // happen but it only surfaces while running the test suite.  In order to
655   // properly diagnose this, we probably need to first figure allow the test
656   // suite to print out full lldb logs, and then add logging to the process
657   // plugin.
658   if (!m_session_data) {
659     LLDB_LOG(log,
660              "Debugger thread reported exception {0:x} at address {1:x}, "
661              "but there is no session.",
662              record.GetExceptionCode(), record.GetExceptionAddress());
663     return ExceptionResult::SendToApplication;
664   }
665 
666   if (!first_chance) {
667     // Not any second chance exception is an application crash by definition.
668     // It may be an expression evaluation crash.
669     SetPrivateState(eStateStopped);
670   }
671 
672   ExceptionResult result = ExceptionResult::SendToApplication;
673   switch (record.GetExceptionCode()) {
674   case EXCEPTION_BREAKPOINT:
675     // Handle breakpoints at the first chance.
676     result = ExceptionResult::BreakInDebugger;
677 
678     if (!m_session_data->m_initial_stop_received) {
679       LLDB_LOG(
680           log,
681           "Hit loader breakpoint at address {0:x}, setting initial stop event.",
682           record.GetExceptionAddress());
683       m_session_data->m_initial_stop_received = true;
684       ::SetEvent(m_session_data->m_initial_stop_event);
685     } else {
686       LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
687                record.GetExceptionAddress());
688     }
689     SetPrivateState(eStateStopped);
690     break;
691   case EXCEPTION_SINGLE_STEP:
692     result = ExceptionResult::BreakInDebugger;
693     SetPrivateState(eStateStopped);
694     break;
695   default:
696     LLDB_LOG(log,
697              "Debugger thread reported exception {0:x} at address {1:x} "
698              "(first_chance={2})",
699              record.GetExceptionCode(), record.GetExceptionAddress(),
700              first_chance);
701     // For non-breakpoints, give the application a chance to handle the
702     // exception first.
703     if (first_chance)
704       result = ExceptionResult::SendToApplication;
705     else
706       result = ExceptionResult::BreakInDebugger;
707   }
708 
709   return result;
710 }
711 
712 void ProcessWindows::OnCreateThread(const HostThread &new_thread) {
713   llvm::sys::ScopedLock lock(m_mutex);
714   const HostThreadWindows &wnew_thread = new_thread.GetNativeThread();
715   m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread;
716 }
717 
718 void ProcessWindows::OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) {
719   llvm::sys::ScopedLock lock(m_mutex);
720 
721   // On a forced termination, we may get exit thread events after the session
722   // data has been cleaned up.
723   if (!m_session_data)
724     return;
725 
726   // A thread may have started and exited before the debugger stopped allowing a
727   // refresh.
728   // Just remove it from the new threads list in that case.
729   auto iter = m_session_data->m_new_threads.find(thread_id);
730   if (iter != m_session_data->m_new_threads.end())
731     m_session_data->m_new_threads.erase(iter);
732   else
733     m_session_data->m_exited_threads.insert(thread_id);
734 }
735 
736 void ProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
737                                lldb::addr_t module_addr) {
738   if (auto dyld = GetDynamicLoader())
739     dyld->OnLoadModule(nullptr, module_spec, module_addr);
740 }
741 
742 void ProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
743   if (auto dyld = GetDynamicLoader())
744     dyld->OnUnloadModule(module_addr);
745 }
746 
747 void ProcessWindows::OnDebugString(const std::string &string) {}
748 
749 void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) {
750   llvm::sys::ScopedLock lock(m_mutex);
751   Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_PROCESS);
752 
753   if (m_session_data->m_initial_stop_received) {
754     // This happened while debugging.  Do we shutdown the debugging session,
755     // try to continue, or do something else?
756     LLDB_LOG(log,
757              "Error {0} occurred during debugging.  Unexpected behavior "
758              "may result.  {1}",
759              error.GetError(), error);
760   } else {
761     // If we haven't actually launched the process yet, this was an error
762     // launching the process.  Set the internal error and signal the initial
763     // stop event so that the DoLaunch method wakes up and returns a failure.
764     m_session_data->m_launch_error = error;
765     ::SetEvent(m_session_data->m_initial_stop_event);
766     LLDB_LOG(
767         log,
768         "Error {0} occurred launching the process before the initial stop. {1}",
769         error.GetError(), error);
770     return;
771   }
772 }
773 } // namespace lldb_private
774