xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/OpenBSD/NativeProcessOpenBSD.cpp (revision 101d251d5caf88a9341f3045ab62e122abae1b90)
1061da546Spatrick //===-- NativeProcessOpenBSD.cpp ------------------------------- -*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick //                     The LLVM Compiler Infrastructure
4061da546Spatrick //
5061da546Spatrick // This file is distributed under the University of Illinois Open Source
6061da546Spatrick // License. See LICENSE.TXT for details.
7061da546Spatrick //
8061da546Spatrick //===----------------------------------------------------------------------===//
9061da546Spatrick 
10061da546Spatrick #include "NativeProcessOpenBSD.h"
11061da546Spatrick 
12061da546Spatrick // C Includes
13061da546Spatrick #include <errno.h>
14061da546Spatrick #define _DYN_LOADER
15061da546Spatrick #include <elf.h>
16061da546Spatrick #include <util.h>
17061da546Spatrick 
18061da546Spatrick // C++ Includes
19061da546Spatrick 
20061da546Spatrick #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
21061da546Spatrick #include "lldb/Host/HostProcess.h"
22061da546Spatrick #include "lldb/Host/common/NativeRegisterContext.h"
23061da546Spatrick #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
24061da546Spatrick #include "llvm/Support/Errno.h"
25061da546Spatrick #include "lldb/Target/Process.h"
26061da546Spatrick #include "lldb/Utility/State.h"
27061da546Spatrick 
28061da546Spatrick // System includes - They have to be included after framework includes because
29061da546Spatrick // they define some macros which collide with variable names in other modules
30061da546Spatrick // clang-format off
31061da546Spatrick #include <sys/types.h>
32061da546Spatrick #include <sys/ptrace.h>
33061da546Spatrick #include <sys/sysctl.h>
34061da546Spatrick #include <sys/wait.h>
35061da546Spatrick // clang-format on
36061da546Spatrick 
37061da546Spatrick using namespace lldb;
38061da546Spatrick using namespace lldb_private;
39061da546Spatrick using namespace lldb_private::process_openbsd;
40061da546Spatrick using namespace llvm;
41061da546Spatrick 
42061da546Spatrick // Simple helper function to ensure flags are enabled on the given file
43061da546Spatrick // descriptor.
EnsureFDFlags(int fd,int flags)44061da546Spatrick static Status EnsureFDFlags(int fd, int flags) {
45061da546Spatrick   Status error;
46061da546Spatrick 
47061da546Spatrick   int status = fcntl(fd, F_GETFL);
48061da546Spatrick   if (status == -1) {
49061da546Spatrick     error.SetErrorToErrno();
50061da546Spatrick     return error;
51061da546Spatrick   }
52061da546Spatrick 
53061da546Spatrick   if (fcntl(fd, F_SETFL, status | flags) == -1) {
54061da546Spatrick     error.SetErrorToErrno();
55061da546Spatrick     return error;
56061da546Spatrick   }
57061da546Spatrick 
58061da546Spatrick   return error;
59061da546Spatrick }
60061da546Spatrick 
61061da546Spatrick // -----------------------------------------------------------------------------
62061da546Spatrick // Public Static Methods
63061da546Spatrick // -----------------------------------------------------------------------------
64061da546Spatrick 
65061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo & launch_info,NativeDelegate & native_delegate,MainLoop & mainloop) const66061da546Spatrick NativeProcessOpenBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
67061da546Spatrick                                      NativeDelegate &native_delegate,
68061da546Spatrick                                      MainLoop &mainloop) const {
69*101d251dSrobert   Log *log = GetLog(POSIXLog::Process);
70061da546Spatrick 
71061da546Spatrick   Status status;
72061da546Spatrick   ::pid_t pid = ProcessLauncherPosixFork()
73061da546Spatrick                     .LaunchProcess(launch_info, status)
74061da546Spatrick                     .GetProcessId();
75061da546Spatrick   LLDB_LOG(log, "pid = {0:x}", pid);
76061da546Spatrick   if (status.Fail()) {
77061da546Spatrick     LLDB_LOG(log, "failed to launch process: {0}", status);
78061da546Spatrick     return status.ToError();
79061da546Spatrick   }
80061da546Spatrick 
81061da546Spatrick   // Wait for the child process to trap on its call to execve.
82061da546Spatrick   int wstatus;
83061da546Spatrick   ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
84061da546Spatrick   assert(wpid == pid);
85061da546Spatrick   (void)wpid;
86061da546Spatrick   if (!WIFSTOPPED(wstatus)) {
87061da546Spatrick     LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
88061da546Spatrick              WaitStatus::Decode(wstatus));
89061da546Spatrick     return llvm::make_error<StringError>("Could not sync with inferior process",
90061da546Spatrick                                          llvm::inconvertibleErrorCode());
91061da546Spatrick   }
92061da546Spatrick   LLDB_LOG(log, "inferior started, now in stopped state");
93061da546Spatrick 
94061da546Spatrick   ProcessInstanceInfo Info;
95061da546Spatrick   if (!Host::GetProcessInfo(pid, Info)) {
96061da546Spatrick     return llvm::make_error<StringError>("Cannot get process architecture",
97061da546Spatrick                                          llvm::inconvertibleErrorCode());
98061da546Spatrick   }
99061da546Spatrick 
100061da546Spatrick   // Set the architecture to the exe architecture.
101061da546Spatrick   LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
102061da546Spatrick            Info.GetArchitecture().GetArchitectureName());
103061da546Spatrick 
104061da546Spatrick   std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
105adae0cfdSpatrick       pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
106061da546Spatrick       Info.GetArchitecture(), mainloop));
107061da546Spatrick 
108061da546Spatrick   status = process_up->ReinitializeThreads();
109061da546Spatrick   if (status.Fail())
110061da546Spatrick     return status.ToError();
111061da546Spatrick 
112061da546Spatrick   for (const auto &thread : process_up->m_threads)
113061da546Spatrick     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
114061da546Spatrick   process_up->SetState(StateType::eStateStopped, false);
115061da546Spatrick 
116061da546Spatrick   return std::move(process_up);
117061da546Spatrick }
118061da546Spatrick 
119061da546Spatrick llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const120061da546Spatrick NativeProcessOpenBSD::Factory::Attach(
121061da546Spatrick     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
122061da546Spatrick     MainLoop &mainloop) const {
123061da546Spatrick 
124*101d251dSrobert   Log *log = GetLog(POSIXLog::Process);
125061da546Spatrick   LLDB_LOG(log, "pid = {0:x}", pid);
126061da546Spatrick 
127061da546Spatrick   // Retrieve the architecture for the running process.
128061da546Spatrick   ProcessInstanceInfo Info;
129061da546Spatrick   if (!Host::GetProcessInfo(pid, Info)) {
130061da546Spatrick     return llvm::make_error<StringError>("Cannot get process architecture",
131061da546Spatrick                                          llvm::inconvertibleErrorCode());
132061da546Spatrick   }
133061da546Spatrick 
134061da546Spatrick   std::unique_ptr<NativeProcessOpenBSD> process_up(new NativeProcessOpenBSD(
135061da546Spatrick       pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
136061da546Spatrick 
137061da546Spatrick   Status status = process_up->Attach();
138061da546Spatrick   if (!status.Success())
139061da546Spatrick     return status.ToError();
140061da546Spatrick 
141061da546Spatrick   return std::move(process_up);
142061da546Spatrick }
143061da546Spatrick 
144a0747c9fSpatrick NativeProcessOpenBSD::Extension
GetSupportedExtensions() const145a0747c9fSpatrick NativeProcessOpenBSD::Factory::GetSupportedExtensions() const {
146a0747c9fSpatrick     return Extension::multiprocess | Extension::fork | Extension::vfork |
147a0747c9fSpatrick            Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
148a0747c9fSpatrick }
149a0747c9fSpatrick 
150a0747c9fSpatrick 
151061da546Spatrick // -----------------------------------------------------------------------------
152061da546Spatrick // Public Instance Methods
153061da546Spatrick // -----------------------------------------------------------------------------
154061da546Spatrick 
NativeProcessOpenBSD(::pid_t pid,int terminal_fd,NativeDelegate & delegate,const ArchSpec & arch,MainLoop & mainloop)155061da546Spatrick NativeProcessOpenBSD::NativeProcessOpenBSD(::pid_t pid, int terminal_fd,
156061da546Spatrick                                          NativeDelegate &delegate,
157061da546Spatrick                                          const ArchSpec &arch,
158061da546Spatrick                                          MainLoop &mainloop)
159061da546Spatrick     : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) {
160061da546Spatrick   if (m_terminal_fd != -1) {
161061da546Spatrick     Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
162061da546Spatrick     assert(status.Success());
163061da546Spatrick   }
164061da546Spatrick 
165061da546Spatrick   Status status;
166061da546Spatrick   m_sigchld_handle = mainloop.RegisterSignal(
167061da546Spatrick       SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
168061da546Spatrick   assert(m_sigchld_handle && status.Success());
169061da546Spatrick }
170061da546Spatrick 
171061da546Spatrick // Handles all waitpid events from the inferior process.
MonitorCallback(lldb::pid_t pid,int signal)172061da546Spatrick void NativeProcessOpenBSD::MonitorCallback(lldb::pid_t pid, int signal) {
173061da546Spatrick   switch (signal) {
174061da546Spatrick     case SIGTRAP:
175061da546Spatrick       return MonitorSIGTRAP(pid);
176061da546Spatrick     default:
177061da546Spatrick       return MonitorSignal(pid, signal);
178061da546Spatrick   }
179061da546Spatrick }
180061da546Spatrick 
MonitorExited(lldb::pid_t pid,WaitStatus status)181061da546Spatrick void NativeProcessOpenBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
182*101d251dSrobert   Log *log = GetLog(POSIXLog::Process);
183061da546Spatrick 
184061da546Spatrick   LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
185061da546Spatrick 
186061da546Spatrick   /* Stop Tracking All Threads attached to Process */
187061da546Spatrick   m_threads.clear();
188061da546Spatrick 
189061da546Spatrick   SetExitStatus(status, true);
190061da546Spatrick 
191061da546Spatrick   // Notify delegate that our process has exited.
192061da546Spatrick   SetState(StateType::eStateExited, true);
193061da546Spatrick }
194061da546Spatrick 
MonitorSIGTRAP(lldb::pid_t pid)195061da546Spatrick void NativeProcessOpenBSD::MonitorSIGTRAP(lldb::pid_t pid) {
196061da546Spatrick   for (const auto &thread : m_threads) {
197061da546Spatrick     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedByBreakpoint();
198061da546Spatrick     FixupBreakpointPCAsNeeded(static_cast<NativeThreadOpenBSD &>(*thread));
199061da546Spatrick   }
200061da546Spatrick   SetState(StateType::eStateStopped, true);
201061da546Spatrick }
202061da546Spatrick 
203061da546Spatrick 
MonitorSignal(lldb::pid_t pid,int signal)204061da546Spatrick void NativeProcessOpenBSD::MonitorSignal(lldb::pid_t pid, int signal) {
205061da546Spatrick   for (const auto &thread : m_threads) {
206061da546Spatrick     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(signal);
207061da546Spatrick   }
208061da546Spatrick   SetState(StateType::eStateStopped, true);
209061da546Spatrick }
210061da546Spatrick 
PtraceWrapper(int req,lldb::pid_t pid,void * addr,int data,int * result)211061da546Spatrick Status NativeProcessOpenBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
212061da546Spatrick                                           int data, int *result) {
213*101d251dSrobert   Log *log = GetLog(POSIXLog::Process);
214061da546Spatrick   Status error;
215061da546Spatrick   int ret;
216061da546Spatrick 
217061da546Spatrick   errno = 0;
218061da546Spatrick   ret = ptrace(req, static_cast<::pid_t>(pid), (caddr_t)addr, data);
219061da546Spatrick 
220061da546Spatrick   if (ret == -1)
221061da546Spatrick     error.SetErrorToErrno();
222061da546Spatrick 
223061da546Spatrick   if (result)
224061da546Spatrick     *result = ret;
225061da546Spatrick 
226061da546Spatrick   LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
227061da546Spatrick 
228061da546Spatrick   if (error.Fail())
229061da546Spatrick     LLDB_LOG(log, "ptrace() failed: {0}", error);
230061da546Spatrick 
231061da546Spatrick   return error;
232061da546Spatrick }
233061da546Spatrick 
Resume(const ResumeActionList & resume_actions)234061da546Spatrick Status NativeProcessOpenBSD::Resume(const ResumeActionList &resume_actions) {
235*101d251dSrobert   Log *log = GetLog(POSIXLog::Process);
236061da546Spatrick   LLDB_LOG(log, "pid {0}", GetID());
237061da546Spatrick 
238061da546Spatrick   const auto &thread = m_threads[0];
239061da546Spatrick   const ResumeAction *const action =
240061da546Spatrick       resume_actions.GetActionForThread(thread->GetID(), true);
241061da546Spatrick 
242061da546Spatrick   if (action == nullptr) {
243061da546Spatrick     LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
244061da546Spatrick              thread->GetID());
245061da546Spatrick     return Status();
246061da546Spatrick   }
247061da546Spatrick 
248061da546Spatrick   Status error;
249972f549bSmortimer   int signal = action->signal != LLDB_INVALID_SIGNAL_NUMBER ? action->signal : 0;
250061da546Spatrick 
251061da546Spatrick   switch (action->state) {
252061da546Spatrick   case eStateRunning: {
253061da546Spatrick     // Run the thread, possibly feeding it the signal.
254061da546Spatrick     error = NativeProcessOpenBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
255972f549bSmortimer                                                signal);
256061da546Spatrick     if (!error.Success())
257061da546Spatrick       return error;
258061da546Spatrick     for (const auto &thread : m_threads)
259061da546Spatrick       static_cast<NativeThreadOpenBSD &>(*thread).SetRunning();
260061da546Spatrick     SetState(eStateRunning, true);
261061da546Spatrick     break;
262061da546Spatrick   }
263061da546Spatrick   case eStateStepping:
264061da546Spatrick #ifdef PT_STEP
265061da546Spatrick     // Run the thread, possibly feeding it the signal.
266061da546Spatrick     error = NativeProcessOpenBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
267972f549bSmortimer                                                signal);
268061da546Spatrick     if (!error.Success())
269061da546Spatrick       return error;
270061da546Spatrick     for (const auto &thread : m_threads)
271061da546Spatrick       static_cast<NativeThreadOpenBSD &>(*thread).SetStepping();
272061da546Spatrick     SetState(eStateStepping, true);
273061da546Spatrick     break;
274061da546Spatrick #else
275061da546Spatrick     return Status("NativeProcessOpenBSD stepping not supported on this platform");
276061da546Spatrick #endif
277061da546Spatrick 
278061da546Spatrick   case eStateSuspended:
279061da546Spatrick   case eStateStopped:
280061da546Spatrick     llvm_unreachable("Unexpected state");
281061da546Spatrick 
282061da546Spatrick   default:
283061da546Spatrick     return Status("NativeProcessOpenBSD::%s (): unexpected state %s specified "
284061da546Spatrick                   "for pid %" PRIu64 ", tid %" PRIu64,
285061da546Spatrick                   __FUNCTION__, StateAsCString(action->state), GetID(),
286061da546Spatrick                   thread->GetID());
287061da546Spatrick   }
288061da546Spatrick 
289061da546Spatrick   return Status();
290061da546Spatrick }
291061da546Spatrick 
Halt()292061da546Spatrick Status NativeProcessOpenBSD::Halt() {
293061da546Spatrick   Status error;
294061da546Spatrick 
295061da546Spatrick   if (kill(GetID(), SIGSTOP) != 0)
296061da546Spatrick     error.SetErrorToErrno();
297061da546Spatrick 
298061da546Spatrick   return error;
299061da546Spatrick }
300061da546Spatrick 
Detach()301061da546Spatrick Status NativeProcessOpenBSD::Detach() {
302061da546Spatrick   Status error;
303061da546Spatrick 
304061da546Spatrick   // Stop monitoring the inferior.
305061da546Spatrick   m_sigchld_handle.reset();
306061da546Spatrick 
307061da546Spatrick   // Tell ptrace to detach from the process.
308061da546Spatrick   if (GetID() == LLDB_INVALID_PROCESS_ID)
309061da546Spatrick     return error;
310061da546Spatrick 
311061da546Spatrick   return PtraceWrapper(PT_DETACH, GetID());
312061da546Spatrick }
313061da546Spatrick 
Signal(int signo)314061da546Spatrick Status NativeProcessOpenBSD::Signal(int signo) {
315061da546Spatrick   Status error;
316061da546Spatrick 
317061da546Spatrick   if (kill(GetID(), signo))
318061da546Spatrick     error.SetErrorToErrno();
319061da546Spatrick 
320061da546Spatrick   return error;
321061da546Spatrick }
322061da546Spatrick 
Kill()323061da546Spatrick Status NativeProcessOpenBSD::Kill() {
324*101d251dSrobert   Log *log = GetLog(POSIXLog::Process);
325061da546Spatrick   LLDB_LOG(log, "pid {0}", GetID());
326061da546Spatrick 
327061da546Spatrick   Status error;
328061da546Spatrick 
329061da546Spatrick   switch (m_state) {
330061da546Spatrick   case StateType::eStateInvalid:
331061da546Spatrick   case StateType::eStateExited:
332061da546Spatrick   case StateType::eStateCrashed:
333061da546Spatrick   case StateType::eStateDetached:
334061da546Spatrick   case StateType::eStateUnloaded:
335061da546Spatrick     // Nothing to do - the process is already dead.
336061da546Spatrick     LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
337061da546Spatrick              StateAsCString(m_state));
338061da546Spatrick     return error;
339061da546Spatrick 
340061da546Spatrick   case StateType::eStateConnected:
341061da546Spatrick   case StateType::eStateAttaching:
342061da546Spatrick   case StateType::eStateLaunching:
343061da546Spatrick   case StateType::eStateStopped:
344061da546Spatrick   case StateType::eStateRunning:
345061da546Spatrick   case StateType::eStateStepping:
346061da546Spatrick   case StateType::eStateSuspended:
347061da546Spatrick     // We can try to kill a process in these states.
348061da546Spatrick     break;
349061da546Spatrick   }
350061da546Spatrick 
351061da546Spatrick   if (kill(GetID(), SIGKILL) != 0) {
352061da546Spatrick     error.SetErrorToErrno();
353061da546Spatrick     return error;
354061da546Spatrick   }
355061da546Spatrick 
356061da546Spatrick   return error;
357061da546Spatrick }
358061da546Spatrick 
GetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & range_info)359061da546Spatrick Status NativeProcessOpenBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
360061da546Spatrick                                                 MemoryRegionInfo &range_info) {
361061da546Spatrick   return Status("Unimplemented");
362061da546Spatrick }
363061da546Spatrick 
PopulateMemoryRegionCache()364061da546Spatrick Status NativeProcessOpenBSD::PopulateMemoryRegionCache() {
365061da546Spatrick   return Status("Unimplemented");
366061da546Spatrick }
367061da546Spatrick 
AllocateMemory(size_t size,uint32_t permissions)368a0747c9fSpatrick llvm::Expected<lldb::addr_t> NativeProcessOpenBSD::AllocateMemory(size_t size,
369a0747c9fSpatrick                                                                  uint32_t permissions) {
370a0747c9fSpatrick   return llvm::make_error<UnimplementedError>();
371061da546Spatrick }
372061da546Spatrick 
DeallocateMemory(lldb::addr_t addr)373a0747c9fSpatrick llvm::Error NativeProcessOpenBSD::DeallocateMemory(lldb::addr_t addr) {
374a0747c9fSpatrick   return llvm::make_error<UnimplementedError>();
375061da546Spatrick }
376061da546Spatrick 
GetSharedLibraryInfoAddress()377061da546Spatrick lldb::addr_t NativeProcessOpenBSD::GetSharedLibraryInfoAddress() {
378061da546Spatrick   // punt on this for now
379061da546Spatrick   return LLDB_INVALID_ADDRESS;
380061da546Spatrick }
381061da546Spatrick 
UpdateThreads()382061da546Spatrick size_t NativeProcessOpenBSD::UpdateThreads() { return m_threads.size(); }
383061da546Spatrick 
SetBreakpoint(lldb::addr_t addr,uint32_t size,bool hardware)384061da546Spatrick Status NativeProcessOpenBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
385061da546Spatrick                                           bool hardware) {
386061da546Spatrick   if (hardware)
387061da546Spatrick     return Status("NativeProcessOpenBSD does not support hardware breakpoints");
388061da546Spatrick   else
389061da546Spatrick     return SetSoftwareBreakpoint(addr, size);
390061da546Spatrick }
391061da546Spatrick 
GetLoadedModuleFileSpec(const char * module_path,FileSpec & file_spec)392061da546Spatrick Status NativeProcessOpenBSD::GetLoadedModuleFileSpec(const char *module_path,
393061da546Spatrick                                                     FileSpec &file_spec) {
394061da546Spatrick   return Status("Unimplemented");
395061da546Spatrick }
396061da546Spatrick 
GetFileLoadAddress(const llvm::StringRef & file_name,lldb::addr_t & load_addr)397061da546Spatrick Status NativeProcessOpenBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
398061da546Spatrick                                                lldb::addr_t &load_addr) {
399061da546Spatrick   load_addr = LLDB_INVALID_ADDRESS;
400061da546Spatrick   return Status();
401061da546Spatrick }
402061da546Spatrick 
SigchldHandler()403061da546Spatrick void NativeProcessOpenBSD::SigchldHandler() {
404*101d251dSrobert   Log *log = GetLog(POSIXLog::Process);
405061da546Spatrick   // Process all pending waitpid notifications.
406061da546Spatrick   int status;
407061da546Spatrick   ::pid_t wait_pid =
408061da546Spatrick       llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WNOHANG);
409061da546Spatrick 
410061da546Spatrick   if (wait_pid == 0)
411061da546Spatrick     return; // We are done.
412061da546Spatrick 
413061da546Spatrick   if (wait_pid == -1) {
414061da546Spatrick     Status error(errno, eErrorTypePOSIX);
415061da546Spatrick     LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
416061da546Spatrick   }
417061da546Spatrick 
418061da546Spatrick   WaitStatus wait_status = WaitStatus::Decode(status);
419061da546Spatrick   bool exited = wait_status.type == WaitStatus::Exit ||
420061da546Spatrick                 (wait_status.type == WaitStatus::Signal &&
421061da546Spatrick                  wait_pid == static_cast<::pid_t>(GetID()));
422061da546Spatrick 
423061da546Spatrick   LLDB_LOG(log,
424061da546Spatrick            "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
425061da546Spatrick            GetID(), wait_pid, status, exited);
426061da546Spatrick 
427061da546Spatrick   if (exited)
428061da546Spatrick     MonitorExited(wait_pid, wait_status);
429061da546Spatrick   else {
430061da546Spatrick     assert(wait_status.type == WaitStatus::Stop);
431061da546Spatrick     MonitorCallback(wait_pid, wait_status.status);
432061da546Spatrick   }
433061da546Spatrick }
434061da546Spatrick 
HasThreadNoLock(lldb::tid_t thread_id)435061da546Spatrick bool NativeProcessOpenBSD::HasThreadNoLock(lldb::tid_t thread_id) {
436061da546Spatrick   for (const auto &thread : m_threads) {
437061da546Spatrick     assert(thread && "thread list should not contain NULL threads");
438061da546Spatrick     if (thread->GetID() == thread_id) {
439061da546Spatrick       // We have this thread.
440061da546Spatrick       return true;
441061da546Spatrick     }
442061da546Spatrick   }
443061da546Spatrick 
444061da546Spatrick   // We don't have this thread.
445061da546Spatrick   return false;
446061da546Spatrick }
447061da546Spatrick 
AddThread(lldb::tid_t thread_id)448061da546Spatrick NativeThreadOpenBSD &NativeProcessOpenBSD::AddThread(lldb::tid_t thread_id) {
449061da546Spatrick 
450*101d251dSrobert   Log *log = GetLog(POSIXLog::Thread);
451061da546Spatrick   LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
452061da546Spatrick 
453061da546Spatrick   assert(!HasThreadNoLock(thread_id) &&
454061da546Spatrick          "attempted to add a thread by id that already exists");
455061da546Spatrick 
456061da546Spatrick   // If this is the first thread, save it as the current thread
457061da546Spatrick   if (m_threads.empty())
458061da546Spatrick     SetCurrentThreadID(thread_id);
459061da546Spatrick 
460061da546Spatrick   m_threads.push_back(std::make_unique<NativeThreadOpenBSD>(*this, thread_id));
461061da546Spatrick   return static_cast<NativeThreadOpenBSD &>(*m_threads.back());
462061da546Spatrick }
463061da546Spatrick 
Attach()464061da546Spatrick Status NativeProcessOpenBSD::Attach() {
465061da546Spatrick   // Attach to the requested process.
466061da546Spatrick   // An attach will cause the thread to stop with a SIGSTOP.
467061da546Spatrick   Status status = PtraceWrapper(PT_ATTACH, m_pid);
468061da546Spatrick   if (status.Fail())
469061da546Spatrick     return status;
470061da546Spatrick 
471061da546Spatrick   int wstatus;
472061da546Spatrick   // At this point we should have a thread stopped if waitpid succeeds.
473061da546Spatrick   if ((wstatus = waitpid(m_pid, NULL, 0)) < 0)
474061da546Spatrick     return Status(errno, eErrorTypePOSIX);
475061da546Spatrick 
476061da546Spatrick   /* Initialize threads */
477061da546Spatrick   status = ReinitializeThreads();
478061da546Spatrick   if (status.Fail())
479061da546Spatrick     return status;
480061da546Spatrick 
481061da546Spatrick   for (const auto &thread : m_threads)
482061da546Spatrick     static_cast<NativeThreadOpenBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
483061da546Spatrick 
484061da546Spatrick   // Let our process instance know the thread has stopped.
485061da546Spatrick   SetState(StateType::eStateStopped);
486061da546Spatrick   return Status();
487061da546Spatrick }
488061da546Spatrick 
ReadMemory(lldb::addr_t addr,void * buf,size_t size,size_t & bytes_read)489061da546Spatrick Status NativeProcessOpenBSD::ReadMemory(lldb::addr_t addr, void *buf,
490061da546Spatrick                                        size_t size, size_t &bytes_read) {
491061da546Spatrick   unsigned char *dst = static_cast<unsigned char *>(buf);
492061da546Spatrick   struct ptrace_io_desc io;
493061da546Spatrick 
494*101d251dSrobert   Log *log = GetLog(POSIXLog::Memory);
495061da546Spatrick   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
496061da546Spatrick 
497061da546Spatrick   bytes_read = 0;
498061da546Spatrick   io.piod_op = PIOD_READ_D;
499061da546Spatrick   io.piod_len = size;
500061da546Spatrick 
501061da546Spatrick   do {
502061da546Spatrick     io.piod_offs = (void *)(addr + bytes_read);
503061da546Spatrick     io.piod_addr = dst + bytes_read;
504061da546Spatrick 
505061da546Spatrick     Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
506061da546Spatrick     if (error.Fail())
507061da546Spatrick       return error;
508061da546Spatrick 
509061da546Spatrick     bytes_read = io.piod_len;
510061da546Spatrick     io.piod_len = size - bytes_read;
511061da546Spatrick   } while (bytes_read < size);
512061da546Spatrick 
513061da546Spatrick   return Status();
514061da546Spatrick }
515061da546Spatrick 
WriteMemory(lldb::addr_t addr,const void * buf,size_t size,size_t & bytes_written)516061da546Spatrick Status NativeProcessOpenBSD::WriteMemory(lldb::addr_t addr, const void *buf,
517061da546Spatrick                                         size_t size, size_t &bytes_written) {
518061da546Spatrick   const unsigned char *src = static_cast<const unsigned char *>(buf);
519061da546Spatrick   Status error;
520061da546Spatrick   struct ptrace_io_desc io;
521061da546Spatrick 
522*101d251dSrobert   Log *log = GetLog(POSIXLog::Memory);
523061da546Spatrick   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
524061da546Spatrick 
525061da546Spatrick   bytes_written = 0;
526061da546Spatrick   io.piod_op = PIOD_WRITE_D;
527061da546Spatrick   io.piod_len = size;
528061da546Spatrick 
529061da546Spatrick   do {
530061da546Spatrick     io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
531061da546Spatrick     io.piod_offs = (void *)(addr + bytes_written);
532061da546Spatrick 
533061da546Spatrick     Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
534061da546Spatrick     if (error.Fail())
535061da546Spatrick       return error;
536061da546Spatrick 
537061da546Spatrick     bytes_written = io.piod_len;
538061da546Spatrick     io.piod_len = size - bytes_written;
539061da546Spatrick   } while (bytes_written < size);
540061da546Spatrick 
541061da546Spatrick   return error;
542061da546Spatrick }
543061da546Spatrick 
544061da546Spatrick llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
GetAuxvData() const545061da546Spatrick NativeProcessOpenBSD::GetAuxvData() const {
546061da546Spatrick   size_t auxv_size = 100 * sizeof(AuxInfo);
547061da546Spatrick 
548061da546Spatrick   ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
549061da546Spatrick       llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
550061da546Spatrick 
551061da546Spatrick   struct ptrace_io_desc io;
552061da546Spatrick   io.piod_op = PIOD_READ_AUXV;
553061da546Spatrick   io.piod_offs = 0;
554061da546Spatrick   io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
555061da546Spatrick   io.piod_len = auxv_size;
556061da546Spatrick 
557061da546Spatrick   Status error = NativeProcessOpenBSD::PtraceWrapper(PT_IO, GetID(), &io);
558061da546Spatrick 
559061da546Spatrick   if (error.Fail())
560061da546Spatrick     return std::error_code(error.GetError(), std::generic_category());
561061da546Spatrick 
562061da546Spatrick   if (io.piod_len < 1)
563061da546Spatrick     return std::error_code(ECANCELED, std::generic_category());
564061da546Spatrick 
565061da546Spatrick   return std::move(buf);
566061da546Spatrick }
567061da546Spatrick 
ReinitializeThreads()568061da546Spatrick Status NativeProcessOpenBSD::ReinitializeThreads() {
569061da546Spatrick   // Clear old threads
570061da546Spatrick   m_threads.clear();
571061da546Spatrick 
572061da546Spatrick   // Initialize new thread
573061da546Spatrick   struct ptrace_thread_state info = {};
574061da546Spatrick   Status error = PtraceWrapper(PT_GET_THREAD_FIRST, GetID(), &info, sizeof(info));
575061da546Spatrick   if (error.Fail()) {
576061da546Spatrick     return error;
577061da546Spatrick   }
578061da546Spatrick   // Reinitialize from scratch threads and register them in process
579061da546Spatrick   while (info.pts_tid > 0) {
580061da546Spatrick     AddThread(info.pts_tid);
581061da546Spatrick     error = PtraceWrapper(PT_GET_THREAD_NEXT, GetID(), &info, sizeof(info));
582061da546Spatrick     if (error.Fail() && errno != 0) {
583061da546Spatrick       return error;
584061da546Spatrick     }
585061da546Spatrick   }
586061da546Spatrick 
587061da546Spatrick   return error;
588061da546Spatrick }
589