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