1 //===-- NativeProcessWindows.cpp ------------------------------------------===//
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 "lldb/Host/windows/windows.h"
10 #include <psapi.h>
11 
12 #include "NativeProcessWindows.h"
13 #include "NativeThreadWindows.h"
14 #include "lldb/Host/FileSystem.h"
15 #include "lldb/Host/HostNativeProcessBase.h"
16 #include "lldb/Host/HostProcess.h"
17 #include "lldb/Host/ProcessLaunchInfo.h"
18 #include "lldb/Host/windows/AutoHandle.h"
19 #include "lldb/Host/windows/HostThreadWindows.h"
20 #include "lldb/Host/windows/ProcessLauncherWindows.h"
21 #include "lldb/Target/MemoryRegionInfo.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Utility/State.h"
24 #include "llvm/Support/ConvertUTF.h"
25 #include "llvm/Support/Errc.h"
26 #include "llvm/Support/Error.h"
27 #include "llvm/Support/Format.h"
28 #include "llvm/Support/Threading.h"
29 #include "llvm/Support/raw_ostream.h"
30 
31 #include "DebuggerThread.h"
32 #include "ExceptionRecord.h"
33 #include "ProcessWindowsLog.h"
34 
35 #include <tlhelp32.h>
36 
37 #pragma warning(disable : 4005)
38 #include "winternl.h"
39 #include <ntstatus.h>
40 
41 using namespace lldb;
42 using namespace lldb_private;
43 using namespace llvm;
44 
45 namespace lldb_private {
46 
NativeProcessWindows(ProcessLaunchInfo & launch_info,NativeDelegate & delegate,llvm::Error & E)47 NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
48                                            NativeDelegate &delegate,
49                                            llvm::Error &E)
50     : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID,
51                             launch_info.GetPTY().ReleasePrimaryFileDescriptor(),
52                             delegate),
53       ProcessDebugger(), m_arch(launch_info.GetArchitecture()) {
54   ErrorAsOutParameter EOut(&E);
55   DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
56   E = LaunchProcess(launch_info, delegate_sp).ToError();
57   if (E)
58     return;
59 
60   SetID(GetDebuggedProcessId());
61 }
62 
NativeProcessWindows(lldb::pid_t pid,int terminal_fd,NativeDelegate & delegate,llvm::Error & E)63 NativeProcessWindows::NativeProcessWindows(lldb::pid_t pid, int terminal_fd,
64                                            NativeDelegate &delegate,
65                                            llvm::Error &E)
66     : NativeProcessProtocol(pid, terminal_fd, delegate), ProcessDebugger() {
67   ErrorAsOutParameter EOut(&E);
68   DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
69   ProcessAttachInfo attach_info;
70   attach_info.SetProcessID(pid);
71   E = AttachProcess(pid, attach_info, delegate_sp).ToError();
72   if (E)
73     return;
74 
75   SetID(GetDebuggedProcessId());
76 
77   ProcessInstanceInfo info;
78   if (!Host::GetProcessInfo(pid, info)) {
79     E = createStringError(inconvertibleErrorCode(),
80                           "Cannot get process information");
81     return;
82   }
83   m_arch = info.GetArchitecture();
84 }
85 
Resume(const ResumeActionList & resume_actions)86 Status NativeProcessWindows::Resume(const ResumeActionList &resume_actions) {
87   Log *log = GetLog(WindowsLog::Process);
88   Status error;
89   llvm::sys::ScopedLock lock(m_mutex);
90 
91   StateType state = GetState();
92   if (state == eStateStopped || state == eStateCrashed) {
93     LLDB_LOG(log, "process {0} is in state {1}.  Resuming...",
94              GetDebuggedProcessId(), state);
95     LLDB_LOG(log, "resuming {0} threads.", m_threads.size());
96 
97     bool failed = false;
98     for (uint32_t i = 0; i < m_threads.size(); ++i) {
99       auto thread = static_cast<NativeThreadWindows *>(m_threads[i].get());
100       const ResumeAction *const action =
101           resume_actions.GetActionForThread(thread->GetID(), true);
102       if (action == nullptr)
103         continue;
104 
105       switch (action->state) {
106       case eStateRunning:
107       case eStateStepping: {
108         Status result = thread->DoResume(action->state);
109         if (result.Fail()) {
110           failed = true;
111           LLDB_LOG(log,
112                    "Trying to resume thread at index {0}, but failed with "
113                    "error {1}.",
114                    i, result);
115         }
116         break;
117       }
118       case eStateSuspended:
119       case eStateStopped:
120         break;
121 
122       default:
123         return Status(
124             "NativeProcessWindows::%s (): unexpected state %s specified "
125             "for pid %" PRIu64 ", tid %" PRIu64,
126             __FUNCTION__, StateAsCString(action->state), GetID(),
127             thread->GetID());
128       }
129     }
130 
131     if (failed) {
132       error.SetErrorString("NativeProcessWindows::DoResume failed");
133     } else {
134       SetState(eStateRunning);
135     }
136 
137     // Resume the debug loop.
138     ExceptionRecordSP active_exception =
139         m_session_data->m_debugger->GetActiveException().lock();
140     if (active_exception) {
141       // Resume the process and continue processing debug events.  Mask the
142       // exception so that from the process's view, there is no indication that
143       // anything happened.
144       m_session_data->m_debugger->ContinueAsyncException(
145           ExceptionResult::MaskException);
146     }
147   } else {
148     LLDB_LOG(log, "error: process {0} is in state {1}.  Returning...",
149              GetDebuggedProcessId(), GetState());
150   }
151 
152   return error;
153 }
154 
155 NativeThreadWindows *
GetThreadByID(lldb::tid_t thread_id)156 NativeProcessWindows::GetThreadByID(lldb::tid_t thread_id) {
157   return static_cast<NativeThreadWindows *>(
158       NativeProcessProtocol::GetThreadByID(thread_id));
159 }
160 
Halt()161 Status NativeProcessWindows::Halt() {
162   bool caused_stop = false;
163   StateType state = GetState();
164   if (state != eStateStopped)
165     return HaltProcess(caused_stop);
166   return Status();
167 }
168 
Detach()169 Status NativeProcessWindows::Detach() {
170   Status error;
171   Log *log = GetLog(WindowsLog::Process);
172   StateType state = GetState();
173   if (state != eStateExited && state != eStateDetached) {
174     error = DetachProcess();
175     if (error.Success())
176       SetState(eStateDetached);
177     else
178       LLDB_LOG(log, "Detaching process error: {0}", error);
179   } else {
180     error.SetErrorStringWithFormatv("error: process {0} in state = {1}, but "
181                                     "cannot detach it in this state.",
182                                     GetID(), state);
183     LLDB_LOG(log, "error: {0}", error);
184   }
185   return error;
186 }
187 
Signal(int signo)188 Status NativeProcessWindows::Signal(int signo) {
189   Status error;
190   error.SetErrorString("Windows does not support sending signals to processes");
191   return error;
192 }
193 
Interrupt()194 Status NativeProcessWindows::Interrupt() { return Halt(); }
195 
Kill()196 Status NativeProcessWindows::Kill() {
197   StateType state = GetState();
198   return DestroyProcess(state);
199 }
200 
IgnoreSignals(llvm::ArrayRef<int> signals)201 Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) {
202   return Status();
203 }
204 
GetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & range_info)205 Status NativeProcessWindows::GetMemoryRegionInfo(lldb::addr_t load_addr,
206                                                  MemoryRegionInfo &range_info) {
207   return ProcessDebugger::GetMemoryRegionInfo(load_addr, range_info);
208 }
209 
ReadMemory(lldb::addr_t addr,void * buf,size_t size,size_t & bytes_read)210 Status NativeProcessWindows::ReadMemory(lldb::addr_t addr, void *buf,
211                                         size_t size, size_t &bytes_read) {
212   return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read);
213 }
214 
WriteMemory(lldb::addr_t addr,const void * buf,size_t size,size_t & bytes_written)215 Status NativeProcessWindows::WriteMemory(lldb::addr_t addr, const void *buf,
216                                          size_t size, size_t &bytes_written) {
217   return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written);
218 }
219 
220 llvm::Expected<lldb::addr_t>
AllocateMemory(size_t size,uint32_t permissions)221 NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions) {
222   lldb::addr_t addr;
223   Status ST = ProcessDebugger::AllocateMemory(size, permissions, addr);
224   if (ST.Success())
225     return addr;
226   return ST.ToError();
227 }
228 
DeallocateMemory(lldb::addr_t addr)229 llvm::Error NativeProcessWindows::DeallocateMemory(lldb::addr_t addr) {
230   return ProcessDebugger::DeallocateMemory(addr).ToError();
231 }
232 
GetSharedLibraryInfoAddress()233 lldb::addr_t NativeProcessWindows::GetSharedLibraryInfoAddress() { return 0; }
234 
IsAlive() const235 bool NativeProcessWindows::IsAlive() const {
236   StateType state = GetState();
237   switch (state) {
238   case eStateCrashed:
239   case eStateDetached:
240   case eStateExited:
241   case eStateInvalid:
242   case eStateUnloaded:
243     return false;
244   default:
245     return true;
246   }
247 }
248 
SetStopReasonForThread(NativeThreadWindows & thread,lldb::StopReason reason,std::string description)249 void NativeProcessWindows::SetStopReasonForThread(NativeThreadWindows &thread,
250                                                   lldb::StopReason reason,
251                                                   std::string description) {
252   SetCurrentThreadID(thread.GetID());
253 
254   ThreadStopInfo stop_info;
255   stop_info.reason = reason;
256   // No signal support on Windows but required to provide a 'valid' signum.
257   stop_info.signo = SIGTRAP;
258 
259   if (reason == StopReason::eStopReasonException) {
260     stop_info.details.exception.type = 0;
261     stop_info.details.exception.data_count = 0;
262   }
263 
264   thread.SetStopReason(stop_info, description);
265 }
266 
StopThread(lldb::tid_t thread_id,lldb::StopReason reason,std::string description)267 void NativeProcessWindows::StopThread(lldb::tid_t thread_id,
268                                       lldb::StopReason reason,
269                                       std::string description) {
270   NativeThreadWindows *thread = GetThreadByID(thread_id);
271   if (!thread)
272     return;
273 
274   for (uint32_t i = 0; i < m_threads.size(); ++i) {
275     auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
276     Status error = t->DoStop();
277     if (error.Fail())
278       exit(1);
279   }
280   SetStopReasonForThread(*thread, reason, description);
281 }
282 
UpdateThreads()283 size_t NativeProcessWindows::UpdateThreads() { return m_threads.size(); }
284 
285 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
GetAuxvData() const286 NativeProcessWindows::GetAuxvData() const {
287   // Not available on this target.
288   return llvm::errc::not_supported;
289 }
290 
291 llvm::Expected<llvm::ArrayRef<uint8_t>>
GetSoftwareBreakpointTrapOpcode(size_t size_hint)292 NativeProcessWindows::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
293   static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
294   static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
295 
296   switch (GetArchitecture().GetMachine()) {
297   case llvm::Triple::aarch64:
298     return llvm::ArrayRef(g_aarch64_opcode);
299 
300   case llvm::Triple::arm:
301   case llvm::Triple::thumb:
302     return llvm::ArrayRef(g_thumb_opcode);
303 
304   default:
305     return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
306   }
307 }
308 
GetSoftwareBreakpointPCOffset()309 size_t NativeProcessWindows::GetSoftwareBreakpointPCOffset() {
310     // Windows always reports an incremented PC after a breakpoint is hit,
311     // even on ARM.
312     return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size();
313 }
314 
FindSoftwareBreakpoint(lldb::addr_t addr)315 bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) {
316   auto it = m_software_breakpoints.find(addr);
317   if (it == m_software_breakpoints.end())
318     return false;
319   return true;
320 }
321 
SetBreakpoint(lldb::addr_t addr,uint32_t size,bool hardware)322 Status NativeProcessWindows::SetBreakpoint(lldb::addr_t addr, uint32_t size,
323                                            bool hardware) {
324   if (hardware)
325     return SetHardwareBreakpoint(addr, size);
326   return SetSoftwareBreakpoint(addr, size);
327 }
328 
RemoveBreakpoint(lldb::addr_t addr,bool hardware)329 Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr,
330                                               bool hardware) {
331   if (hardware)
332     return RemoveHardwareBreakpoint(addr);
333   return RemoveSoftwareBreakpoint(addr);
334 }
335 
CacheLoadedModules()336 Status NativeProcessWindows::CacheLoadedModules() {
337   Status error;
338   if (!m_loaded_modules.empty())
339     return Status();
340 
341   // Retrieve loaded modules by a Target/Module free implemenation.
342   AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));
343   if (snapshot.IsValid()) {
344     MODULEENTRY32W me;
345     me.dwSize = sizeof(MODULEENTRY32W);
346     if (Module32FirstW(snapshot.get(), &me)) {
347       do {
348         std::string path;
349         if (!llvm::convertWideToUTF8(me.szExePath, path))
350           continue;
351 
352         FileSpec file_spec(path);
353         FileSystem::Instance().Resolve(file_spec);
354         m_loaded_modules[file_spec] = (addr_t)me.modBaseAddr;
355       } while (Module32Next(snapshot.get(), &me));
356     }
357 
358     if (!m_loaded_modules.empty())
359       return Status();
360   }
361 
362   error.SetError(::GetLastError(), lldb::ErrorType::eErrorTypeWin32);
363   return error;
364 }
365 
GetLoadedModuleFileSpec(const char * module_path,FileSpec & file_spec)366 Status NativeProcessWindows::GetLoadedModuleFileSpec(const char *module_path,
367                                                      FileSpec &file_spec) {
368   Status error = CacheLoadedModules();
369   if (error.Fail())
370     return error;
371 
372   FileSpec module_file_spec(module_path);
373   FileSystem::Instance().Resolve(module_file_spec);
374   for (auto &it : m_loaded_modules) {
375     if (it.first == module_file_spec) {
376       file_spec = it.first;
377       return Status();
378     }
379   }
380   return Status("Module (%s) not found in process %" PRIu64 "!",
381                 module_file_spec.GetPath().c_str(), GetID());
382 }
383 
384 Status
GetFileLoadAddress(const llvm::StringRef & file_name,lldb::addr_t & load_addr)385 NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name,
386                                          lldb::addr_t &load_addr) {
387   Status error = CacheLoadedModules();
388   if (error.Fail())
389     return error;
390 
391   load_addr = LLDB_INVALID_ADDRESS;
392   FileSpec file_spec(file_name);
393   FileSystem::Instance().Resolve(file_spec);
394   for (auto &it : m_loaded_modules) {
395     if (it.first == file_spec) {
396       load_addr = it.second;
397       return Status();
398     }
399   }
400   return Status("Can't get loaded address of file (%s) in process %" PRIu64 "!",
401                 file_spec.GetPath().c_str(), GetID());
402 }
403 
OnExitProcess(uint32_t exit_code)404 void NativeProcessWindows::OnExitProcess(uint32_t exit_code) {
405   Log *log = GetLog(WindowsLog::Process);
406   LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
407 
408   ProcessDebugger::OnExitProcess(exit_code);
409 
410   // No signal involved.  It is just an exit event.
411   WaitStatus wait_status(WaitStatus::Exit, exit_code);
412   SetExitStatus(wait_status, true);
413 
414   // Notify the native delegate.
415   SetState(eStateExited, true);
416 }
417 
OnDebuggerConnected(lldb::addr_t image_base)418 void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
419   Log *log = GetLog(WindowsLog::Process);
420   LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",
421            GetDebuggedProcessId(), image_base);
422 
423   // This is the earliest chance we can resolve the process ID and
424   // architecture if we don't know them yet.
425   if (GetID() == LLDB_INVALID_PROCESS_ID)
426     SetID(GetDebuggedProcessId());
427 
428   if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) {
429     ProcessInstanceInfo process_info;
430     if (!Host::GetProcessInfo(GetDebuggedProcessId(), process_info)) {
431       LLDB_LOG(log, "Cannot get process information during debugger connecting "
432                     "to process");
433       return;
434     }
435     SetArchitecture(process_info.GetArchitecture());
436   }
437 
438   // The very first one shall always be the main thread.
439   assert(m_threads.empty());
440   m_threads.push_back(std::make_unique<NativeThreadWindows>(
441       *this, m_session_data->m_debugger->GetMainThread()));
442 }
443 
444 ExceptionResult
OnDebugException(bool first_chance,const ExceptionRecord & record)445 NativeProcessWindows::OnDebugException(bool first_chance,
446                                        const ExceptionRecord &record) {
447   Log *log = GetLog(WindowsLog::Exception);
448   llvm::sys::ScopedLock lock(m_mutex);
449 
450   // Let the debugger establish the internal status.
451   ProcessDebugger::OnDebugException(first_chance, record);
452 
453   static bool initial_stop = false;
454   if (!first_chance) {
455     SetState(eStateStopped, false);
456   }
457 
458   ExceptionResult result = ExceptionResult::SendToApplication;
459   switch (record.GetExceptionCode()) {
460   case DWORD(STATUS_SINGLE_STEP):
461   case STATUS_WX86_SINGLE_STEP: {
462     uint32_t wp_id = LLDB_INVALID_INDEX32;
463     if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) {
464       NativeRegisterContextWindows &reg_ctx = thread->GetRegisterContext();
465       Status error =
466           reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress());
467       if (error.Fail())
468         LLDB_LOG(log,
469                  "received error while checking for watchpoint hits, pid = "
470                  "{0}, error = {1}",
471                  thread->GetID(), error);
472       if (wp_id != LLDB_INVALID_INDEX32) {
473         addr_t wp_addr = reg_ctx.GetWatchpointAddress(wp_id);
474         addr_t wp_hit_addr = reg_ctx.GetWatchpointHitAddress(wp_id);
475         std::string desc =
476             formatv("{0} {1} {2}", wp_addr, wp_id, wp_hit_addr).str();
477         StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint,
478                    desc);
479       }
480     }
481     if (wp_id == LLDB_INVALID_INDEX32)
482       StopThread(record.GetThreadID(), StopReason::eStopReasonTrace);
483 
484     SetState(eStateStopped, true);
485 
486     // Continue the debugger.
487     return ExceptionResult::MaskException;
488   }
489   case DWORD(STATUS_BREAKPOINT):
490   case STATUS_WX86_BREAKPOINT:
491     if (FindSoftwareBreakpoint(record.GetExceptionAddress())) {
492       LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
493                record.GetExceptionAddress());
494 
495       StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint);
496 
497       if (NativeThreadWindows *stop_thread =
498               GetThreadByID(record.GetThreadID())) {
499         auto &register_context = stop_thread->GetRegisterContext();
500         uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset();
501         // The current PC is AFTER the BP opcode, on all architectures.
502         uint64_t pc = register_context.GetPC() - breakpoint_size;
503         register_context.SetPC(pc);
504       }
505 
506       SetState(eStateStopped, true);
507       return ExceptionResult::MaskException;
508     }
509 
510     if (!initial_stop) {
511       initial_stop = true;
512       LLDB_LOG(log,
513                "Hit loader breakpoint at address {0:x}, setting initial stop "
514                "event.",
515                record.GetExceptionAddress());
516 
517       // We are required to report the reason for the first stop after
518       // launching or being attached.
519       if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID()))
520         SetStopReasonForThread(*thread, StopReason::eStopReasonBreakpoint);
521 
522       // Do not notify the native delegate (e.g. llgs) since at this moment
523       // the program hasn't returned from Factory::Launch() and the delegate
524       // might not have an valid native process to operate on.
525       SetState(eStateStopped, false);
526 
527       // Hit the initial stop. Continue the application.
528       return ExceptionResult::BreakInDebugger;
529     }
530 
531     [[fallthrough]];
532   default:
533     LLDB_LOG(log,
534              "Debugger thread reported exception {0:x} at address {1:x} "
535              "(first_chance={2})",
536              record.GetExceptionCode(), record.GetExceptionAddress(),
537              first_chance);
538 
539     {
540       std::string desc;
541       llvm::raw_string_ostream desc_stream(desc);
542       desc_stream << "Exception "
543                   << llvm::format_hex(record.GetExceptionCode(), 8)
544                   << " encountered at address "
545                   << llvm::format_hex(record.GetExceptionAddress(), 8);
546       StopThread(record.GetThreadID(), StopReason::eStopReasonException,
547                  desc_stream.str().c_str());
548 
549       SetState(eStateStopped, true);
550     }
551 
552     // For non-breakpoints, give the application a chance to handle the
553     // exception first.
554     if (first_chance)
555       result = ExceptionResult::SendToApplication;
556     else
557       result = ExceptionResult::BreakInDebugger;
558   }
559 
560   return result;
561 }
562 
OnCreateThread(const HostThread & new_thread)563 void NativeProcessWindows::OnCreateThread(const HostThread &new_thread) {
564   llvm::sys::ScopedLock lock(m_mutex);
565 
566   auto thread = std::make_unique<NativeThreadWindows>(*this, new_thread);
567   thread->GetRegisterContext().ClearAllHardwareWatchpoints();
568   for (const auto &pair : GetWatchpointMap()) {
569     const NativeWatchpoint &wp = pair.second;
570     thread->SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags,
571                           wp.m_hardware);
572   }
573 
574   m_threads.push_back(std::move(thread));
575 }
576 
OnExitThread(lldb::tid_t thread_id,uint32_t exit_code)577 void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id,
578                                         uint32_t exit_code) {
579   llvm::sys::ScopedLock lock(m_mutex);
580   NativeThreadWindows *thread = GetThreadByID(thread_id);
581   if (!thread)
582     return;
583 
584   for (auto t = m_threads.begin(); t != m_threads.end();) {
585     if ((*t)->GetID() == thread_id) {
586       t = m_threads.erase(t);
587     } else {
588       ++t;
589     }
590   }
591 }
592 
OnLoadDll(const ModuleSpec & module_spec,lldb::addr_t module_addr)593 void NativeProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
594                                      lldb::addr_t module_addr) {
595   // Simply invalidate the cached loaded modules.
596   if (!m_loaded_modules.empty())
597     m_loaded_modules.clear();
598 }
599 
OnUnloadDll(lldb::addr_t module_addr)600 void NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
601   if (!m_loaded_modules.empty())
602     m_loaded_modules.clear();
603 }
604 
605 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo & launch_info,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const606 NativeProcessWindows::Factory::Launch(
607     ProcessLaunchInfo &launch_info,
608     NativeProcessProtocol::NativeDelegate &native_delegate,
609     MainLoop &mainloop) const {
610   Error E = Error::success();
611   auto process_up = std::unique_ptr<NativeProcessWindows>(
612       new NativeProcessWindows(launch_info, native_delegate, E));
613   if (E)
614     return std::move(E);
615   return std::move(process_up);
616 }
617 
618 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const619 NativeProcessWindows::Factory::Attach(
620     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
621     MainLoop &mainloop) const {
622   Error E = Error::success();
623   // Set pty primary fd invalid since it is not available.
624   auto process_up = std::unique_ptr<NativeProcessWindows>(
625       new NativeProcessWindows(pid, -1, native_delegate, E));
626   if (E)
627     return std::move(E);
628   return std::move(process_up);
629 }
630 } // namespace lldb_private
631