15ffd83dbSDimitry Andric //===-- NativeProcessNetBSD.cpp -------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "NativeProcessNetBSD.h"
100b57cec5SDimitry Andric 
11480093f4SDimitry Andric #include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
120b57cec5SDimitry Andric #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
130b57cec5SDimitry Andric #include "lldb/Host/HostProcess.h"
140b57cec5SDimitry Andric #include "lldb/Host/common/NativeRegisterContext.h"
150b57cec5SDimitry Andric #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
160b57cec5SDimitry Andric #include "lldb/Target/Process.h"
170b57cec5SDimitry Andric #include "lldb/Utility/State.h"
180b57cec5SDimitry Andric #include "llvm/Support/Errno.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric // System includes - They have to be included after framework includes because
210b57cec5SDimitry Andric // they define some macros which collide with variable names in other modules
220b57cec5SDimitry Andric // clang-format off
230b57cec5SDimitry Andric #include <sys/types.h>
240b57cec5SDimitry Andric #include <sys/ptrace.h>
250b57cec5SDimitry Andric #include <sys/sysctl.h>
260b57cec5SDimitry Andric #include <sys/wait.h>
270b57cec5SDimitry Andric #include <uvm/uvm_prot.h>
280b57cec5SDimitry Andric #include <elf.h>
290b57cec5SDimitry Andric #include <util.h>
300b57cec5SDimitry Andric // clang-format on
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace lldb;
330b57cec5SDimitry Andric using namespace lldb_private;
340b57cec5SDimitry Andric using namespace lldb_private::process_netbsd;
350b57cec5SDimitry Andric using namespace llvm;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric // Simple helper function to ensure flags are enabled on the given file
380b57cec5SDimitry Andric // descriptor.
EnsureFDFlags(int fd,int flags)390b57cec5SDimitry Andric static Status EnsureFDFlags(int fd, int flags) {
400b57cec5SDimitry Andric   Status error;
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   int status = fcntl(fd, F_GETFL);
430b57cec5SDimitry Andric   if (status == -1) {
440b57cec5SDimitry Andric     error.SetErrorToErrno();
450b57cec5SDimitry Andric     return error;
460b57cec5SDimitry Andric   }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   if (fcntl(fd, F_SETFL, status | flags) == -1) {
490b57cec5SDimitry Andric     error.SetErrorToErrno();
500b57cec5SDimitry Andric     return error;
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   return error;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric // Public Static Methods
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Launch(ProcessLaunchInfo & launch_info,NativeDelegate & native_delegate,MainLoop & mainloop) const590b57cec5SDimitry Andric NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
600b57cec5SDimitry Andric                                      NativeDelegate &native_delegate,
610b57cec5SDimitry Andric                                      MainLoop &mainloop) const {
620b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   Status status;
650b57cec5SDimitry Andric   ::pid_t pid = ProcessLauncherPosixFork()
660b57cec5SDimitry Andric                     .LaunchProcess(launch_info, status)
670b57cec5SDimitry Andric                     .GetProcessId();
680b57cec5SDimitry Andric   LLDB_LOG(log, "pid = {0:x}", pid);
690b57cec5SDimitry Andric   if (status.Fail()) {
700b57cec5SDimitry Andric     LLDB_LOG(log, "failed to launch process: {0}", status);
710b57cec5SDimitry Andric     return status.ToError();
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   // Wait for the child process to trap on its call to execve.
750b57cec5SDimitry Andric   int wstatus;
760b57cec5SDimitry Andric   ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
770b57cec5SDimitry Andric   assert(wpid == pid);
780b57cec5SDimitry Andric   (void)wpid;
790b57cec5SDimitry Andric   if (!WIFSTOPPED(wstatus)) {
800b57cec5SDimitry Andric     LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
810b57cec5SDimitry Andric              WaitStatus::Decode(wstatus));
820b57cec5SDimitry Andric     return llvm::make_error<StringError>("Could not sync with inferior process",
830b57cec5SDimitry Andric                                          llvm::inconvertibleErrorCode());
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric   LLDB_LOG(log, "inferior started, now in stopped state");
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   ProcessInstanceInfo Info;
880b57cec5SDimitry Andric   if (!Host::GetProcessInfo(pid, Info)) {
890b57cec5SDimitry Andric     return llvm::make_error<StringError>("Cannot get process architecture",
900b57cec5SDimitry Andric                                          llvm::inconvertibleErrorCode());
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   // Set the architecture to the exe architecture.
940b57cec5SDimitry Andric   LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
950b57cec5SDimitry Andric            Info.GetArchitecture().GetArchitectureName());
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
985ffd83dbSDimitry Andric       pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,
990b57cec5SDimitry Andric       Info.GetArchitecture(), mainloop));
1000b57cec5SDimitry Andric 
101af732203SDimitry Andric   status = process_up->SetupTrace();
1020b57cec5SDimitry Andric   if (status.Fail())
1030b57cec5SDimitry Andric     return status.ToError();
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   for (const auto &thread : process_up->m_threads)
1060b57cec5SDimitry Andric     static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
1070b57cec5SDimitry Andric   process_up->SetState(StateType::eStateStopped, false);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   return std::move(process_up);
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
Attach(lldb::pid_t pid,NativeProcessProtocol::NativeDelegate & native_delegate,MainLoop & mainloop) const1130b57cec5SDimitry Andric NativeProcessNetBSD::Factory::Attach(
1140b57cec5SDimitry Andric     lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
1150b57cec5SDimitry Andric     MainLoop &mainloop) const {
1160b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1170b57cec5SDimitry Andric   LLDB_LOG(log, "pid = {0:x}", pid);
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   // Retrieve the architecture for the running process.
1200b57cec5SDimitry Andric   ProcessInstanceInfo Info;
1210b57cec5SDimitry Andric   if (!Host::GetProcessInfo(pid, Info)) {
1220b57cec5SDimitry Andric     return llvm::make_error<StringError>("Cannot get process architecture",
1230b57cec5SDimitry Andric                                          llvm::inconvertibleErrorCode());
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
1270b57cec5SDimitry Andric       pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   Status status = process_up->Attach();
1300b57cec5SDimitry Andric   if (!status.Success())
1310b57cec5SDimitry Andric     return status.ToError();
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   return std::move(process_up);
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric 
136*5f7ddb14SDimitry Andric NativeProcessNetBSD::Extension
GetSupportedExtensions() const137*5f7ddb14SDimitry Andric NativeProcessNetBSD::Factory::GetSupportedExtensions() const {
138*5f7ddb14SDimitry Andric   return Extension::multiprocess | Extension::fork | Extension::vfork |
139*5f7ddb14SDimitry Andric          Extension::pass_signals | Extension::auxv | Extension::libraries_svr4;
140*5f7ddb14SDimitry Andric }
141*5f7ddb14SDimitry Andric 
1420b57cec5SDimitry Andric // Public Instance Methods
1430b57cec5SDimitry Andric 
NativeProcessNetBSD(::pid_t pid,int terminal_fd,NativeDelegate & delegate,const ArchSpec & arch,MainLoop & mainloop)1440b57cec5SDimitry Andric NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
1450b57cec5SDimitry Andric                                          NativeDelegate &delegate,
1460b57cec5SDimitry Andric                                          const ArchSpec &arch,
1470b57cec5SDimitry Andric                                          MainLoop &mainloop)
148*5f7ddb14SDimitry Andric     : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),
149*5f7ddb14SDimitry Andric       m_main_loop(mainloop) {
1500b57cec5SDimitry Andric   if (m_terminal_fd != -1) {
1510b57cec5SDimitry Andric     Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
1520b57cec5SDimitry Andric     assert(status.Success());
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   Status status;
1560b57cec5SDimitry Andric   m_sigchld_handle = mainloop.RegisterSignal(
1570b57cec5SDimitry Andric       SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
1580b57cec5SDimitry Andric   assert(m_sigchld_handle && status.Success());
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric // Handles all waitpid events from the inferior process.
MonitorCallback(lldb::pid_t pid,int signal)1620b57cec5SDimitry Andric void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
1630b57cec5SDimitry Andric   switch (signal) {
1640b57cec5SDimitry Andric   case SIGTRAP:
1650b57cec5SDimitry Andric     return MonitorSIGTRAP(pid);
1660b57cec5SDimitry Andric   case SIGSTOP:
1670b57cec5SDimitry Andric     return MonitorSIGSTOP(pid);
1680b57cec5SDimitry Andric   default:
1690b57cec5SDimitry Andric     return MonitorSignal(pid, signal);
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
MonitorExited(lldb::pid_t pid,WaitStatus status)1730b57cec5SDimitry Andric void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
1740b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   /* Stop Tracking All Threads attached to Process */
1790b57cec5SDimitry Andric   m_threads.clear();
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   SetExitStatus(status, true);
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   // Notify delegate that our process has exited.
1840b57cec5SDimitry Andric   SetState(StateType::eStateExited, true);
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
MonitorSIGSTOP(lldb::pid_t pid)1870b57cec5SDimitry Andric void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
1880b57cec5SDimitry Andric   ptrace_siginfo_t info;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   const auto siginfo_err =
1910b57cec5SDimitry Andric       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // Get details on the signal raised.
1940b57cec5SDimitry Andric   if (siginfo_err.Success()) {
1950b57cec5SDimitry Andric     // Handle SIGSTOP from LLGS (LLDB GDB Server)
1960b57cec5SDimitry Andric     if (info.psi_siginfo.si_code == SI_USER &&
1970b57cec5SDimitry Andric         info.psi_siginfo.si_pid == ::getpid()) {
1980b57cec5SDimitry Andric       /* Stop Tracking all Threads attached to Process */
1990b57cec5SDimitry Andric       for (const auto &thread : m_threads) {
2000b57cec5SDimitry Andric         static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
2010b57cec5SDimitry Andric             SIGSTOP, &info.psi_siginfo);
2020b57cec5SDimitry Andric       }
2030b57cec5SDimitry Andric     }
2049dba64beSDimitry Andric     SetState(StateType::eStateStopped, true);
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
MonitorSIGTRAP(lldb::pid_t pid)2080b57cec5SDimitry Andric void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
2090b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
2100b57cec5SDimitry Andric   ptrace_siginfo_t info;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   const auto siginfo_err =
2130b57cec5SDimitry Andric       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   // Get details on the signal raised.
2160b57cec5SDimitry Andric   if (siginfo_err.Fail()) {
217af732203SDimitry Andric     LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);
2180b57cec5SDimitry Andric     return;
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric 
221af732203SDimitry Andric   LLDB_LOG(log, "got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid,
222af732203SDimitry Andric            info.psi_lwpid, info.psi_siginfo.si_code);
223480093f4SDimitry Andric   NativeThreadNetBSD *thread = nullptr;
224af732203SDimitry Andric 
225480093f4SDimitry Andric   if (info.psi_lwpid > 0) {
226480093f4SDimitry Andric     for (const auto &t : m_threads) {
227480093f4SDimitry Andric       if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
228480093f4SDimitry Andric         thread = static_cast<NativeThreadNetBSD *>(t.get());
229480093f4SDimitry Andric         break;
230480093f4SDimitry Andric       }
231480093f4SDimitry Andric       static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
232480093f4SDimitry Andric     }
233480093f4SDimitry Andric     if (!thread)
234af732203SDimitry Andric       LLDB_LOG(log, "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
235480093f4SDimitry Andric                info.psi_lwpid);
236480093f4SDimitry Andric   }
237480093f4SDimitry Andric 
2380b57cec5SDimitry Andric   switch (info.psi_siginfo.si_code) {
2390b57cec5SDimitry Andric   case TRAP_BRKPT:
240480093f4SDimitry Andric     if (thread) {
241480093f4SDimitry Andric       thread->SetStoppedByBreakpoint();
242480093f4SDimitry Andric       FixupBreakpointPCAsNeeded(*thread);
2430b57cec5SDimitry Andric     }
2440b57cec5SDimitry Andric     SetState(StateType::eStateStopped, true);
245af732203SDimitry Andric     return;
2460b57cec5SDimitry Andric   case TRAP_TRACE:
247480093f4SDimitry Andric     if (thread)
248480093f4SDimitry Andric       thread->SetStoppedByTrace();
2490b57cec5SDimitry Andric     SetState(StateType::eStateStopped, true);
250af732203SDimitry Andric     return;
2510b57cec5SDimitry Andric   case TRAP_EXEC: {
2520b57cec5SDimitry Andric     Status error = ReinitializeThreads();
2530b57cec5SDimitry Andric     if (error.Fail()) {
2540b57cec5SDimitry Andric       SetState(StateType::eStateInvalid);
2550b57cec5SDimitry Andric       return;
2560b57cec5SDimitry Andric     }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     // Let our delegate know we have just exec'd.
2590b57cec5SDimitry Andric     NotifyDidExec();
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric     for (const auto &thread : m_threads)
2620b57cec5SDimitry Andric       static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
2630b57cec5SDimitry Andric     SetState(StateType::eStateStopped, true);
264af732203SDimitry Andric     return;
265af732203SDimitry Andric   }
266*5f7ddb14SDimitry Andric   case TRAP_CHLD: {
267*5f7ddb14SDimitry Andric     ptrace_state_t pst;
268*5f7ddb14SDimitry Andric     Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
269*5f7ddb14SDimitry Andric     if (error.Fail()) {
270*5f7ddb14SDimitry Andric       SetState(StateType::eStateInvalid);
271*5f7ddb14SDimitry Andric       return;
272*5f7ddb14SDimitry Andric     }
273*5f7ddb14SDimitry Andric 
274*5f7ddb14SDimitry Andric     assert(thread);
275*5f7ddb14SDimitry Andric     if (pst.pe_report_event == PTRACE_VFORK_DONE) {
276*5f7ddb14SDimitry Andric       if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {
277*5f7ddb14SDimitry Andric         thread->SetStoppedByVForkDone();
278*5f7ddb14SDimitry Andric         SetState(StateType::eStateStopped, true);
279*5f7ddb14SDimitry Andric       } else {
280*5f7ddb14SDimitry Andric         Status error =
281*5f7ddb14SDimitry Andric             PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
282*5f7ddb14SDimitry Andric         if (error.Fail())
283*5f7ddb14SDimitry Andric           SetState(StateType::eStateInvalid);
284*5f7ddb14SDimitry Andric       }
285*5f7ddb14SDimitry Andric     } else {
286*5f7ddb14SDimitry Andric       assert(pst.pe_report_event == PTRACE_FORK ||
287*5f7ddb14SDimitry Andric              pst.pe_report_event == PTRACE_VFORK);
288*5f7ddb14SDimitry Andric       MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK,
289*5f7ddb14SDimitry Andric                    *thread);
290*5f7ddb14SDimitry Andric     }
291*5f7ddb14SDimitry Andric     return;
292*5f7ddb14SDimitry Andric   }
293480093f4SDimitry Andric   case TRAP_LWP: {
294480093f4SDimitry Andric     ptrace_state_t pst;
295480093f4SDimitry Andric     Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
296480093f4SDimitry Andric     if (error.Fail()) {
297480093f4SDimitry Andric       SetState(StateType::eStateInvalid);
298480093f4SDimitry Andric       return;
2990b57cec5SDimitry Andric     }
300480093f4SDimitry Andric 
301480093f4SDimitry Andric     switch (pst.pe_report_event) {
302480093f4SDimitry Andric     case PTRACE_LWP_CREATE: {
303af732203SDimitry Andric       LLDB_LOG(log, "monitoring new thread, pid = {0}, LWP = {1}", pid,
304480093f4SDimitry Andric                pst.pe_lwp);
305480093f4SDimitry Andric       NativeThreadNetBSD &t = AddThread(pst.pe_lwp);
306480093f4SDimitry Andric       error = t.CopyWatchpointsFrom(
307480093f4SDimitry Andric           static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));
308480093f4SDimitry Andric       if (error.Fail()) {
309af732203SDimitry Andric         LLDB_LOG(log, "failed to copy watchpoints to new thread {0}: {1}",
310480093f4SDimitry Andric                  pst.pe_lwp, error);
311480093f4SDimitry Andric         SetState(StateType::eStateInvalid);
312480093f4SDimitry Andric         return;
313480093f4SDimitry Andric       }
314480093f4SDimitry Andric     } break;
315480093f4SDimitry Andric     case PTRACE_LWP_EXIT:
316af732203SDimitry Andric       LLDB_LOG(log, "removing exited thread, pid = {0}, LWP = {1}", pid,
317480093f4SDimitry Andric                pst.pe_lwp);
318480093f4SDimitry Andric       RemoveThread(pst.pe_lwp);
3190b57cec5SDimitry Andric       break;
3200b57cec5SDimitry Andric     }
3210b57cec5SDimitry Andric 
322480093f4SDimitry Andric     error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);
323af732203SDimitry Andric     if (error.Fail())
324480093f4SDimitry Andric       SetState(StateType::eStateInvalid);
325480093f4SDimitry Andric     return;
326480093f4SDimitry Andric   }
327480093f4SDimitry Andric   case TRAP_DBREG: {
328480093f4SDimitry Andric     if (!thread)
329480093f4SDimitry Andric       break;
330480093f4SDimitry Andric 
331480093f4SDimitry Andric     auto &regctx = static_cast<NativeRegisterContextNetBSD &>(
332480093f4SDimitry Andric         thread->GetRegisterContext());
3330b57cec5SDimitry Andric     uint32_t wp_index = LLDB_INVALID_INDEX32;
334af732203SDimitry Andric     Status error = regctx.GetWatchpointHitIndex(
335af732203SDimitry Andric         wp_index, (uintptr_t)info.psi_siginfo.si_addr);
3360b57cec5SDimitry Andric     if (error.Fail())
3370b57cec5SDimitry Andric       LLDB_LOG(log,
3380b57cec5SDimitry Andric                "received error while checking for watchpoint hits, pid = "
339af732203SDimitry Andric                "{0}, LWP = {1}, error = {2}",
340af732203SDimitry Andric                pid, info.psi_lwpid, error);
3410b57cec5SDimitry Andric     if (wp_index != LLDB_INVALID_INDEX32) {
342480093f4SDimitry Andric       thread->SetStoppedByWatchpoint(wp_index);
343480093f4SDimitry Andric       regctx.ClearWatchpointHit(wp_index);
3440b57cec5SDimitry Andric       SetState(StateType::eStateStopped, true);
345af732203SDimitry Andric       return;
3460b57cec5SDimitry Andric     }
3470b57cec5SDimitry Andric 
348480093f4SDimitry Andric     thread->SetStoppedByTrace();
3490b57cec5SDimitry Andric     SetState(StateType::eStateStopped, true);
350af732203SDimitry Andric     return;
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric   }
3530b57cec5SDimitry Andric 
354af732203SDimitry Andric   // Either user-generated SIGTRAP or an unknown event that would
355af732203SDimitry Andric   // otherwise leave the debugger hanging.
356af732203SDimitry Andric   LLDB_LOG(log, "unknown SIGTRAP, passing to generic handler");
357af732203SDimitry Andric   MonitorSignal(pid, SIGTRAP);
358af732203SDimitry Andric }
359af732203SDimitry Andric 
MonitorSignal(lldb::pid_t pid,int signal)3600b57cec5SDimitry Andric void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
361af732203SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
3620b57cec5SDimitry Andric   ptrace_siginfo_t info;
363af732203SDimitry Andric 
3640b57cec5SDimitry Andric   const auto siginfo_err =
3650b57cec5SDimitry Andric       PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
366af732203SDimitry Andric   if (siginfo_err.Fail()) {
367af732203SDimitry Andric     LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);
368af732203SDimitry Andric     return;
369af732203SDimitry Andric   }
3700b57cec5SDimitry Andric 
371480093f4SDimitry Andric   for (const auto &abs_thread : m_threads) {
372480093f4SDimitry Andric     NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
373480093f4SDimitry Andric     assert(info.psi_lwpid >= 0);
374480093f4SDimitry Andric     if (info.psi_lwpid == 0 ||
375480093f4SDimitry Andric         static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
376480093f4SDimitry Andric       thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
377480093f4SDimitry Andric     else
378480093f4SDimitry Andric       thread.SetStoppedWithNoReason();
3790b57cec5SDimitry Andric   }
3800b57cec5SDimitry Andric   SetState(StateType::eStateStopped, true);
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
PtraceWrapper(int req,lldb::pid_t pid,void * addr,int data,int * result)3830b57cec5SDimitry Andric Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
3840b57cec5SDimitry Andric                                           int data, int *result) {
3850b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
3860b57cec5SDimitry Andric   Status error;
3870b57cec5SDimitry Andric   int ret;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   errno = 0;
3900b57cec5SDimitry Andric   ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   if (ret == -1)
3930b57cec5SDimitry Andric     error.SetErrorToErrno();
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   if (result)
3960b57cec5SDimitry Andric     *result = ret;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   if (error.Fail())
4010b57cec5SDimitry Andric     LLDB_LOG(log, "ptrace() failed: {0}", error);
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   return error;
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
ComputeSignalInfo(const std::vector<std::unique_ptr<NativeThreadProtocol>> & threads,const ResumeActionList & resume_actions)406480093f4SDimitry Andric static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
407480093f4SDimitry Andric     const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
408480093f4SDimitry Andric     const ResumeActionList &resume_actions) {
409480093f4SDimitry Andric   // We need to account for three possible scenarios:
410480093f4SDimitry Andric   // 1. no signal being sent.
411480093f4SDimitry Andric   // 2. a signal being sent to one thread.
412480093f4SDimitry Andric   // 3. a signal being sent to the whole process.
413480093f4SDimitry Andric 
414480093f4SDimitry Andric   // Count signaled threads.  While at it, determine which signal is being sent
415480093f4SDimitry Andric   // and ensure there's only one.
416480093f4SDimitry Andric   size_t signaled_threads = 0;
417480093f4SDimitry Andric   int signal = LLDB_INVALID_SIGNAL_NUMBER;
418480093f4SDimitry Andric   lldb::tid_t signaled_lwp;
419480093f4SDimitry Andric   for (const auto &thread : threads) {
420480093f4SDimitry Andric     assert(thread && "thread list should not contain NULL threads");
421480093f4SDimitry Andric     const ResumeAction *action =
422480093f4SDimitry Andric         resume_actions.GetActionForThread(thread->GetID(), true);
423480093f4SDimitry Andric     if (action) {
424480093f4SDimitry Andric       if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
425480093f4SDimitry Andric         signaled_threads++;
426480093f4SDimitry Andric         if (action->signal != signal) {
427480093f4SDimitry Andric           if (signal != LLDB_INVALID_SIGNAL_NUMBER)
428480093f4SDimitry Andric             return Status("NetBSD does not support passing multiple signals "
429480093f4SDimitry Andric                           "simultaneously")
430480093f4SDimitry Andric                 .ToError();
431480093f4SDimitry Andric           signal = action->signal;
432480093f4SDimitry Andric           signaled_lwp = thread->GetID();
433480093f4SDimitry Andric         }
434480093f4SDimitry Andric       }
435480093f4SDimitry Andric     }
436480093f4SDimitry Andric   }
437480093f4SDimitry Andric 
438480093f4SDimitry Andric   if (signaled_threads == 0) {
439480093f4SDimitry Andric     ptrace_siginfo_t siginfo;
440480093f4SDimitry Andric     siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
441480093f4SDimitry Andric     return siginfo;
442480093f4SDimitry Andric   }
443480093f4SDimitry Andric 
444480093f4SDimitry Andric   if (signaled_threads > 1 && signaled_threads < threads.size())
445480093f4SDimitry Andric     return Status("NetBSD does not support passing signal to 1<i<all threads")
446480093f4SDimitry Andric         .ToError();
447480093f4SDimitry Andric 
448480093f4SDimitry Andric   ptrace_siginfo_t siginfo;
449480093f4SDimitry Andric   siginfo.psi_siginfo.si_signo = signal;
450480093f4SDimitry Andric   siginfo.psi_siginfo.si_code = SI_USER;
451480093f4SDimitry Andric   siginfo.psi_siginfo.si_pid = getpid();
452480093f4SDimitry Andric   siginfo.psi_siginfo.si_uid = getuid();
453480093f4SDimitry Andric   if (signaled_threads == 1)
454480093f4SDimitry Andric     siginfo.psi_lwpid = signaled_lwp;
455480093f4SDimitry Andric   else // signal for the whole process
456480093f4SDimitry Andric     siginfo.psi_lwpid = 0;
457480093f4SDimitry Andric   return siginfo;
458480093f4SDimitry Andric }
459480093f4SDimitry Andric 
Resume(const ResumeActionList & resume_actions)4600b57cec5SDimitry Andric Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
4610b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
4620b57cec5SDimitry Andric   LLDB_LOG(log, "pid {0}", GetID());
4630b57cec5SDimitry Andric 
464480093f4SDimitry Andric   Status ret;
465480093f4SDimitry Andric 
466480093f4SDimitry Andric   Expected<ptrace_siginfo_t> siginfo =
467480093f4SDimitry Andric       ComputeSignalInfo(m_threads, resume_actions);
468480093f4SDimitry Andric   if (!siginfo)
469480093f4SDimitry Andric     return Status(siginfo.takeError());
470480093f4SDimitry Andric 
471480093f4SDimitry Andric   for (const auto &abs_thread : m_threads) {
472480093f4SDimitry Andric     assert(abs_thread && "thread list should not contain NULL threads");
473480093f4SDimitry Andric     NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
474480093f4SDimitry Andric 
475480093f4SDimitry Andric     const ResumeAction *action =
476480093f4SDimitry Andric         resume_actions.GetActionForThread(thread.GetID(), true);
477480093f4SDimitry Andric     // we need to explicit issue suspend requests, so it is simpler to map it
478480093f4SDimitry Andric     // into proper action
479480093f4SDimitry Andric     ResumeAction suspend_action{thread.GetID(), eStateSuspended,
480480093f4SDimitry Andric                                 LLDB_INVALID_SIGNAL_NUMBER};
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric     if (action == nullptr) {
4830b57cec5SDimitry Andric       LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
484480093f4SDimitry Andric                thread.GetID());
485480093f4SDimitry Andric       action = &suspend_action;
4860b57cec5SDimitry Andric     }
4870b57cec5SDimitry Andric 
488480093f4SDimitry Andric     LLDB_LOG(
489480093f4SDimitry Andric         log,
490480093f4SDimitry Andric         "processing resume action state {0} signal {1} for pid {2} tid {3}",
491480093f4SDimitry Andric         action->state, action->signal, GetID(), thread.GetID());
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric     switch (action->state) {
494480093f4SDimitry Andric     case eStateRunning:
495480093f4SDimitry Andric       ret = thread.Resume();
4960b57cec5SDimitry Andric       break;
4970b57cec5SDimitry Andric     case eStateStepping:
498480093f4SDimitry Andric       ret = thread.SingleStep();
4990b57cec5SDimitry Andric       break;
5000b57cec5SDimitry Andric     case eStateSuspended:
5010b57cec5SDimitry Andric     case eStateStopped:
502480093f4SDimitry Andric       if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
503480093f4SDimitry Andric         return Status("Passing signal to suspended thread unsupported");
504480093f4SDimitry Andric 
505480093f4SDimitry Andric       ret = thread.Suspend();
506480093f4SDimitry Andric       break;
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric     default:
5090b57cec5SDimitry Andric       return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
5100b57cec5SDimitry Andric                     "for pid %" PRIu64 ", tid %" PRIu64,
5110b57cec5SDimitry Andric                     __FUNCTION__, StateAsCString(action->state), GetID(),
512480093f4SDimitry Andric                     thread.GetID());
5130b57cec5SDimitry Andric     }
5140b57cec5SDimitry Andric 
515480093f4SDimitry Andric     if (!ret.Success())
516480093f4SDimitry Andric       return ret;
517480093f4SDimitry Andric   }
518480093f4SDimitry Andric 
519480093f4SDimitry Andric   int signal = 0;
520480093f4SDimitry Andric   if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
521480093f4SDimitry Andric     ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
522480093f4SDimitry Andric                         sizeof(*siginfo));
523480093f4SDimitry Andric     if (!ret.Success())
524480093f4SDimitry Andric       return ret;
525480093f4SDimitry Andric     signal = siginfo->psi_siginfo.si_signo;
526480093f4SDimitry Andric   }
527480093f4SDimitry Andric 
528af732203SDimitry Andric   ret =
529af732203SDimitry Andric       PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), signal);
530480093f4SDimitry Andric   if (ret.Success())
531480093f4SDimitry Andric     SetState(eStateRunning, true);
532480093f4SDimitry Andric   return ret;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric 
Halt()535af732203SDimitry Andric Status NativeProcessNetBSD::Halt() { return PtraceWrapper(PT_STOP, GetID()); }
5360b57cec5SDimitry Andric 
Detach()5370b57cec5SDimitry Andric Status NativeProcessNetBSD::Detach() {
5380b57cec5SDimitry Andric   Status error;
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   // Stop monitoring the inferior.
5410b57cec5SDimitry Andric   m_sigchld_handle.reset();
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   // Tell ptrace to detach from the process.
5440b57cec5SDimitry Andric   if (GetID() == LLDB_INVALID_PROCESS_ID)
5450b57cec5SDimitry Andric     return error;
5460b57cec5SDimitry Andric 
547*5f7ddb14SDimitry Andric   return PtraceWrapper(PT_DETACH, GetID(), reinterpret_cast<void *>(1));
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric 
Signal(int signo)5500b57cec5SDimitry Andric Status NativeProcessNetBSD::Signal(int signo) {
5510b57cec5SDimitry Andric   Status error;
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric   if (kill(GetID(), signo))
5540b57cec5SDimitry Andric     error.SetErrorToErrno();
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   return error;
5570b57cec5SDimitry Andric }
5580b57cec5SDimitry Andric 
Interrupt()559480093f4SDimitry Andric Status NativeProcessNetBSD::Interrupt() {
560480093f4SDimitry Andric   return PtraceWrapper(PT_STOP, GetID());
561480093f4SDimitry Andric }
562480093f4SDimitry Andric 
Kill()5630b57cec5SDimitry Andric Status NativeProcessNetBSD::Kill() {
5640b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
5650b57cec5SDimitry Andric   LLDB_LOG(log, "pid {0}", GetID());
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   Status error;
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   switch (m_state) {
5700b57cec5SDimitry Andric   case StateType::eStateInvalid:
5710b57cec5SDimitry Andric   case StateType::eStateExited:
5720b57cec5SDimitry Andric   case StateType::eStateCrashed:
5730b57cec5SDimitry Andric   case StateType::eStateDetached:
5740b57cec5SDimitry Andric   case StateType::eStateUnloaded:
5750b57cec5SDimitry Andric     // Nothing to do - the process is already dead.
5760b57cec5SDimitry Andric     LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
5770b57cec5SDimitry Andric              StateAsCString(m_state));
5780b57cec5SDimitry Andric     return error;
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   case StateType::eStateConnected:
5810b57cec5SDimitry Andric   case StateType::eStateAttaching:
5820b57cec5SDimitry Andric   case StateType::eStateLaunching:
5830b57cec5SDimitry Andric   case StateType::eStateStopped:
5840b57cec5SDimitry Andric   case StateType::eStateRunning:
5850b57cec5SDimitry Andric   case StateType::eStateStepping:
5860b57cec5SDimitry Andric   case StateType::eStateSuspended:
5870b57cec5SDimitry Andric     // We can try to kill a process in these states.
5880b57cec5SDimitry Andric     break;
5890b57cec5SDimitry Andric   }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric   if (kill(GetID(), SIGKILL) != 0) {
5920b57cec5SDimitry Andric     error.SetErrorToErrno();
5930b57cec5SDimitry Andric     return error;
5940b57cec5SDimitry Andric   }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   return error;
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric 
GetMemoryRegionInfo(lldb::addr_t load_addr,MemoryRegionInfo & range_info)5990b57cec5SDimitry Andric Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
6000b57cec5SDimitry Andric                                                 MemoryRegionInfo &range_info) {
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
6030b57cec5SDimitry Andric     // We're done.
6040b57cec5SDimitry Andric     return Status("unsupported");
6050b57cec5SDimitry Andric   }
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   Status error = PopulateMemoryRegionCache();
6080b57cec5SDimitry Andric   if (error.Fail()) {
6090b57cec5SDimitry Andric     return error;
6100b57cec5SDimitry Andric   }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   lldb::addr_t prev_base_address = 0;
6130b57cec5SDimitry Andric   // FIXME start by finding the last region that is <= target address using
6140b57cec5SDimitry Andric   // binary search.  Data is sorted.
6150b57cec5SDimitry Andric   // There can be a ton of regions on pthreads apps with lots of threads.
6160b57cec5SDimitry Andric   for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
6170b57cec5SDimitry Andric        ++it) {
6180b57cec5SDimitry Andric     MemoryRegionInfo &proc_entry_info = it->first;
6190b57cec5SDimitry Andric     // Sanity check assumption that memory map entries are ascending.
6200b57cec5SDimitry Andric     assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
6210b57cec5SDimitry Andric            "descending memory map entries detected, unexpected");
6220b57cec5SDimitry Andric     prev_base_address = proc_entry_info.GetRange().GetRangeBase();
6230b57cec5SDimitry Andric     UNUSED_IF_ASSERT_DISABLED(prev_base_address);
6240b57cec5SDimitry Andric     // If the target address comes before this entry, indicate distance to next
6250b57cec5SDimitry Andric     // region.
6260b57cec5SDimitry Andric     if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
6270b57cec5SDimitry Andric       range_info.GetRange().SetRangeBase(load_addr);
6280b57cec5SDimitry Andric       range_info.GetRange().SetByteSize(
6290b57cec5SDimitry Andric           proc_entry_info.GetRange().GetRangeBase() - load_addr);
6300b57cec5SDimitry Andric       range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
6310b57cec5SDimitry Andric       range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
6320b57cec5SDimitry Andric       range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
6330b57cec5SDimitry Andric       range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
6340b57cec5SDimitry Andric       return error;
6350b57cec5SDimitry Andric     } else if (proc_entry_info.GetRange().Contains(load_addr)) {
6360b57cec5SDimitry Andric       // The target address is within the memory region we're processing here.
6370b57cec5SDimitry Andric       range_info = proc_entry_info;
6380b57cec5SDimitry Andric       return error;
6390b57cec5SDimitry Andric     }
6400b57cec5SDimitry Andric     // The target memory address comes somewhere after the region we just
6410b57cec5SDimitry Andric     // parsed.
6420b57cec5SDimitry Andric   }
6430b57cec5SDimitry Andric   // If we made it here, we didn't find an entry that contained the given
6440b57cec5SDimitry Andric   // address. Return the load_addr as start and the amount of bytes betwwen
6450b57cec5SDimitry Andric   // load address and the end of the memory as size.
6460b57cec5SDimitry Andric   range_info.GetRange().SetRangeBase(load_addr);
6470b57cec5SDimitry Andric   range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
6480b57cec5SDimitry Andric   range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
6490b57cec5SDimitry Andric   range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
6500b57cec5SDimitry Andric   range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
6510b57cec5SDimitry Andric   range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
6520b57cec5SDimitry Andric   return error;
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
PopulateMemoryRegionCache()6550b57cec5SDimitry Andric Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
6560b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
6570b57cec5SDimitry Andric   // If our cache is empty, pull the latest.  There should always be at least
6580b57cec5SDimitry Andric   // one memory region if memory region handling is supported.
6590b57cec5SDimitry Andric   if (!m_mem_region_cache.empty()) {
6600b57cec5SDimitry Andric     LLDB_LOG(log, "reusing {0} cached memory region entries",
6610b57cec5SDimitry Andric              m_mem_region_cache.size());
6620b57cec5SDimitry Andric     return Status();
6630b57cec5SDimitry Andric   }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   struct kinfo_vmentry *vm;
6660b57cec5SDimitry Andric   size_t count, i;
6670b57cec5SDimitry Andric   vm = kinfo_getvmmap(GetID(), &count);
6680b57cec5SDimitry Andric   if (vm == NULL) {
6690b57cec5SDimitry Andric     m_supports_mem_region = LazyBool::eLazyBoolNo;
6700b57cec5SDimitry Andric     Status error;
6710b57cec5SDimitry Andric     error.SetErrorString("not supported");
6720b57cec5SDimitry Andric     return error;
6730b57cec5SDimitry Andric   }
6740b57cec5SDimitry Andric   for (i = 0; i < count; i++) {
6750b57cec5SDimitry Andric     MemoryRegionInfo info;
6760b57cec5SDimitry Andric     info.Clear();
6770b57cec5SDimitry Andric     info.GetRange().SetRangeBase(vm[i].kve_start);
6780b57cec5SDimitry Andric     info.GetRange().SetRangeEnd(vm[i].kve_end);
6790b57cec5SDimitry Andric     info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric     if (vm[i].kve_protection & VM_PROT_READ)
6820b57cec5SDimitry Andric       info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
6830b57cec5SDimitry Andric     else
6840b57cec5SDimitry Andric       info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric     if (vm[i].kve_protection & VM_PROT_WRITE)
6870b57cec5SDimitry Andric       info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
6880b57cec5SDimitry Andric     else
6890b57cec5SDimitry Andric       info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric     if (vm[i].kve_protection & VM_PROT_EXECUTE)
6920b57cec5SDimitry Andric       info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
6930b57cec5SDimitry Andric     else
6940b57cec5SDimitry Andric       info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric     if (vm[i].kve_path[0])
6970b57cec5SDimitry Andric       info.SetName(vm[i].kve_path);
6980b57cec5SDimitry Andric 
699af732203SDimitry Andric     m_mem_region_cache.emplace_back(info,
700af732203SDimitry Andric                                     FileSpec(info.GetName().GetCString()));
7010b57cec5SDimitry Andric   }
7020b57cec5SDimitry Andric   free(vm);
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   if (m_mem_region_cache.empty()) {
7050b57cec5SDimitry Andric     // No entries after attempting to read them.  This shouldn't happen. Assume
7060b57cec5SDimitry Andric     // we don't support map entries.
7070b57cec5SDimitry Andric     LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
7080b57cec5SDimitry Andric                   "for memory region metadata retrieval");
7090b57cec5SDimitry Andric     m_supports_mem_region = LazyBool::eLazyBoolNo;
7100b57cec5SDimitry Andric     Status error;
7110b57cec5SDimitry Andric     error.SetErrorString("not supported");
7120b57cec5SDimitry Andric     return error;
7130b57cec5SDimitry Andric   }
7140b57cec5SDimitry Andric   LLDB_LOG(log, "read {0} memory region entries from process {1}",
7150b57cec5SDimitry Andric            m_mem_region_cache.size(), GetID());
7160b57cec5SDimitry Andric   // We support memory retrieval, remember that.
7170b57cec5SDimitry Andric   m_supports_mem_region = LazyBool::eLazyBoolYes;
7180b57cec5SDimitry Andric   return Status();
7190b57cec5SDimitry Andric }
7200b57cec5SDimitry Andric 
GetSharedLibraryInfoAddress()7210b57cec5SDimitry Andric lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
7220b57cec5SDimitry Andric   // punt on this for now
7230b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
7240b57cec5SDimitry Andric }
7250b57cec5SDimitry Andric 
UpdateThreads()7260b57cec5SDimitry Andric size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }
7270b57cec5SDimitry Andric 
SetBreakpoint(lldb::addr_t addr,uint32_t size,bool hardware)7280b57cec5SDimitry Andric Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
7290b57cec5SDimitry Andric                                           bool hardware) {
7300b57cec5SDimitry Andric   if (hardware)
7310b57cec5SDimitry Andric     return Status("NativeProcessNetBSD does not support hardware breakpoints");
7320b57cec5SDimitry Andric   else
7330b57cec5SDimitry Andric     return SetSoftwareBreakpoint(addr, size);
7340b57cec5SDimitry Andric }
7350b57cec5SDimitry Andric 
GetLoadedModuleFileSpec(const char * module_path,FileSpec & file_spec)7360b57cec5SDimitry Andric Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
7370b57cec5SDimitry Andric                                                     FileSpec &file_spec) {
738af732203SDimitry Andric   Status error = PopulateMemoryRegionCache();
739af732203SDimitry Andric   if (error.Fail())
740af732203SDimitry Andric     return error;
741af732203SDimitry Andric 
742af732203SDimitry Andric   FileSpec module_file_spec(module_path);
743af732203SDimitry Andric   FileSystem::Instance().Resolve(module_file_spec);
744af732203SDimitry Andric 
745af732203SDimitry Andric   file_spec.Clear();
746af732203SDimitry Andric   for (const auto &it : m_mem_region_cache) {
747af732203SDimitry Andric     if (it.second.GetFilename() == module_file_spec.GetFilename()) {
748af732203SDimitry Andric       file_spec = it.second;
749af732203SDimitry Andric       return Status();
750af732203SDimitry Andric     }
751af732203SDimitry Andric   }
752af732203SDimitry Andric   return Status("Module file (%s) not found in process' memory map!",
753af732203SDimitry Andric                 module_file_spec.GetFilename().AsCString());
7540b57cec5SDimitry Andric }
7550b57cec5SDimitry Andric 
GetFileLoadAddress(const llvm::StringRef & file_name,lldb::addr_t & load_addr)7560b57cec5SDimitry Andric Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
7570b57cec5SDimitry Andric                                                lldb::addr_t &load_addr) {
7580b57cec5SDimitry Andric   load_addr = LLDB_INVALID_ADDRESS;
759af732203SDimitry Andric   Status error = PopulateMemoryRegionCache();
760af732203SDimitry Andric   if (error.Fail())
761af732203SDimitry Andric     return error;
762af732203SDimitry Andric 
763af732203SDimitry Andric   FileSpec file(file_name);
764af732203SDimitry Andric   for (const auto &it : m_mem_region_cache) {
765af732203SDimitry Andric     if (it.second == file) {
766af732203SDimitry Andric       load_addr = it.first.GetRange().GetRangeBase();
7670b57cec5SDimitry Andric       return Status();
7680b57cec5SDimitry Andric     }
769af732203SDimitry Andric   }
770af732203SDimitry Andric   return Status("No load address found for file %s.", file_name.str().c_str());
771af732203SDimitry Andric }
7720b57cec5SDimitry Andric 
SigchldHandler()7730b57cec5SDimitry Andric void NativeProcessNetBSD::SigchldHandler() {
7740b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
7750b57cec5SDimitry Andric   int status;
776af732203SDimitry Andric   ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status,
777af732203SDimitry Andric                                                  WALLSIG | WNOHANG);
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric   if (wait_pid == 0)
780*5f7ddb14SDimitry Andric     return;
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   if (wait_pid == -1) {
7830b57cec5SDimitry Andric     Status error(errno, eErrorTypePOSIX);
7840b57cec5SDimitry Andric     LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
785*5f7ddb14SDimitry Andric     return;
7860b57cec5SDimitry Andric   }
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   WaitStatus wait_status = WaitStatus::Decode(status);
7890b57cec5SDimitry Andric   bool exited = wait_status.type == WaitStatus::Exit ||
7900b57cec5SDimitry Andric                 (wait_status.type == WaitStatus::Signal &&
7910b57cec5SDimitry Andric                  wait_pid == static_cast<::pid_t>(GetID()));
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric   LLDB_LOG(log,
7940b57cec5SDimitry Andric            "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
7950b57cec5SDimitry Andric            GetID(), wait_pid, status, exited);
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric   if (exited)
7980b57cec5SDimitry Andric     MonitorExited(wait_pid, wait_status);
7990b57cec5SDimitry Andric   else {
8000b57cec5SDimitry Andric     assert(wait_status.type == WaitStatus::Stop);
8010b57cec5SDimitry Andric     MonitorCallback(wait_pid, wait_status.status);
8020b57cec5SDimitry Andric   }
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric 
HasThreadNoLock(lldb::tid_t thread_id)8050b57cec5SDimitry Andric bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
8060b57cec5SDimitry Andric   for (const auto &thread : m_threads) {
8070b57cec5SDimitry Andric     assert(thread && "thread list should not contain NULL threads");
8080b57cec5SDimitry Andric     if (thread->GetID() == thread_id) {
8090b57cec5SDimitry Andric       // We have this thread.
8100b57cec5SDimitry Andric       return true;
8110b57cec5SDimitry Andric     }
8120b57cec5SDimitry Andric   }
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   // We don't have this thread.
8150b57cec5SDimitry Andric   return false;
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric 
AddThread(lldb::tid_t thread_id)8180b57cec5SDimitry Andric NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
8190b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
8200b57cec5SDimitry Andric   LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
8210b57cec5SDimitry Andric 
822480093f4SDimitry Andric   assert(thread_id > 0);
8230b57cec5SDimitry Andric   assert(!HasThreadNoLock(thread_id) &&
8240b57cec5SDimitry Andric          "attempted to add a thread by id that already exists");
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   // If this is the first thread, save it as the current thread
8270b57cec5SDimitry Andric   if (m_threads.empty())
8280b57cec5SDimitry Andric     SetCurrentThreadID(thread_id);
8290b57cec5SDimitry Andric 
8309dba64beSDimitry Andric   m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*this, thread_id));
8310b57cec5SDimitry Andric   return static_cast<NativeThreadNetBSD &>(*m_threads.back());
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric 
RemoveThread(lldb::tid_t thread_id)834480093f4SDimitry Andric void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
835480093f4SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
836480093f4SDimitry Andric   LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
837480093f4SDimitry Andric 
838480093f4SDimitry Andric   assert(thread_id > 0);
839480093f4SDimitry Andric   assert(HasThreadNoLock(thread_id) &&
840480093f4SDimitry Andric          "attempted to remove a thread that does not exist");
841480093f4SDimitry Andric 
842480093f4SDimitry Andric   for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
843480093f4SDimitry Andric     if ((*it)->GetID() == thread_id) {
844480093f4SDimitry Andric       m_threads.erase(it);
845480093f4SDimitry Andric       break;
846480093f4SDimitry Andric     }
847480093f4SDimitry Andric   }
848480093f4SDimitry Andric }
849480093f4SDimitry Andric 
Attach()8500b57cec5SDimitry Andric Status NativeProcessNetBSD::Attach() {
8510b57cec5SDimitry Andric   // Attach to the requested process.
8520b57cec5SDimitry Andric   // An attach will cause the thread to stop with a SIGSTOP.
8530b57cec5SDimitry Andric   Status status = PtraceWrapper(PT_ATTACH, m_pid);
8540b57cec5SDimitry Andric   if (status.Fail())
8550b57cec5SDimitry Andric     return status;
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric   int wstatus;
8580b57cec5SDimitry Andric   // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
8590b57cec5SDimitry Andric   // point we should have a thread stopped if waitpid succeeds.
860af732203SDimitry Andric   if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid, m_pid, nullptr,
861af732203SDimitry Andric                                              WALLSIG)) < 0)
8620b57cec5SDimitry Andric     return Status(errno, eErrorTypePOSIX);
8630b57cec5SDimitry Andric 
864af732203SDimitry Andric   // Initialize threads and tracing status
865af732203SDimitry Andric   // NB: this needs to be called before we set thread state
866af732203SDimitry Andric   status = SetupTrace();
8670b57cec5SDimitry Andric   if (status.Fail())
8680b57cec5SDimitry Andric     return status;
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric   for (const auto &thread : m_threads)
8710b57cec5SDimitry Andric     static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   // Let our process instance know the thread has stopped.
874af732203SDimitry Andric   SetCurrentThreadID(m_threads.front()->GetID());
875af732203SDimitry Andric   SetState(StateType::eStateStopped, false);
8760b57cec5SDimitry Andric   return Status();
8770b57cec5SDimitry Andric }
8780b57cec5SDimitry Andric 
ReadMemory(lldb::addr_t addr,void * buf,size_t size,size_t & bytes_read)8790b57cec5SDimitry Andric Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
8800b57cec5SDimitry Andric                                        size_t size, size_t &bytes_read) {
8810b57cec5SDimitry Andric   unsigned char *dst = static_cast<unsigned char *>(buf);
8820b57cec5SDimitry Andric   struct ptrace_io_desc io;
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
8850b57cec5SDimitry Andric   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   bytes_read = 0;
8880b57cec5SDimitry Andric   io.piod_op = PIOD_READ_D;
8890b57cec5SDimitry Andric   io.piod_len = size;
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric   do {
8920b57cec5SDimitry Andric     io.piod_offs = (void *)(addr + bytes_read);
8930b57cec5SDimitry Andric     io.piod_addr = dst + bytes_read;
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric     Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
8960b57cec5SDimitry Andric     if (error.Fail() || io.piod_len == 0)
8970b57cec5SDimitry Andric       return error;
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric     bytes_read += io.piod_len;
9000b57cec5SDimitry Andric     io.piod_len = size - bytes_read;
9010b57cec5SDimitry Andric   } while (bytes_read < size);
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric   return Status();
9040b57cec5SDimitry Andric }
9050b57cec5SDimitry Andric 
WriteMemory(lldb::addr_t addr,const void * buf,size_t size,size_t & bytes_written)9060b57cec5SDimitry Andric Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
9070b57cec5SDimitry Andric                                         size_t size, size_t &bytes_written) {
9080b57cec5SDimitry Andric   const unsigned char *src = static_cast<const unsigned char *>(buf);
9090b57cec5SDimitry Andric   Status error;
9100b57cec5SDimitry Andric   struct ptrace_io_desc io;
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
9130b57cec5SDimitry Andric   LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric   bytes_written = 0;
9160b57cec5SDimitry Andric   io.piod_op = PIOD_WRITE_D;
9170b57cec5SDimitry Andric   io.piod_len = size;
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   do {
920af732203SDimitry Andric     io.piod_addr =
921af732203SDimitry Andric         const_cast<void *>(static_cast<const void *>(src + bytes_written));
9220b57cec5SDimitry Andric     io.piod_offs = (void *)(addr + bytes_written);
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric     Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
9250b57cec5SDimitry Andric     if (error.Fail() || io.piod_len == 0)
9260b57cec5SDimitry Andric       return error;
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric     bytes_written += io.piod_len;
9290b57cec5SDimitry Andric     io.piod_len = size - bytes_written;
9300b57cec5SDimitry Andric   } while (bytes_written < size);
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric   return error;
9330b57cec5SDimitry Andric }
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
GetAuxvData() const9360b57cec5SDimitry Andric NativeProcessNetBSD::GetAuxvData() const {
9370b57cec5SDimitry Andric   /*
9380b57cec5SDimitry Andric    * ELF_AUX_ENTRIES is currently restricted to kernel
9390b57cec5SDimitry Andric    * (<sys/exec_elf.h> r. 1.155 specifies 15)
9400b57cec5SDimitry Andric    *
9410b57cec5SDimitry Andric    * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
9420b57cec5SDimitry Andric    * information isn't needed.
9430b57cec5SDimitry Andric    */
9440b57cec5SDimitry Andric   size_t auxv_size = 100 * sizeof(AuxInfo);
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric   ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
9470b57cec5SDimitry Andric       llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
9480b57cec5SDimitry Andric 
9490b57cec5SDimitry Andric   struct ptrace_io_desc io;
9500b57cec5SDimitry Andric   io.piod_op = PIOD_READ_AUXV;
9510b57cec5SDimitry Andric   io.piod_offs = 0;
9520b57cec5SDimitry Andric   io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
9530b57cec5SDimitry Andric   io.piod_len = auxv_size;
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric   Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric   if (error.Fail())
9580b57cec5SDimitry Andric     return std::error_code(error.GetError(), std::generic_category());
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   if (io.piod_len < 1)
9610b57cec5SDimitry Andric     return std::error_code(ECANCELED, std::generic_category());
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric   return std::move(buf);
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric 
SetupTrace()966af732203SDimitry Andric Status NativeProcessNetBSD::SetupTrace() {
967af732203SDimitry Andric   // Enable event reporting
968af732203SDimitry Andric   ptrace_event_t events;
969af732203SDimitry Andric   Status status =
970af732203SDimitry Andric       PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));
971af732203SDimitry Andric   if (status.Fail())
972af732203SDimitry Andric     return status;
973*5f7ddb14SDimitry Andric   // TODO: PTRACE_POSIX_SPAWN?
974*5f7ddb14SDimitry Andric   events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |
975*5f7ddb14SDimitry Andric                          PTRACE_VFORK | PTRACE_VFORK_DONE;
976af732203SDimitry Andric   status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));
977af732203SDimitry Andric   if (status.Fail())
978af732203SDimitry Andric     return status;
979af732203SDimitry Andric 
980af732203SDimitry Andric   return ReinitializeThreads();
981af732203SDimitry Andric }
982af732203SDimitry Andric 
ReinitializeThreads()9830b57cec5SDimitry Andric Status NativeProcessNetBSD::ReinitializeThreads() {
9840b57cec5SDimitry Andric   // Clear old threads
9850b57cec5SDimitry Andric   m_threads.clear();
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   // Initialize new thread
988480093f4SDimitry Andric #ifdef PT_LWPSTATUS
989480093f4SDimitry Andric   struct ptrace_lwpstatus info = {};
990480093f4SDimitry Andric   int op = PT_LWPNEXT;
991480093f4SDimitry Andric #else
9920b57cec5SDimitry Andric   struct ptrace_lwpinfo info = {};
993480093f4SDimitry Andric   int op = PT_LWPINFO;
994480093f4SDimitry Andric #endif
995480093f4SDimitry Andric 
996480093f4SDimitry Andric   Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));
997480093f4SDimitry Andric 
9980b57cec5SDimitry Andric   if (error.Fail()) {
9990b57cec5SDimitry Andric     return error;
10000b57cec5SDimitry Andric   }
10010b57cec5SDimitry Andric   // Reinitialize from scratch threads and register them in process
10020b57cec5SDimitry Andric   while (info.pl_lwpid != 0) {
10030b57cec5SDimitry Andric     AddThread(info.pl_lwpid);
1004480093f4SDimitry Andric     error = PtraceWrapper(op, GetID(), &info, sizeof(info));
10050b57cec5SDimitry Andric     if (error.Fail()) {
10060b57cec5SDimitry Andric       return error;
10070b57cec5SDimitry Andric     }
10080b57cec5SDimitry Andric   }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric   return error;
10110b57cec5SDimitry Andric }
1012*5f7ddb14SDimitry Andric 
MonitorClone(::pid_t child_pid,bool is_vfork,NativeThreadNetBSD & parent_thread)1013*5f7ddb14SDimitry Andric void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork,
1014*5f7ddb14SDimitry Andric                                        NativeThreadNetBSD &parent_thread) {
1015*5f7ddb14SDimitry Andric   Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
1016*5f7ddb14SDimitry Andric   LLDB_LOG(log, "clone, child_pid={0}", child_pid);
1017*5f7ddb14SDimitry Andric 
1018*5f7ddb14SDimitry Andric   int status;
1019*5f7ddb14SDimitry Andric   ::pid_t wait_pid =
1020*5f7ddb14SDimitry Andric       llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
1021*5f7ddb14SDimitry Andric   if (wait_pid != child_pid) {
1022*5f7ddb14SDimitry Andric     LLDB_LOG(log,
1023*5f7ddb14SDimitry Andric              "waiting for pid {0} failed. Assuming the pid has "
1024*5f7ddb14SDimitry Andric              "disappeared in the meantime",
1025*5f7ddb14SDimitry Andric              child_pid);
1026*5f7ddb14SDimitry Andric     return;
1027*5f7ddb14SDimitry Andric   }
1028*5f7ddb14SDimitry Andric   if (WIFEXITED(status)) {
1029*5f7ddb14SDimitry Andric     LLDB_LOG(log,
1030*5f7ddb14SDimitry Andric              "waiting for pid {0} returned an 'exited' event. Not "
1031*5f7ddb14SDimitry Andric              "tracking it.",
1032*5f7ddb14SDimitry Andric              child_pid);
1033*5f7ddb14SDimitry Andric     return;
1034*5f7ddb14SDimitry Andric   }
1035*5f7ddb14SDimitry Andric 
1036*5f7ddb14SDimitry Andric   ptrace_siginfo_t info;
1037*5f7ddb14SDimitry Andric   const auto siginfo_err =
1038*5f7ddb14SDimitry Andric       PtraceWrapper(PT_GET_SIGINFO, child_pid, &info, sizeof(info));
1039*5f7ddb14SDimitry Andric   if (siginfo_err.Fail()) {
1040*5f7ddb14SDimitry Andric     LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);
1041*5f7ddb14SDimitry Andric     return;
1042*5f7ddb14SDimitry Andric   }
1043*5f7ddb14SDimitry Andric   assert(info.psi_lwpid >= 0);
1044*5f7ddb14SDimitry Andric   lldb::tid_t child_tid = info.psi_lwpid;
1045*5f7ddb14SDimitry Andric 
1046*5f7ddb14SDimitry Andric   std::unique_ptr<NativeProcessNetBSD> child_process{
1047*5f7ddb14SDimitry Andric       new NativeProcessNetBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,
1048*5f7ddb14SDimitry Andric                               m_delegate, m_arch, m_main_loop)};
1049*5f7ddb14SDimitry Andric   if (!is_vfork)
1050*5f7ddb14SDimitry Andric     child_process->m_software_breakpoints = m_software_breakpoints;
1051*5f7ddb14SDimitry Andric 
1052*5f7ddb14SDimitry Andric   Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;
1053*5f7ddb14SDimitry Andric   if ((m_enabled_extensions & expected_ext) == expected_ext) {
1054*5f7ddb14SDimitry Andric     child_process->SetupTrace();
1055*5f7ddb14SDimitry Andric     for (const auto &thread : child_process->m_threads)
1056*5f7ddb14SDimitry Andric       static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
1057*5f7ddb14SDimitry Andric     child_process->SetState(StateType::eStateStopped, false);
1058*5f7ddb14SDimitry Andric 
1059*5f7ddb14SDimitry Andric     m_delegate.NewSubprocess(this, std::move(child_process));
1060*5f7ddb14SDimitry Andric     if (is_vfork)
1061*5f7ddb14SDimitry Andric       parent_thread.SetStoppedByVFork(child_pid, child_tid);
1062*5f7ddb14SDimitry Andric     else
1063*5f7ddb14SDimitry Andric       parent_thread.SetStoppedByFork(child_pid, child_tid);
1064*5f7ddb14SDimitry Andric     SetState(StateType::eStateStopped, true);
1065*5f7ddb14SDimitry Andric   } else {
1066*5f7ddb14SDimitry Andric     child_process->Detach();
1067*5f7ddb14SDimitry Andric     Status pt_error =
1068*5f7ddb14SDimitry Andric         PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);
1069*5f7ddb14SDimitry Andric     if (pt_error.Fail()) {
1070*5f7ddb14SDimitry Andric       LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),
1071*5f7ddb14SDimitry Andric                      "unable to resume parent process {1}: {0}", GetID());
1072*5f7ddb14SDimitry Andric       SetState(StateType::eStateInvalid);
1073*5f7ddb14SDimitry Andric     }
1074*5f7ddb14SDimitry Andric   }
1075*5f7ddb14SDimitry Andric }
1076