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