1dda28197Spatrick //===-- NativeProcessWindows.cpp ------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "lldb/Host/windows/windows.h"
10061da546Spatrick #include <psapi.h>
11061da546Spatrick 
12061da546Spatrick #include "NativeProcessWindows.h"
13061da546Spatrick #include "NativeThreadWindows.h"
14061da546Spatrick #include "lldb/Host/FileSystem.h"
15061da546Spatrick #include "lldb/Host/HostNativeProcessBase.h"
16061da546Spatrick #include "lldb/Host/HostProcess.h"
17061da546Spatrick #include "lldb/Host/ProcessLaunchInfo.h"
18061da546Spatrick #include "lldb/Host/windows/AutoHandle.h"
19061da546Spatrick #include "lldb/Host/windows/HostThreadWindows.h"
20061da546Spatrick #include "lldb/Host/windows/ProcessLauncherWindows.h"
21061da546Spatrick #include "lldb/Target/MemoryRegionInfo.h"
22061da546Spatrick #include "lldb/Target/Process.h"
23061da546Spatrick #include "lldb/Utility/State.h"
24061da546Spatrick #include "llvm/Support/ConvertUTF.h"
25061da546Spatrick #include "llvm/Support/Errc.h"
26061da546Spatrick #include "llvm/Support/Error.h"
27061da546Spatrick #include "llvm/Support/Format.h"
28061da546Spatrick #include "llvm/Support/Threading.h"
29061da546Spatrick #include "llvm/Support/raw_ostream.h"
30061da546Spatrick 
31061da546Spatrick #include "DebuggerThread.h"
32061da546Spatrick #include "ExceptionRecord.h"
33061da546Spatrick #include "ProcessWindowsLog.h"
34061da546Spatrick 
35061da546Spatrick #include <tlhelp32.h>
36061da546Spatrick 
37061da546Spatrick #pragma warning(disable : 4005)
38061da546Spatrick #include "winternl.h"
39061da546Spatrick #include <ntstatus.h>
40061da546Spatrick 
41061da546Spatrick using namespace lldb;
42061da546Spatrick using namespace lldb_private;
43061da546Spatrick using namespace llvm;
44061da546Spatrick 
45061da546Spatrick namespace lldb_private {
46061da546Spatrick 
NativeProcessWindows(ProcessLaunchInfo & launch_info,NativeDelegate & delegate,llvm::Error & E)47061da546Spatrick NativeProcessWindows::NativeProcessWindows(ProcessLaunchInfo &launch_info,
48061da546Spatrick                                            NativeDelegate &delegate,
49061da546Spatrick                                            llvm::Error &E)
50061da546Spatrick     : NativeProcessProtocol(LLDB_INVALID_PROCESS_ID,
51dda28197Spatrick                             launch_info.GetPTY().ReleasePrimaryFileDescriptor(),
52061da546Spatrick                             delegate),
53061da546Spatrick       ProcessDebugger(), m_arch(launch_info.GetArchitecture()) {
54061da546Spatrick   ErrorAsOutParameter EOut(&E);
55061da546Spatrick   DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
56061da546Spatrick   E = LaunchProcess(launch_info, delegate_sp).ToError();
57061da546Spatrick   if (E)
58061da546Spatrick     return;
59061da546Spatrick 
60061da546Spatrick   SetID(GetDebuggedProcessId());
61061da546Spatrick }
62061da546Spatrick 
NativeProcessWindows(lldb::pid_t pid,int terminal_fd,NativeDelegate & delegate,llvm::Error & E)63061da546Spatrick NativeProcessWindows::NativeProcessWindows(lldb::pid_t pid, int terminal_fd,
64061da546Spatrick                                            NativeDelegate &delegate,
65061da546Spatrick                                            llvm::Error &E)
66061da546Spatrick     : NativeProcessProtocol(pid, terminal_fd, delegate), ProcessDebugger() {
67061da546Spatrick   ErrorAsOutParameter EOut(&E);
68061da546Spatrick   DebugDelegateSP delegate_sp(new NativeDebugDelegate(*this));
69061da546Spatrick   ProcessAttachInfo attach_info;
70061da546Spatrick   attach_info.SetProcessID(pid);
71061da546Spatrick   E = AttachProcess(pid, attach_info, delegate_sp).ToError();
72061da546Spatrick   if (E)
73061da546Spatrick     return;
74061da546Spatrick 
75061da546Spatrick   SetID(GetDebuggedProcessId());
76061da546Spatrick 
77061da546Spatrick   ProcessInstanceInfo info;
78061da546Spatrick   if (!Host::GetProcessInfo(pid, info)) {
79061da546Spatrick     E = createStringError(inconvertibleErrorCode(),
80061da546Spatrick                           "Cannot get process information");
81061da546Spatrick     return;
82061da546Spatrick   }
83061da546Spatrick   m_arch = info.GetArchitecture();
84061da546Spatrick }
85061da546Spatrick 
Resume(const ResumeActionList & resume_actions)86061da546Spatrick Status NativeProcessWindows::Resume(const ResumeActionList &resume_actions) {
87*f6aab3d8Srobert   Log *log = GetLog(WindowsLog::Process);
88061da546Spatrick   Status error;
89061da546Spatrick   llvm::sys::ScopedLock lock(m_mutex);
90061da546Spatrick 
91061da546Spatrick   StateType state = GetState();
92061da546Spatrick   if (state == eStateStopped || state == eStateCrashed) {
93061da546Spatrick     LLDB_LOG(log, "process {0} is in state {1}.  Resuming...",
94061da546Spatrick              GetDebuggedProcessId(), state);
95061da546Spatrick     LLDB_LOG(log, "resuming {0} threads.", m_threads.size());
96061da546Spatrick 
97061da546Spatrick     bool failed = false;
98061da546Spatrick     for (uint32_t i = 0; i < m_threads.size(); ++i) {
99061da546Spatrick       auto thread = static_cast<NativeThreadWindows *>(m_threads[i].get());
100061da546Spatrick       const ResumeAction *const action =
101061da546Spatrick           resume_actions.GetActionForThread(thread->GetID(), true);
102061da546Spatrick       if (action == nullptr)
103061da546Spatrick         continue;
104061da546Spatrick 
105061da546Spatrick       switch (action->state) {
106061da546Spatrick       case eStateRunning:
107061da546Spatrick       case eStateStepping: {
108061da546Spatrick         Status result = thread->DoResume(action->state);
109061da546Spatrick         if (result.Fail()) {
110061da546Spatrick           failed = true;
111061da546Spatrick           LLDB_LOG(log,
112061da546Spatrick                    "Trying to resume thread at index {0}, but failed with "
113061da546Spatrick                    "error {1}.",
114061da546Spatrick                    i, result);
115061da546Spatrick         }
116061da546Spatrick         break;
117061da546Spatrick       }
118061da546Spatrick       case eStateSuspended:
119061da546Spatrick       case eStateStopped:
120*f6aab3d8Srobert         break;
121061da546Spatrick 
122061da546Spatrick       default:
123061da546Spatrick         return Status(
124061da546Spatrick             "NativeProcessWindows::%s (): unexpected state %s specified "
125061da546Spatrick             "for pid %" PRIu64 ", tid %" PRIu64,
126061da546Spatrick             __FUNCTION__, StateAsCString(action->state), GetID(),
127061da546Spatrick             thread->GetID());
128061da546Spatrick       }
129061da546Spatrick     }
130061da546Spatrick 
131061da546Spatrick     if (failed) {
132061da546Spatrick       error.SetErrorString("NativeProcessWindows::DoResume failed");
133061da546Spatrick     } else {
134061da546Spatrick       SetState(eStateRunning);
135061da546Spatrick     }
136061da546Spatrick 
137061da546Spatrick     // Resume the debug loop.
138061da546Spatrick     ExceptionRecordSP active_exception =
139061da546Spatrick         m_session_data->m_debugger->GetActiveException().lock();
140061da546Spatrick     if (active_exception) {
141061da546Spatrick       // Resume the process and continue processing debug events.  Mask the
142061da546Spatrick       // exception so that from the process's view, there is no indication that
143061da546Spatrick       // anything happened.
144061da546Spatrick       m_session_data->m_debugger->ContinueAsyncException(
145061da546Spatrick           ExceptionResult::MaskException);
146061da546Spatrick     }
147061da546Spatrick   } else {
148061da546Spatrick     LLDB_LOG(log, "error: process {0} is in state {1}.  Returning...",
149061da546Spatrick              GetDebuggedProcessId(), GetState());
150061da546Spatrick   }
151061da546Spatrick 
152061da546Spatrick   return error;
153061da546Spatrick }
154061da546Spatrick 
155061da546Spatrick NativeThreadWindows *
GetThreadByID(lldb::tid_t thread_id)156061da546Spatrick NativeProcessWindows::GetThreadByID(lldb::tid_t thread_id) {
157061da546Spatrick   return static_cast<NativeThreadWindows *>(
158061da546Spatrick       NativeProcessProtocol::GetThreadByID(thread_id));
159061da546Spatrick }
160061da546Spatrick 
Halt()161061da546Spatrick Status NativeProcessWindows::Halt() {
162061da546Spatrick   bool caused_stop = false;
163061da546Spatrick   StateType state = GetState();
164061da546Spatrick   if (state != eStateStopped)
165061da546Spatrick     return HaltProcess(caused_stop);
166061da546Spatrick   return Status();
167061da546Spatrick }
168061da546Spatrick 
Detach()169061da546Spatrick Status NativeProcessWindows::Detach() {
170061da546Spatrick   Status error;
171*f6aab3d8Srobert   Log *log = GetLog(WindowsLog::Process);
172061da546Spatrick   StateType state = GetState();
173061da546Spatrick   if (state != eStateExited && state != eStateDetached) {
174061da546Spatrick     error = DetachProcess();
175061da546Spatrick     if (error.Success())
176061da546Spatrick       SetState(eStateDetached);
177061da546Spatrick     else
178061da546Spatrick       LLDB_LOG(log, "Detaching process error: {0}", error);
179061da546Spatrick   } else {
180061da546Spatrick     error.SetErrorStringWithFormatv("error: process {0} in state = {1}, but "
181061da546Spatrick                                     "cannot detach it in this state.",
182061da546Spatrick                                     GetID(), state);
183061da546Spatrick     LLDB_LOG(log, "error: {0}", error);
184061da546Spatrick   }
185061da546Spatrick   return error;
186061da546Spatrick }
187061da546Spatrick 
Signal(int signo)188061da546Spatrick Status NativeProcessWindows::Signal(int signo) {
189061da546Spatrick   Status error;
190061da546Spatrick   error.SetErrorString("Windows does not support sending signals to processes");
191061da546Spatrick   return error;
192061da546Spatrick }
193061da546Spatrick 
Interrupt()194061da546Spatrick Status NativeProcessWindows::Interrupt() { return Halt(); }
195061da546Spatrick 
Kill()196061da546Spatrick Status NativeProcessWindows::Kill() {
197061da546Spatrick   StateType state = GetState();
198061da546Spatrick   return DestroyProcess(state);
199061da546Spatrick }
200061da546Spatrick 
IgnoreSignals(llvm::ArrayRef<int> signals)201061da546Spatrick Status NativeProcessWindows::IgnoreSignals(llvm::ArrayRef<int> signals) {
202061da546Spatrick   return Status();
203061da546Spatrick }
204061da546Spatrick 
GetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & range_info)205061da546Spatrick Status NativeProcessWindows::GetMemoryRegionInfo(lldb::addr_t load_addr,
206061da546Spatrick                                                  MemoryRegionInfo &range_info) {
207061da546Spatrick   return ProcessDebugger::GetMemoryRegionInfo(load_addr, range_info);
208061da546Spatrick }
209061da546Spatrick 
ReadMemory(lldb::addr_t addr,void * buf,size_t size,size_t & bytes_read)210061da546Spatrick Status NativeProcessWindows::ReadMemory(lldb::addr_t addr, void *buf,
211061da546Spatrick                                         size_t size, size_t &bytes_read) {
212061da546Spatrick   return ProcessDebugger::ReadMemory(addr, buf, size, bytes_read);
213061da546Spatrick }
214061da546Spatrick 
WriteMemory(lldb::addr_t addr,const void * buf,size_t size,size_t & bytes_written)215061da546Spatrick Status NativeProcessWindows::WriteMemory(lldb::addr_t addr, const void *buf,
216061da546Spatrick                                          size_t size, size_t &bytes_written) {
217061da546Spatrick   return ProcessDebugger::WriteMemory(addr, buf, size, bytes_written);
218061da546Spatrick }
219061da546Spatrick 
220be691f3bSpatrick llvm::Expected<lldb::addr_t>
AllocateMemory(size_t size,uint32_t permissions)221be691f3bSpatrick NativeProcessWindows::AllocateMemory(size_t size, uint32_t permissions) {
222be691f3bSpatrick   lldb::addr_t addr;
223be691f3bSpatrick   Status ST = ProcessDebugger::AllocateMemory(size, permissions, addr);
224be691f3bSpatrick   if (ST.Success())
225be691f3bSpatrick     return addr;
226be691f3bSpatrick   return ST.ToError();
227061da546Spatrick }
228061da546Spatrick 
DeallocateMemory(lldb::addr_t addr)229be691f3bSpatrick llvm::Error NativeProcessWindows::DeallocateMemory(lldb::addr_t addr) {
230be691f3bSpatrick   return ProcessDebugger::DeallocateMemory(addr).ToError();
231061da546Spatrick }
232061da546Spatrick 
GetSharedLibraryInfoAddress()233061da546Spatrick lldb::addr_t NativeProcessWindows::GetSharedLibraryInfoAddress() { return 0; }
234061da546Spatrick 
IsAlive() const235061da546Spatrick bool NativeProcessWindows::IsAlive() const {
236061da546Spatrick   StateType state = GetState();
237061da546Spatrick   switch (state) {
238061da546Spatrick   case eStateCrashed:
239061da546Spatrick   case eStateDetached:
240061da546Spatrick   case eStateExited:
241061da546Spatrick   case eStateInvalid:
242061da546Spatrick   case eStateUnloaded:
243061da546Spatrick     return false;
244061da546Spatrick   default:
245061da546Spatrick     return true;
246061da546Spatrick   }
247061da546Spatrick }
248061da546Spatrick 
SetStopReasonForThread(NativeThreadWindows & thread,lldb::StopReason reason,std::string description)249061da546Spatrick void NativeProcessWindows::SetStopReasonForThread(NativeThreadWindows &thread,
250061da546Spatrick                                                   lldb::StopReason reason,
251061da546Spatrick                                                   std::string description) {
252061da546Spatrick   SetCurrentThreadID(thread.GetID());
253061da546Spatrick 
254061da546Spatrick   ThreadStopInfo stop_info;
255061da546Spatrick   stop_info.reason = reason;
256061da546Spatrick   // No signal support on Windows but required to provide a 'valid' signum.
257*f6aab3d8Srobert   stop_info.signo = SIGTRAP;
258*f6aab3d8Srobert 
259061da546Spatrick   if (reason == StopReason::eStopReasonException) {
260061da546Spatrick     stop_info.details.exception.type = 0;
261061da546Spatrick     stop_info.details.exception.data_count = 0;
262061da546Spatrick   }
263061da546Spatrick 
264061da546Spatrick   thread.SetStopReason(stop_info, description);
265061da546Spatrick }
266061da546Spatrick 
StopThread(lldb::tid_t thread_id,lldb::StopReason reason,std::string description)267061da546Spatrick void NativeProcessWindows::StopThread(lldb::tid_t thread_id,
268061da546Spatrick                                       lldb::StopReason reason,
269061da546Spatrick                                       std::string description) {
270061da546Spatrick   NativeThreadWindows *thread = GetThreadByID(thread_id);
271061da546Spatrick   if (!thread)
272061da546Spatrick     return;
273061da546Spatrick 
274061da546Spatrick   for (uint32_t i = 0; i < m_threads.size(); ++i) {
275061da546Spatrick     auto t = static_cast<NativeThreadWindows *>(m_threads[i].get());
276061da546Spatrick     Status error = t->DoStop();
277061da546Spatrick     if (error.Fail())
278061da546Spatrick       exit(1);
279061da546Spatrick   }
280061da546Spatrick   SetStopReasonForThread(*thread, reason, description);
281061da546Spatrick }
282061da546Spatrick 
UpdateThreads()283061da546Spatrick size_t NativeProcessWindows::UpdateThreads() { return m_threads.size(); }
284061da546Spatrick 
285061da546Spatrick llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
GetAuxvData() const286061da546Spatrick NativeProcessWindows::GetAuxvData() const {
287061da546Spatrick   // Not available on this target.
288061da546Spatrick   return llvm::errc::not_supported;
289061da546Spatrick }
290061da546Spatrick 
291*f6aab3d8Srobert llvm::Expected<llvm::ArrayRef<uint8_t>>
GetSoftwareBreakpointTrapOpcode(size_t size_hint)292*f6aab3d8Srobert NativeProcessWindows::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
293*f6aab3d8Srobert   static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x3e, 0xd4}; // brk #0xf000
294*f6aab3d8Srobert   static const uint8_t g_thumb_opcode[] = {0xfe, 0xde}; // udf #0xfe
295*f6aab3d8Srobert 
296*f6aab3d8Srobert   switch (GetArchitecture().GetMachine()) {
297*f6aab3d8Srobert   case llvm::Triple::aarch64:
298*f6aab3d8Srobert     return llvm::ArrayRef(g_aarch64_opcode);
299*f6aab3d8Srobert 
300*f6aab3d8Srobert   case llvm::Triple::arm:
301*f6aab3d8Srobert   case llvm::Triple::thumb:
302*f6aab3d8Srobert     return llvm::ArrayRef(g_thumb_opcode);
303*f6aab3d8Srobert 
304*f6aab3d8Srobert   default:
305*f6aab3d8Srobert     return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
306*f6aab3d8Srobert   }
307*f6aab3d8Srobert }
308*f6aab3d8Srobert 
GetSoftwareBreakpointPCOffset()309*f6aab3d8Srobert size_t NativeProcessWindows::GetSoftwareBreakpointPCOffset() {
310*f6aab3d8Srobert     // Windows always reports an incremented PC after a breakpoint is hit,
311*f6aab3d8Srobert     // even on ARM.
312*f6aab3d8Srobert     return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size();
313*f6aab3d8Srobert }
314*f6aab3d8Srobert 
FindSoftwareBreakpoint(lldb::addr_t addr)315061da546Spatrick bool NativeProcessWindows::FindSoftwareBreakpoint(lldb::addr_t addr) {
316061da546Spatrick   auto it = m_software_breakpoints.find(addr);
317061da546Spatrick   if (it == m_software_breakpoints.end())
318061da546Spatrick     return false;
319061da546Spatrick   return true;
320061da546Spatrick }
321061da546Spatrick 
SetBreakpoint(lldb::addr_t addr,uint32_t size,bool hardware)322061da546Spatrick Status NativeProcessWindows::SetBreakpoint(lldb::addr_t addr, uint32_t size,
323061da546Spatrick                                            bool hardware) {
324061da546Spatrick   if (hardware)
325061da546Spatrick     return SetHardwareBreakpoint(addr, size);
326061da546Spatrick   return SetSoftwareBreakpoint(addr, size);
327061da546Spatrick }
328061da546Spatrick 
RemoveBreakpoint(lldb::addr_t addr,bool hardware)329061da546Spatrick Status NativeProcessWindows::RemoveBreakpoint(lldb::addr_t addr,
330061da546Spatrick                                               bool hardware) {
331061da546Spatrick   if (hardware)
332061da546Spatrick     return RemoveHardwareBreakpoint(addr);
333061da546Spatrick   return RemoveSoftwareBreakpoint(addr);
334061da546Spatrick }
335061da546Spatrick 
CacheLoadedModules()336061da546Spatrick Status NativeProcessWindows::CacheLoadedModules() {
337061da546Spatrick   Status error;
338061da546Spatrick   if (!m_loaded_modules.empty())
339061da546Spatrick     return Status();
340061da546Spatrick 
341061da546Spatrick   // Retrieve loaded modules by a Target/Module free implemenation.
342061da546Spatrick   AutoHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetID()));
343061da546Spatrick   if (snapshot.IsValid()) {
344061da546Spatrick     MODULEENTRY32W me;
345061da546Spatrick     me.dwSize = sizeof(MODULEENTRY32W);
346061da546Spatrick     if (Module32FirstW(snapshot.get(), &me)) {
347061da546Spatrick       do {
348061da546Spatrick         std::string path;
349061da546Spatrick         if (!llvm::convertWideToUTF8(me.szExePath, path))
350061da546Spatrick           continue;
351061da546Spatrick 
352061da546Spatrick         FileSpec file_spec(path);
353061da546Spatrick         FileSystem::Instance().Resolve(file_spec);
354061da546Spatrick         m_loaded_modules[file_spec] = (addr_t)me.modBaseAddr;
355061da546Spatrick       } while (Module32Next(snapshot.get(), &me));
356061da546Spatrick     }
357061da546Spatrick 
358061da546Spatrick     if (!m_loaded_modules.empty())
359061da546Spatrick       return Status();
360061da546Spatrick   }
361061da546Spatrick 
362061da546Spatrick   error.SetError(::GetLastError(), lldb::ErrorType::eErrorTypeWin32);
363061da546Spatrick   return error;
364061da546Spatrick }
365061da546Spatrick 
GetLoadedModuleFileSpec(const char * module_path,FileSpec & file_spec)366061da546Spatrick Status NativeProcessWindows::GetLoadedModuleFileSpec(const char *module_path,
367061da546Spatrick                                                      FileSpec &file_spec) {
368061da546Spatrick   Status error = CacheLoadedModules();
369061da546Spatrick   if (error.Fail())
370061da546Spatrick     return error;
371061da546Spatrick 
372061da546Spatrick   FileSpec module_file_spec(module_path);
373061da546Spatrick   FileSystem::Instance().Resolve(module_file_spec);
374061da546Spatrick   for (auto &it : m_loaded_modules) {
375061da546Spatrick     if (it.first == module_file_spec) {
376061da546Spatrick       file_spec = it.first;
377061da546Spatrick       return Status();
378061da546Spatrick     }
379061da546Spatrick   }
380061da546Spatrick   return Status("Module (%s) not found in process %" PRIu64 "!",
381*f6aab3d8Srobert                 module_file_spec.GetPath().c_str(), GetID());
382061da546Spatrick }
383061da546Spatrick 
384061da546Spatrick Status
GetFileLoadAddress(const llvm::StringRef & file_name,lldb::addr_t & load_addr)385061da546Spatrick NativeProcessWindows::GetFileLoadAddress(const llvm::StringRef &file_name,
386061da546Spatrick                                          lldb::addr_t &load_addr) {
387061da546Spatrick   Status error = CacheLoadedModules();
388061da546Spatrick   if (error.Fail())
389061da546Spatrick     return error;
390061da546Spatrick 
391061da546Spatrick   load_addr = LLDB_INVALID_ADDRESS;
392061da546Spatrick   FileSpec file_spec(file_name);
393061da546Spatrick   FileSystem::Instance().Resolve(file_spec);
394061da546Spatrick   for (auto &it : m_loaded_modules) {
395061da546Spatrick     if (it.first == file_spec) {
396061da546Spatrick       load_addr = it.second;
397061da546Spatrick       return Status();
398061da546Spatrick     }
399061da546Spatrick   }
400061da546Spatrick   return Status("Can't get loaded address of file (%s) in process %" PRIu64 "!",
401*f6aab3d8Srobert                 file_spec.GetPath().c_str(), GetID());
402061da546Spatrick }
403061da546Spatrick 
OnExitProcess(uint32_t exit_code)404061da546Spatrick void NativeProcessWindows::OnExitProcess(uint32_t exit_code) {
405*f6aab3d8Srobert   Log *log = GetLog(WindowsLog::Process);
406061da546Spatrick   LLDB_LOG(log, "Process {0} exited with code {1}", GetID(), exit_code);
407061da546Spatrick 
408061da546Spatrick   ProcessDebugger::OnExitProcess(exit_code);
409061da546Spatrick 
410061da546Spatrick   // No signal involved.  It is just an exit event.
411061da546Spatrick   WaitStatus wait_status(WaitStatus::Exit, exit_code);
412061da546Spatrick   SetExitStatus(wait_status, true);
413061da546Spatrick 
414061da546Spatrick   // Notify the native delegate.
415061da546Spatrick   SetState(eStateExited, true);
416061da546Spatrick }
417061da546Spatrick 
OnDebuggerConnected(lldb::addr_t image_base)418061da546Spatrick void NativeProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
419*f6aab3d8Srobert   Log *log = GetLog(WindowsLog::Process);
420061da546Spatrick   LLDB_LOG(log, "Debugger connected to process {0}. Image base = {1:x}",
421061da546Spatrick            GetDebuggedProcessId(), image_base);
422061da546Spatrick 
423061da546Spatrick   // This is the earliest chance we can resolve the process ID and
424dda28197Spatrick   // architecture if we don't know them yet.
425061da546Spatrick   if (GetID() == LLDB_INVALID_PROCESS_ID)
426061da546Spatrick     SetID(GetDebuggedProcessId());
427061da546Spatrick 
428061da546Spatrick   if (GetArchitecture().GetMachine() == llvm::Triple::UnknownArch) {
429061da546Spatrick     ProcessInstanceInfo process_info;
430061da546Spatrick     if (!Host::GetProcessInfo(GetDebuggedProcessId(), process_info)) {
431061da546Spatrick       LLDB_LOG(log, "Cannot get process information during debugger connecting "
432061da546Spatrick                     "to process");
433061da546Spatrick       return;
434061da546Spatrick     }
435061da546Spatrick     SetArchitecture(process_info.GetArchitecture());
436061da546Spatrick   }
437061da546Spatrick 
438061da546Spatrick   // The very first one shall always be the main thread.
439061da546Spatrick   assert(m_threads.empty());
440061da546Spatrick   m_threads.push_back(std::make_unique<NativeThreadWindows>(
441061da546Spatrick       *this, m_session_data->m_debugger->GetMainThread()));
442061da546Spatrick }
443061da546Spatrick 
444061da546Spatrick ExceptionResult
OnDebugException(bool first_chance,const ExceptionRecord & record)445061da546Spatrick NativeProcessWindows::OnDebugException(bool first_chance,
446061da546Spatrick                                        const ExceptionRecord &record) {
447*f6aab3d8Srobert   Log *log = GetLog(WindowsLog::Exception);
448061da546Spatrick   llvm::sys::ScopedLock lock(m_mutex);
449061da546Spatrick 
450061da546Spatrick   // Let the debugger establish the internal status.
451061da546Spatrick   ProcessDebugger::OnDebugException(first_chance, record);
452061da546Spatrick 
453061da546Spatrick   static bool initial_stop = false;
454061da546Spatrick   if (!first_chance) {
455061da546Spatrick     SetState(eStateStopped, false);
456061da546Spatrick   }
457061da546Spatrick 
458061da546Spatrick   ExceptionResult result = ExceptionResult::SendToApplication;
459061da546Spatrick   switch (record.GetExceptionCode()) {
460061da546Spatrick   case DWORD(STATUS_SINGLE_STEP):
461061da546Spatrick   case STATUS_WX86_SINGLE_STEP: {
462061da546Spatrick     uint32_t wp_id = LLDB_INVALID_INDEX32;
463061da546Spatrick     if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID())) {
464061da546Spatrick       NativeRegisterContextWindows &reg_ctx = thread->GetRegisterContext();
465061da546Spatrick       Status error =
466061da546Spatrick           reg_ctx.GetWatchpointHitIndex(wp_id, record.GetExceptionAddress());
467061da546Spatrick       if (error.Fail())
468061da546Spatrick         LLDB_LOG(log,
469061da546Spatrick                  "received error while checking for watchpoint hits, pid = "
470061da546Spatrick                  "{0}, error = {1}",
471061da546Spatrick                  thread->GetID(), error);
472061da546Spatrick       if (wp_id != LLDB_INVALID_INDEX32) {
473061da546Spatrick         addr_t wp_addr = reg_ctx.GetWatchpointAddress(wp_id);
474061da546Spatrick         addr_t wp_hit_addr = reg_ctx.GetWatchpointHitAddress(wp_id);
475061da546Spatrick         std::string desc =
476061da546Spatrick             formatv("{0} {1} {2}", wp_addr, wp_id, wp_hit_addr).str();
477061da546Spatrick         StopThread(record.GetThreadID(), StopReason::eStopReasonWatchpoint,
478061da546Spatrick                    desc);
479061da546Spatrick       }
480061da546Spatrick     }
481061da546Spatrick     if (wp_id == LLDB_INVALID_INDEX32)
482061da546Spatrick       StopThread(record.GetThreadID(), StopReason::eStopReasonTrace);
483061da546Spatrick 
484061da546Spatrick     SetState(eStateStopped, true);
485061da546Spatrick 
486061da546Spatrick     // Continue the debugger.
487061da546Spatrick     return ExceptionResult::MaskException;
488061da546Spatrick   }
489061da546Spatrick   case DWORD(STATUS_BREAKPOINT):
490061da546Spatrick   case STATUS_WX86_BREAKPOINT:
491061da546Spatrick     if (FindSoftwareBreakpoint(record.GetExceptionAddress())) {
492061da546Spatrick       LLDB_LOG(log, "Hit non-loader breakpoint at address {0:x}.",
493061da546Spatrick                record.GetExceptionAddress());
494061da546Spatrick 
495061da546Spatrick       StopThread(record.GetThreadID(), StopReason::eStopReasonBreakpoint);
496061da546Spatrick 
497061da546Spatrick       if (NativeThreadWindows *stop_thread =
498061da546Spatrick               GetThreadByID(record.GetThreadID())) {
499061da546Spatrick         auto &register_context = stop_thread->GetRegisterContext();
500*f6aab3d8Srobert         uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset();
501*f6aab3d8Srobert         // The current PC is AFTER the BP opcode, on all architectures.
502*f6aab3d8Srobert         uint64_t pc = register_context.GetPC() - breakpoint_size;
503061da546Spatrick         register_context.SetPC(pc);
504061da546Spatrick       }
505061da546Spatrick 
506061da546Spatrick       SetState(eStateStopped, true);
507061da546Spatrick       return ExceptionResult::MaskException;
508061da546Spatrick     }
509061da546Spatrick 
510061da546Spatrick     if (!initial_stop) {
511061da546Spatrick       initial_stop = true;
512061da546Spatrick       LLDB_LOG(log,
513061da546Spatrick                "Hit loader breakpoint at address {0:x}, setting initial stop "
514061da546Spatrick                "event.",
515061da546Spatrick                record.GetExceptionAddress());
516061da546Spatrick 
517061da546Spatrick       // We are required to report the reason for the first stop after
518061da546Spatrick       // launching or being attached.
519061da546Spatrick       if (NativeThreadWindows *thread = GetThreadByID(record.GetThreadID()))
520061da546Spatrick         SetStopReasonForThread(*thread, StopReason::eStopReasonBreakpoint);
521061da546Spatrick 
522061da546Spatrick       // Do not notify the native delegate (e.g. llgs) since at this moment
523061da546Spatrick       // the program hasn't returned from Factory::Launch() and the delegate
524061da546Spatrick       // might not have an valid native process to operate on.
525061da546Spatrick       SetState(eStateStopped, false);
526061da546Spatrick 
527061da546Spatrick       // Hit the initial stop. Continue the application.
528061da546Spatrick       return ExceptionResult::BreakInDebugger;
529061da546Spatrick     }
530061da546Spatrick 
531*f6aab3d8Srobert     [[fallthrough]];
532061da546Spatrick   default:
533061da546Spatrick     LLDB_LOG(log,
534061da546Spatrick              "Debugger thread reported exception {0:x} at address {1:x} "
535061da546Spatrick              "(first_chance={2})",
536061da546Spatrick              record.GetExceptionCode(), record.GetExceptionAddress(),
537061da546Spatrick              first_chance);
538061da546Spatrick 
539061da546Spatrick     {
540061da546Spatrick       std::string desc;
541061da546Spatrick       llvm::raw_string_ostream desc_stream(desc);
542061da546Spatrick       desc_stream << "Exception "
543061da546Spatrick                   << llvm::format_hex(record.GetExceptionCode(), 8)
544061da546Spatrick                   << " encountered at address "
545061da546Spatrick                   << llvm::format_hex(record.GetExceptionAddress(), 8);
546061da546Spatrick       StopThread(record.GetThreadID(), StopReason::eStopReasonException,
547061da546Spatrick                  desc_stream.str().c_str());
548061da546Spatrick 
549061da546Spatrick       SetState(eStateStopped, true);
550061da546Spatrick     }
551061da546Spatrick 
552061da546Spatrick     // For non-breakpoints, give the application a chance to handle the
553061da546Spatrick     // exception first.
554061da546Spatrick     if (first_chance)
555061da546Spatrick       result = ExceptionResult::SendToApplication;
556061da546Spatrick     else
557061da546Spatrick       result = ExceptionResult::BreakInDebugger;
558061da546Spatrick   }
559061da546Spatrick 
560061da546Spatrick   return result;
561061da546Spatrick }
562061da546Spatrick 
OnCreateThread(const HostThread & new_thread)563061da546Spatrick void NativeProcessWindows::OnCreateThread(const HostThread &new_thread) {
564061da546Spatrick   llvm::sys::ScopedLock lock(m_mutex);
565061da546Spatrick 
566061da546Spatrick   auto thread = std::make_unique<NativeThreadWindows>(*this, new_thread);
567061da546Spatrick   thread->GetRegisterContext().ClearAllHardwareWatchpoints();
568061da546Spatrick   for (const auto &pair : GetWatchpointMap()) {
569061da546Spatrick     const NativeWatchpoint &wp = pair.second;
570061da546Spatrick     thread->SetWatchpoint(wp.m_addr, wp.m_size, wp.m_watch_flags,
571061da546Spatrick                           wp.m_hardware);
572061da546Spatrick   }
573061da546Spatrick 
574061da546Spatrick   m_threads.push_back(std::move(thread));
575061da546Spatrick }
576061da546Spatrick 
OnExitThread(lldb::tid_t thread_id,uint32_t exit_code)577061da546Spatrick void NativeProcessWindows::OnExitThread(lldb::tid_t thread_id,
578061da546Spatrick                                         uint32_t exit_code) {
579061da546Spatrick   llvm::sys::ScopedLock lock(m_mutex);
580061da546Spatrick   NativeThreadWindows *thread = GetThreadByID(thread_id);
581061da546Spatrick   if (!thread)
582061da546Spatrick     return;
583061da546Spatrick 
584061da546Spatrick   for (auto t = m_threads.begin(); t != m_threads.end();) {
585061da546Spatrick     if ((*t)->GetID() == thread_id) {
586061da546Spatrick       t = m_threads.erase(t);
587061da546Spatrick     } else {
588061da546Spatrick       ++t;
589061da546Spatrick     }
590061da546Spatrick   }
591061da546Spatrick }
592061da546Spatrick 
OnLoadDll(const ModuleSpec & module_spec,lldb::addr_t module_addr)593061da546Spatrick void NativeProcessWindows::OnLoadDll(const ModuleSpec &module_spec,
594061da546Spatrick                                      lldb::addr_t module_addr) {
595061da546Spatrick   // Simply invalidate the cached loaded modules.
596061da546Spatrick   if (!m_loaded_modules.empty())
597061da546Spatrick     m_loaded_modules.clear();
598061da546Spatrick }
599061da546Spatrick 
OnUnloadDll(lldb::addr_t module_addr)600061da546Spatrick void NativeProcessWindows::OnUnloadDll(lldb::addr_t module_addr) {
601061da546Spatrick   if (!m_loaded_modules.empty())
602061da546Spatrick     m_loaded_modules.clear();
603061da546Spatrick }
604061da546Spatrick 
605061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo & launch_info,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const606061da546Spatrick NativeProcessWindows::Factory::Launch(
607061da546Spatrick     ProcessLaunchInfo &launch_info,
608061da546Spatrick     NativeProcessProtocol::NativeDelegate &native_delegate,
609061da546Spatrick     MainLoop &mainloop) const {
610061da546Spatrick   Error E = Error::success();
611061da546Spatrick   auto process_up = std::unique_ptr<NativeProcessWindows>(
612061da546Spatrick       new NativeProcessWindows(launch_info, native_delegate, E));
613061da546Spatrick   if (E)
614061da546Spatrick     return std::move(E);
615061da546Spatrick   return std::move(process_up);
616061da546Spatrick }
617061da546Spatrick 
618061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const619061da546Spatrick NativeProcessWindows::Factory::Attach(
620061da546Spatrick     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
621061da546Spatrick     MainLoop &mainloop) const {
622061da546Spatrick   Error E = Error::success();
623*f6aab3d8Srobert   // Set pty primary fd invalid since it is not available.
624061da546Spatrick   auto process_up = std::unique_ptr<NativeProcessWindows>(
625061da546Spatrick       new NativeProcessWindows(pid, -1, native_delegate, E));
626061da546Spatrick   if (E)
627061da546Spatrick     return std::move(E);
628061da546Spatrick   return std::move(process_up);
629061da546Spatrick }
630061da546Spatrick } // namespace lldb_private
631