1 //===-- NativeProcessNetBSD.cpp ------------------------------- -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "NativeProcessNetBSD.h"
11 
12 // C Includes
13 
14 // C++ Includes
15 
16 // Other libraries and framework includes
17 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
18 #include "lldb/Host/HostProcess.h"
19 #include "lldb/Host/common/NativeBreakpoint.h"
20 #include "lldb/Host/common/NativeRegisterContext.h"
21 #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Utility/State.h"
24 #include "llvm/Support/Errno.h"
25 
26 // System includes - They have to be included after framework includes because
27 // they define some macros which collide with variable names in other modules
28 // clang-format off
29 #include <sys/types.h>
30 #include <sys/ptrace.h>
31 #include <sys/sysctl.h>
32 #include <sys/wait.h>
33 #include <uvm/uvm_prot.h>
34 #include <elf.h>
35 #include <util.h>
36 // clang-format on
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 using namespace lldb_private::process_netbsd;
41 using namespace llvm;
42 
43 // Simple helper function to ensure flags are enabled on the given file
44 // descriptor.
45 static Status EnsureFDFlags(int fd, int flags) {
46   Status error;
47 
48   int status = fcntl(fd, F_GETFL);
49   if (status == -1) {
50     error.SetErrorToErrno();
51     return error;
52   }
53 
54   if (fcntl(fd, F_SETFL, status | flags) == -1) {
55     error.SetErrorToErrno();
56     return error;
57   }
58 
59   return error;
60 }
61 
62 // -----------------------------------------------------------------------------
63 // Public Static Methods
64 // -----------------------------------------------------------------------------
65 
66 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
67 NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
68                                      NativeDelegate &native_delegate,
69                                      MainLoop &mainloop) const {
70   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
71 
72   Status status;
73   ::pid_t pid = ProcessLauncherPosixFork()
74                     .LaunchProcess(launch_info, status)
75                     .GetProcessId();
76   LLDB_LOG(log, "pid = {0:x}", pid);
77   if (status.Fail()) {
78     LLDB_LOG(log, "failed to launch process: {0}", status);
79     return status.ToError();
80   }
81 
82   // Wait for the child process to trap on its call to execve.
83   int wstatus;
84   ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
85   assert(wpid == pid);
86   (void)wpid;
87   if (!WIFSTOPPED(wstatus)) {
88     LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
89              WaitStatus::Decode(wstatus));
90     return llvm::make_error<StringError>("Could not sync with inferior process",
91                                          llvm::inconvertibleErrorCode());
92   }
93   LLDB_LOG(log, "inferior started, now in stopped state");
94 
95   ProcessInstanceInfo Info;
96   if (!Host::GetProcessInfo(pid, Info)) {
97     return llvm::make_error<StringError>("Cannot get process architecture",
98                                          llvm::inconvertibleErrorCode());
99   }
100 
101   // Set the architecture to the exe architecture.
102   LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
103            Info.GetArchitecture().GetArchitectureName());
104 
105   std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
106       pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
107       Info.GetArchitecture(), mainloop));
108 
109   status = process_up->ReinitializeThreads();
110   if (status.Fail())
111     return status.ToError();
112 
113   for (const auto &thread : process_up->m_threads)
114     static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
115   process_up->SetState(StateType::eStateStopped, false);
116 
117   return std::move(process_up);
118 }
119 
120 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
121 NativeProcessNetBSD::Factory::Attach(
122     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
123     MainLoop &mainloop) const {
124   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
125   LLDB_LOG(log, "pid = {0:x}", pid);
126 
127   // Retrieve the architecture for the running process.
128   ProcessInstanceInfo Info;
129   if (!Host::GetProcessInfo(pid, Info)) {
130     return llvm::make_error<StringError>("Cannot get process architecture",
131                                          llvm::inconvertibleErrorCode());
132   }
133 
134   std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
135       pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
136 
137   Status status = process_up->Attach();
138   if (!status.Success())
139     return status.ToError();
140 
141   return std::move(process_up);
142 }
143 
144 // -----------------------------------------------------------------------------
145 // Public Instance Methods
146 // -----------------------------------------------------------------------------
147 
148 NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
149                                          NativeDelegate &delegate,
150                                          const ArchSpec &arch,
151                                          MainLoop &mainloop)
152     : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch) {
153   if (m_terminal_fd != -1) {
154     Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
155     assert(status.Success());
156   }
157 
158   Status status;
159   m_sigchld_handle = mainloop.RegisterSignal(
160       SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
161   assert(m_sigchld_handle && status.Success());
162 }
163 
164 // Handles all waitpid events from the inferior process.
165 void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
166   switch (signal) {
167   case SIGTRAP:
168     return MonitorSIGTRAP(pid);
169   case SIGSTOP:
170     return MonitorSIGSTOP(pid);
171   default:
172     return MonitorSignal(pid, signal);
173   }
174 }
175 
176 void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
177   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
178 
179   LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
180 
181   /* Stop Tracking All Threads attached to Process */
182   m_threads.clear();
183 
184   SetExitStatus(status, true);
185 
186   // Notify delegate that our process has exited.
187   SetState(StateType::eStateExited, true);
188 }
189 
190 void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
191   ptrace_siginfo_t info;
192 
193   const auto siginfo_err =
194       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
195 
196   // Get details on the signal raised.
197   if (siginfo_err.Success()) {
198     // Handle SIGSTOP from LLGS (LLDB GDB Server)
199     if (info.psi_siginfo.si_code == SI_USER &&
200         info.psi_siginfo.si_pid == ::getpid()) {
201       /* Stop Tracking all Threads attached to Process */
202       for (const auto &thread : m_threads) {
203         static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
204             SIGSTOP, &info.psi_siginfo);
205       }
206     }
207   }
208 }
209 
210 void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
211   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
212   ptrace_siginfo_t info;
213 
214   const auto siginfo_err =
215       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
216 
217   // Get details on the signal raised.
218   if (siginfo_err.Fail()) {
219     return;
220   }
221 
222   switch (info.psi_siginfo.si_code) {
223   case TRAP_BRKPT:
224     for (const auto &thread : m_threads) {
225       static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
226       FixupBreakpointPCAsNeeded(static_cast<NativeThreadNetBSD &>(*thread));
227     }
228     SetState(StateType::eStateStopped, true);
229     break;
230   case TRAP_TRACE:
231     for (const auto &thread : m_threads)
232       static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByTrace();
233     SetState(StateType::eStateStopped, true);
234     break;
235   case TRAP_EXEC: {
236     Status error = ReinitializeThreads();
237     if (error.Fail()) {
238       SetState(StateType::eStateInvalid);
239       return;
240     }
241 
242     // Let our delegate know we have just exec'd.
243     NotifyDidExec();
244 
245     for (const auto &thread : m_threads)
246       static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
247     SetState(StateType::eStateStopped, true);
248   } break;
249   case TRAP_DBREG: {
250     // If a watchpoint was hit, report it
251     uint32_t wp_index;
252     Status error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid])
253                        .GetRegisterContext()
254                        .GetWatchpointHitIndex(
255                            wp_index, (uintptr_t)info.psi_siginfo.si_addr);
256     if (error.Fail())
257       LLDB_LOG(log,
258                "received error while checking for watchpoint hits, pid = "
259                "{0}, LWP = {1}, error = {2}",
260                GetID(), info.psi_lwpid, error);
261     if (wp_index != LLDB_INVALID_INDEX32) {
262       for (const auto &thread : m_threads)
263         static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByWatchpoint(
264             wp_index);
265       SetState(StateType::eStateStopped, true);
266       break;
267     }
268 
269     // If a breakpoint was hit, report it
270     uint32_t bp_index;
271     error = static_cast<NativeThreadNetBSD &>(*m_threads[info.psi_lwpid])
272                 .GetRegisterContext()
273                 .GetHardwareBreakHitIndex(bp_index,
274                                            (uintptr_t)info.psi_siginfo.si_addr);
275     if (error.Fail())
276       LLDB_LOG(log,
277                "received error while checking for hardware "
278                "breakpoint hits, pid = {0}, LWP = {1}, error = {2}",
279                GetID(), info.psi_lwpid, error);
280     if (bp_index != LLDB_INVALID_INDEX32) {
281       for (const auto &thread : m_threads)
282         static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByBreakpoint();
283       SetState(StateType::eStateStopped, true);
284       break;
285     }
286   } break;
287   }
288 }
289 
290 void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
291   ptrace_siginfo_t info;
292   const auto siginfo_err =
293       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
294 
295   for (const auto &thread : m_threads) {
296     static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
297         info.psi_siginfo.si_signo, &info.psi_siginfo);
298   }
299   SetState(StateType::eStateStopped, true);
300 }
301 
302 Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
303                                           int data, int *result) {
304   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
305   Status error;
306   int ret;
307 
308   errno = 0;
309   ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);
310 
311   if (ret == -1)
312     error.SetErrorToErrno();
313 
314   if (result)
315     *result = ret;
316 
317   LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
318 
319   if (error.Fail())
320     LLDB_LOG(log, "ptrace() failed: {0}", error);
321 
322   return error;
323 }
324 
325 Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
326   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
327   LLDB_LOG(log, "pid {0}", GetID());
328 
329   const auto &thread = m_threads[0];
330   const ResumeAction *const action =
331       resume_actions.GetActionForThread(thread->GetID(), true);
332 
333   if (action == nullptr) {
334     LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
335              thread->GetID());
336     return Status();
337   }
338 
339   Status error;
340 
341   switch (action->state) {
342   case eStateRunning: {
343     // Run the thread, possibly feeding it the signal.
344     error = NativeProcessNetBSD::PtraceWrapper(PT_CONTINUE, GetID(), (void *)1,
345                                                action->signal);
346     if (!error.Success())
347       return error;
348     for (const auto &thread : m_threads)
349       static_cast<NativeThreadNetBSD &>(*thread).SetRunning();
350     SetState(eStateRunning, true);
351     break;
352   }
353   case eStateStepping:
354     // Run the thread, possibly feeding it the signal.
355     error = NativeProcessNetBSD::PtraceWrapper(PT_STEP, GetID(), (void *)1,
356                                                action->signal);
357     if (!error.Success())
358       return error;
359     for (const auto &thread : m_threads)
360       static_cast<NativeThreadNetBSD &>(*thread).SetStepping();
361     SetState(eStateStepping, true);
362     break;
363 
364   case eStateSuspended:
365   case eStateStopped:
366     llvm_unreachable("Unexpected state");
367 
368   default:
369     return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
370                   "for pid %" PRIu64 ", tid %" PRIu64,
371                   __FUNCTION__, StateAsCString(action->state), GetID(),
372                   thread->GetID());
373   }
374 
375   return Status();
376 }
377 
378 Status NativeProcessNetBSD::Halt() {
379   Status error;
380 
381   if (kill(GetID(), SIGSTOP) != 0)
382     error.SetErrorToErrno();
383 
384   return error;
385 }
386 
387 Status NativeProcessNetBSD::Detach() {
388   Status error;
389 
390   // Stop monitoring the inferior.
391   m_sigchld_handle.reset();
392 
393   // Tell ptrace to detach from the process.
394   if (GetID() == LLDB_INVALID_PROCESS_ID)
395     return error;
396 
397   return PtraceWrapper(PT_DETACH, GetID());
398 }
399 
400 Status NativeProcessNetBSD::Signal(int signo) {
401   Status error;
402 
403   if (kill(GetID(), signo))
404     error.SetErrorToErrno();
405 
406   return error;
407 }
408 
409 Status NativeProcessNetBSD::Kill() {
410   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
411   LLDB_LOG(log, "pid {0}", GetID());
412 
413   Status error;
414 
415   switch (m_state) {
416   case StateType::eStateInvalid:
417   case StateType::eStateExited:
418   case StateType::eStateCrashed:
419   case StateType::eStateDetached:
420   case StateType::eStateUnloaded:
421     // Nothing to do - the process is already dead.
422     LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
423              StateAsCString(m_state));
424     return error;
425 
426   case StateType::eStateConnected:
427   case StateType::eStateAttaching:
428   case StateType::eStateLaunching:
429   case StateType::eStateStopped:
430   case StateType::eStateRunning:
431   case StateType::eStateStepping:
432   case StateType::eStateSuspended:
433     // We can try to kill a process in these states.
434     break;
435   }
436 
437   if (kill(GetID(), SIGKILL) != 0) {
438     error.SetErrorToErrno();
439     return error;
440   }
441 
442   return error;
443 }
444 
445 Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
446                                                 MemoryRegionInfo &range_info) {
447 
448   if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
449     // We're done.
450     return Status("unsupported");
451   }
452 
453   Status error = PopulateMemoryRegionCache();
454   if (error.Fail()) {
455     return error;
456   }
457 
458   lldb::addr_t prev_base_address = 0;
459   // FIXME start by finding the last region that is <= target address using
460   // binary search.  Data is sorted.
461   // There can be a ton of regions on pthreads apps with lots of threads.
462   for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
463        ++it) {
464     MemoryRegionInfo &proc_entry_info = it->first;
465     // Sanity check assumption that memory map entries are ascending.
466     assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
467            "descending memory map entries detected, unexpected");
468     prev_base_address = proc_entry_info.GetRange().GetRangeBase();
469     UNUSED_IF_ASSERT_DISABLED(prev_base_address);
470     // If the target address comes before this entry, indicate distance to next
471     // region.
472     if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
473       range_info.GetRange().SetRangeBase(load_addr);
474       range_info.GetRange().SetByteSize(
475           proc_entry_info.GetRange().GetRangeBase() - load_addr);
476       range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
477       range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
478       range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
479       range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
480       return error;
481     } else if (proc_entry_info.GetRange().Contains(load_addr)) {
482       // The target address is within the memory region we're processing here.
483       range_info = proc_entry_info;
484       return error;
485     }
486     // The target memory address comes somewhere after the region we just
487     // parsed.
488   }
489   // If we made it here, we didn't find an entry that contained the given
490   // address. Return the load_addr as start and the amount of bytes betwwen
491   // load address and the end of the memory as size.
492   range_info.GetRange().SetRangeBase(load_addr);
493   range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
494   range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
495   range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
496   range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
497   range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
498   return error;
499 }
500 
501 Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
502   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
503   // If our cache is empty, pull the latest.  There should always be at least
504   // one memory region if memory region handling is supported.
505   if (!m_mem_region_cache.empty()) {
506     LLDB_LOG(log, "reusing {0} cached memory region entries",
507              m_mem_region_cache.size());
508     return Status();
509   }
510 
511   struct kinfo_vmentry *vm;
512   size_t count, i;
513   vm = kinfo_getvmmap(GetID(), &count);
514   if (vm == NULL) {
515     m_supports_mem_region = LazyBool::eLazyBoolNo;
516     Status error;
517     error.SetErrorString("not supported");
518     return error;
519   }
520   for (i = 0; i < count; i++) {
521     MemoryRegionInfo info;
522     info.Clear();
523     info.GetRange().SetRangeBase(vm[i].kve_start);
524     info.GetRange().SetRangeEnd(vm[i].kve_end);
525     info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
526 
527     if (vm[i].kve_protection & VM_PROT_READ)
528       info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
529     else
530       info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
531 
532     if (vm[i].kve_protection & VM_PROT_WRITE)
533       info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
534     else
535       info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
536 
537     if (vm[i].kve_protection & VM_PROT_EXECUTE)
538       info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
539     else
540       info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
541 
542     if (vm[i].kve_path[0])
543       info.SetName(vm[i].kve_path);
544 
545     m_mem_region_cache.emplace_back(
546         info, FileSpec(info.GetName().GetCString(), true));
547   }
548   free(vm);
549 
550   if (m_mem_region_cache.empty()) {
551     // No entries after attempting to read them.  This shouldn't happen. Assume
552     // we don't support map entries.
553     LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
554                   "for memory region metadata retrieval");
555     m_supports_mem_region = LazyBool::eLazyBoolNo;
556     Status error;
557     error.SetErrorString("not supported");
558     return error;
559   }
560   LLDB_LOG(log, "read {0} memory region entries from process {1}",
561            m_mem_region_cache.size(), GetID());
562   // We support memory retrieval, remember that.
563   m_supports_mem_region = LazyBool::eLazyBoolYes;
564   return Status();
565 }
566 
567 Status NativeProcessNetBSD::AllocateMemory(size_t size, uint32_t permissions,
568                                            lldb::addr_t &addr) {
569   return Status("Unimplemented");
570 }
571 
572 Status NativeProcessNetBSD::DeallocateMemory(lldb::addr_t addr) {
573   return Status("Unimplemented");
574 }
575 
576 lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
577   // punt on this for now
578   return LLDB_INVALID_ADDRESS;
579 }
580 
581 size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }
582 
583 Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
584                                           bool hardware) {
585   if (hardware)
586     return Status("NativeProcessNetBSD does not support hardware breakpoints");
587   else
588     return SetSoftwareBreakpoint(addr, size);
589 }
590 
591 Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
592                                                     FileSpec &file_spec) {
593   return Status("Unimplemented");
594 }
595 
596 Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
597                                                lldb::addr_t &load_addr) {
598   load_addr = LLDB_INVALID_ADDRESS;
599   return Status();
600 }
601 
602 void NativeProcessNetBSD::SigchldHandler() {
603   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
604   // Process all pending waitpid notifications.
605   int status;
606   ::pid_t wait_pid =
607       llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG);
608 
609   if (wait_pid == 0)
610     return; // We are done.
611 
612   if (wait_pid == -1) {
613     Status error(errno, eErrorTypePOSIX);
614     LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
615   }
616 
617   WaitStatus wait_status = WaitStatus::Decode(status);
618   bool exited = wait_status.type == WaitStatus::Exit ||
619                 (wait_status.type == WaitStatus::Signal &&
620                  wait_pid == static_cast<::pid_t>(GetID()));
621 
622   LLDB_LOG(log,
623            "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
624            GetID(), wait_pid, status, exited);
625 
626   if (exited)
627     MonitorExited(wait_pid, wait_status);
628   else {
629     assert(wait_status.type == WaitStatus::Stop);
630     MonitorCallback(wait_pid, wait_status.status);
631   }
632 }
633 
634 bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
635   for (const auto &thread : m_threads) {
636     assert(thread && "thread list should not contain NULL threads");
637     if (thread->GetID() == thread_id) {
638       // We have this thread.
639       return true;
640     }
641   }
642 
643   // We don't have this thread.
644   return false;
645 }
646 
647 NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
648 
649   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
650   LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
651 
652   assert(!HasThreadNoLock(thread_id) &&
653          "attempted to add a thread by id that already exists");
654 
655   // If this is the first thread, save it as the current thread
656   if (m_threads.empty())
657     SetCurrentThreadID(thread_id);
658 
659   m_threads.push_back(llvm::make_unique<NativeThreadNetBSD>(*this, thread_id));
660   return static_cast<NativeThreadNetBSD &>(*m_threads.back());
661 }
662 
663 Status NativeProcessNetBSD::Attach() {
664   // Attach to the requested process.
665   // An attach will cause the thread to stop with a SIGSTOP.
666   Status status = PtraceWrapper(PT_ATTACH, m_pid);
667   if (status.Fail())
668     return status;
669 
670   int wstatus;
671   // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
672   // point we should have a thread stopped if waitpid succeeds.
673   if ((wstatus = waitpid(m_pid, NULL, WALLSIG)) < 0)
674     return Status(errno, eErrorTypePOSIX);
675 
676   /* Initialize threads */
677   status = ReinitializeThreads();
678   if (status.Fail())
679     return status;
680 
681   for (const auto &thread : m_threads)
682     static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
683 
684   // Let our process instance know the thread has stopped.
685   SetState(StateType::eStateStopped);
686   return Status();
687 }
688 
689 Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
690                                        size_t size, size_t &bytes_read) {
691   unsigned char *dst = static_cast<unsigned char *>(buf);
692   struct ptrace_io_desc io;
693 
694   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
695   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
696 
697   bytes_read = 0;
698   io.piod_op = PIOD_READ_D;
699   io.piod_len = size;
700 
701   do {
702     io.piod_offs = (void *)(addr + bytes_read);
703     io.piod_addr = dst + bytes_read;
704 
705     Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
706     if (error.Fail())
707       return error;
708 
709     bytes_read = io.piod_len;
710     io.piod_len = size - bytes_read;
711   } while (bytes_read < size);
712 
713   return Status();
714 }
715 
716 Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
717                                         size_t size, size_t &bytes_written) {
718   const unsigned char *src = static_cast<const unsigned char *>(buf);
719   Status error;
720   struct ptrace_io_desc io;
721 
722   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
723   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
724 
725   bytes_written = 0;
726   io.piod_op = PIOD_WRITE_D;
727   io.piod_len = size;
728 
729   do {
730     io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
731     io.piod_offs = (void *)(addr + bytes_written);
732 
733     Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
734     if (error.Fail())
735       return error;
736 
737     bytes_written = io.piod_len;
738     io.piod_len = size - bytes_written;
739   } while (bytes_written < size);
740 
741   return error;
742 }
743 
744 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
745 NativeProcessNetBSD::GetAuxvData() const {
746   /*
747    * ELF_AUX_ENTRIES is currently restricted to kernel
748    * (<sys/exec_elf.h> r. 1.155 specifies 15)
749    *
750    * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
751    * information isn't needed.
752    */
753   size_t auxv_size = 100 * sizeof(AuxInfo);
754 
755   ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
756       llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
757 
758   struct ptrace_io_desc io;
759   io.piod_op = PIOD_READ_AUXV;
760   io.piod_offs = 0;
761   io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
762   io.piod_len = auxv_size;
763 
764   Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
765 
766   if (error.Fail())
767     return std::error_code(error.GetError(), std::generic_category());
768 
769   if (io.piod_len < 1)
770     return std::error_code(ECANCELED, std::generic_category());
771 
772   return std::move(buf);
773 }
774 
775 Status NativeProcessNetBSD::ReinitializeThreads() {
776   // Clear old threads
777   m_threads.clear();
778 
779   // Initialize new thread
780   struct ptrace_lwpinfo info = {};
781   Status error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
782   if (error.Fail()) {
783     return error;
784   }
785   // Reinitialize from scratch threads and register them in process
786   while (info.pl_lwpid != 0) {
787     AddThread(info.pl_lwpid);
788     error = PtraceWrapper(PT_LWPINFO, GetID(), &info, sizeof(info));
789     if (error.Fail()) {
790       return error;
791     }
792   }
793 
794   return error;
795 }
796