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