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