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