1 //===-- NativeProcessNetBSD.cpp ------------------------------- -*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "NativeProcessNetBSD.h"
11 #include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
12 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
13 #include "lldb/Host/HostProcess.h"
14 #include "lldb/Host/common/NativeRegisterContext.h"
15 #include "lldb/Host/posix/ProcessLauncherPosixFork.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Utility/State.h"
18 #include "llvm/Support/Errno.h"
20 // System includes - They have to be included after framework includes because
21 // they define some macros which collide with variable names in other modules
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <sys/sysctl.h>
27 #include <uvm/uvm_prot.h>
33 using namespace lldb_private;
34 using namespace lldb_private::process_netbsd;
37 // Simple helper function to ensure flags are enabled on the given file
39 static Status EnsureFDFlags(int fd, int flags) {
42 int status = fcntl(fd, F_GETFL);
44 error.SetErrorToErrno();
48 if (fcntl(fd, F_SETFL, status | flags) == -1) {
49 error.SetErrorToErrno();
56 // Public Static Methods
58 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
59 NativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
60 NativeDelegate &native_delegate,
61 MainLoop &mainloop) const {
62 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
65 ::pid_t pid = ProcessLauncherPosixFork()
66 .LaunchProcess(launch_info, status)
68 LLDB_LOG(log, "pid = {0:x}", pid);
70 LLDB_LOG(log, "failed to launch process: {0}", status);
71 return status.ToError();
74 // Wait for the child process to trap on its call to execve.
76 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
79 if (!WIFSTOPPED(wstatus)) {
80 LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
81 WaitStatus::Decode(wstatus));
82 return llvm::make_error<StringError>("Could not sync with inferior process",
83 llvm::inconvertibleErrorCode());
85 LLDB_LOG(log, "inferior started, now in stopped state");
87 ProcessInstanceInfo Info;
88 if (!Host::GetProcessInfo(pid, Info)) {
89 return llvm::make_error<StringError>("Cannot get process architecture",
90 llvm::inconvertibleErrorCode());
93 // Set the architecture to the exe architecture.
94 LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
95 Info.GetArchitecture().GetArchitectureName());
97 std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
98 pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
99 Info.GetArchitecture(), mainloop));
101 // Enable event reporting
102 ptrace_event_t events;
103 status = PtraceWrapper(PT_GET_EVENT_MASK, pid, &events, sizeof(events));
105 return status.ToError();
106 // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
107 events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
108 status = PtraceWrapper(PT_SET_EVENT_MASK, pid, &events, sizeof(events));
110 return status.ToError();
112 status = process_up->ReinitializeThreads();
114 return status.ToError();
116 for (const auto &thread : process_up->m_threads)
117 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
118 process_up->SetState(StateType::eStateStopped, false);
120 return std::move(process_up);
123 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
124 NativeProcessNetBSD::Factory::Attach(
125 lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
126 MainLoop &mainloop) const {
127 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
128 LLDB_LOG(log, "pid = {0:x}", pid);
130 // Retrieve the architecture for the running process.
131 ProcessInstanceInfo Info;
132 if (!Host::GetProcessInfo(pid, Info)) {
133 return llvm::make_error<StringError>("Cannot get process architecture",
134 llvm::inconvertibleErrorCode());
137 std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
138 pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
140 Status status = process_up->Attach();
141 if (!status.Success())
142 return status.ToError();
144 return std::move(process_up);
147 // Public Instance Methods
149 NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
150 NativeDelegate &delegate,
151 const ArchSpec &arch,
153 : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
154 if (m_terminal_fd != -1) {
155 Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
156 assert(status.Success());
160 m_sigchld_handle = mainloop.RegisterSignal(
161 SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
162 assert(m_sigchld_handle && status.Success());
165 // Handles all waitpid events from the inferior process.
166 void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
169 return MonitorSIGTRAP(pid);
171 return MonitorSIGSTOP(pid);
173 return MonitorSignal(pid, signal);
177 void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
178 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
180 LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
182 /* Stop Tracking All Threads attached to Process */
185 SetExitStatus(status, true);
187 // Notify delegate that our process has exited.
188 SetState(StateType::eStateExited, true);
191 void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
192 ptrace_siginfo_t info;
194 const auto siginfo_err =
195 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
197 // Get details on the signal raised.
198 if (siginfo_err.Success()) {
199 // Handle SIGSTOP from LLGS (LLDB GDB Server)
200 if (info.psi_siginfo.si_code == SI_USER &&
201 info.psi_siginfo.si_pid == ::getpid()) {
202 /* Stop Tracking all Threads attached to Process */
203 for (const auto &thread : m_threads) {
204 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
205 SIGSTOP, &info.psi_siginfo);
208 SetState(StateType::eStateStopped, true);
212 void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
213 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
214 ptrace_siginfo_t info;
216 const auto siginfo_err =
217 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
219 // Get details on the signal raised.
220 if (siginfo_err.Fail()) {
224 NativeThreadNetBSD* thread = nullptr;
225 if (info.psi_lwpid > 0) {
226 for (const auto &t : m_threads) {
227 if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
228 thread = static_cast<NativeThreadNetBSD *>(t.get());
231 static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
235 "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
239 switch (info.psi_siginfo.si_code) {
242 thread->SetStoppedByBreakpoint();
243 FixupBreakpointPCAsNeeded(*thread);
245 SetState(StateType::eStateStopped, true);
249 thread->SetStoppedByTrace();
250 SetState(StateType::eStateStopped, true);
253 Status error = ReinitializeThreads();
255 SetState(StateType::eStateInvalid);
259 // Let our delegate know we have just exec'd.
262 for (const auto &thread : m_threads)
263 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
264 SetState(StateType::eStateStopped, true);
268 Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
270 SetState(StateType::eStateInvalid);
274 switch (pst.pe_report_event) {
275 case PTRACE_LWP_CREATE: {
277 "monitoring new thread, pid = {0}, LWP = {1}", pid,
279 NativeThreadNetBSD& t = AddThread(pst.pe_lwp);
280 error = t.CopyWatchpointsFrom(
281 static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));
284 "failed to copy watchpoints to new thread {0}: {1}",
286 SetState(StateType::eStateInvalid);
290 case PTRACE_LWP_EXIT:
292 "removing exited thread, pid = {0}, LWP = {1}", pid,
294 RemoveThread(pst.pe_lwp);
298 error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void*>(1), 0);
300 SetState(StateType::eStateInvalid);
308 auto ®ctx = static_cast<NativeRegisterContextNetBSD &>(
309 thread->GetRegisterContext());
310 uint32_t wp_index = LLDB_INVALID_INDEX32;
311 Status error = regctx.GetWatchpointHitIndex(wp_index,
312 (uintptr_t)info.psi_siginfo.si_addr);
315 "received error while checking for watchpoint hits, pid = "
316 "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error);
317 if (wp_index != LLDB_INVALID_INDEX32) {
318 thread->SetStoppedByWatchpoint(wp_index);
319 regctx.ClearWatchpointHit(wp_index);
320 SetState(StateType::eStateStopped, true);
324 thread->SetStoppedByTrace();
325 SetState(StateType::eStateStopped, true);
330 void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
331 ptrace_siginfo_t info;
332 const auto siginfo_err =
333 PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
335 for (const auto &abs_thread : m_threads) {
336 NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
337 assert(info.psi_lwpid >= 0);
338 if (info.psi_lwpid == 0 ||
339 static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
340 thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
342 thread.SetStoppedWithNoReason();
344 SetState(StateType::eStateStopped, true);
347 Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
348 int data, int *result) {
349 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
354 ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);
357 error.SetErrorToErrno();
362 LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
365 LLDB_LOG(log, "ptrace() failed: {0}", error);
370 static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
371 const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
372 const ResumeActionList &resume_actions) {
373 // We need to account for three possible scenarios:
374 // 1. no signal being sent.
375 // 2. a signal being sent to one thread.
376 // 3. a signal being sent to the whole process.
378 // Count signaled threads. While at it, determine which signal is being sent
379 // and ensure there's only one.
380 size_t signaled_threads = 0;
381 int signal = LLDB_INVALID_SIGNAL_NUMBER;
382 lldb::tid_t signaled_lwp;
383 for (const auto &thread : threads) {
384 assert(thread && "thread list should not contain NULL threads");
385 const ResumeAction *action =
386 resume_actions.GetActionForThread(thread->GetID(), true);
388 if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
390 if (action->signal != signal) {
391 if (signal != LLDB_INVALID_SIGNAL_NUMBER)
392 return Status("NetBSD does not support passing multiple signals "
395 signal = action->signal;
396 signaled_lwp = thread->GetID();
402 if (signaled_threads == 0) {
403 ptrace_siginfo_t siginfo;
404 siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
408 if (signaled_threads > 1 && signaled_threads < threads.size())
409 return Status("NetBSD does not support passing signal to 1<i<all threads")
412 ptrace_siginfo_t siginfo;
413 siginfo.psi_siginfo.si_signo = signal;
414 siginfo.psi_siginfo.si_code = SI_USER;
415 siginfo.psi_siginfo.si_pid = getpid();
416 siginfo.psi_siginfo.si_uid = getuid();
417 if (signaled_threads == 1)
418 siginfo.psi_lwpid = signaled_lwp;
419 else // signal for the whole process
420 siginfo.psi_lwpid = 0;
424 Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
425 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
426 LLDB_LOG(log, "pid {0}", GetID());
430 Expected<ptrace_siginfo_t> siginfo =
431 ComputeSignalInfo(m_threads, resume_actions);
433 return Status(siginfo.takeError());
435 for (const auto &abs_thread : m_threads) {
436 assert(abs_thread && "thread list should not contain NULL threads");
437 NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
439 const ResumeAction *action =
440 resume_actions.GetActionForThread(thread.GetID(), true);
441 // we need to explicit issue suspend requests, so it is simpler to map it
442 // into proper action
443 ResumeAction suspend_action{thread.GetID(), eStateSuspended,
444 LLDB_INVALID_SIGNAL_NUMBER};
446 if (action == nullptr) {
447 LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
449 action = &suspend_action;
454 "processing resume action state {0} signal {1} for pid {2} tid {3}",
455 action->state, action->signal, GetID(), thread.GetID());
457 switch (action->state) {
459 ret = thread.Resume();
462 ret = thread.SingleStep();
464 case eStateSuspended:
466 if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
467 return Status("Passing signal to suspended thread unsupported");
469 ret = thread.Suspend();
473 return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
474 "for pid %" PRIu64 ", tid %" PRIu64,
475 __FUNCTION__, StateAsCString(action->state), GetID(),
484 if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
485 ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
489 signal = siginfo->psi_siginfo.si_signo;
492 ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1),
495 SetState(eStateRunning, true);
499 Status NativeProcessNetBSD::Halt() {
500 return PtraceWrapper(PT_STOP, GetID());
503 Status NativeProcessNetBSD::Detach() {
506 // Stop monitoring the inferior.
507 m_sigchld_handle.reset();
509 // Tell ptrace to detach from the process.
510 if (GetID() == LLDB_INVALID_PROCESS_ID)
513 return PtraceWrapper(PT_DETACH, GetID());
516 Status NativeProcessNetBSD::Signal(int signo) {
519 if (kill(GetID(), signo))
520 error.SetErrorToErrno();
525 Status NativeProcessNetBSD::Interrupt() {
526 return PtraceWrapper(PT_STOP, GetID());
529 Status NativeProcessNetBSD::Kill() {
530 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
531 LLDB_LOG(log, "pid {0}", GetID());
536 case StateType::eStateInvalid:
537 case StateType::eStateExited:
538 case StateType::eStateCrashed:
539 case StateType::eStateDetached:
540 case StateType::eStateUnloaded:
541 // Nothing to do - the process is already dead.
542 LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
543 StateAsCString(m_state));
546 case StateType::eStateConnected:
547 case StateType::eStateAttaching:
548 case StateType::eStateLaunching:
549 case StateType::eStateStopped:
550 case StateType::eStateRunning:
551 case StateType::eStateStepping:
552 case StateType::eStateSuspended:
553 // We can try to kill a process in these states.
557 if (kill(GetID(), SIGKILL) != 0) {
558 error.SetErrorToErrno();
565 Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
566 MemoryRegionInfo &range_info) {
568 if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
570 return Status("unsupported");
573 Status error = PopulateMemoryRegionCache();
578 lldb::addr_t prev_base_address = 0;
579 // FIXME start by finding the last region that is <= target address using
580 // binary search. Data is sorted.
581 // There can be a ton of regions on pthreads apps with lots of threads.
582 for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
584 MemoryRegionInfo &proc_entry_info = it->first;
585 // Sanity check assumption that memory map entries are ascending.
586 assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
587 "descending memory map entries detected, unexpected");
588 prev_base_address = proc_entry_info.GetRange().GetRangeBase();
589 UNUSED_IF_ASSERT_DISABLED(prev_base_address);
590 // If the target address comes before this entry, indicate distance to next
592 if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
593 range_info.GetRange().SetRangeBase(load_addr);
594 range_info.GetRange().SetByteSize(
595 proc_entry_info.GetRange().GetRangeBase() - load_addr);
596 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
597 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
598 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
599 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
601 } else if (proc_entry_info.GetRange().Contains(load_addr)) {
602 // The target address is within the memory region we're processing here.
603 range_info = proc_entry_info;
606 // The target memory address comes somewhere after the region we just
609 // If we made it here, we didn't find an entry that contained the given
610 // address. Return the load_addr as start and the amount of bytes betwwen
611 // load address and the end of the memory as size.
612 range_info.GetRange().SetRangeBase(load_addr);
613 range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
614 range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
615 range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
616 range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
617 range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
621 Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
622 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
623 // If our cache is empty, pull the latest. There should always be at least
624 // one memory region if memory region handling is supported.
625 if (!m_mem_region_cache.empty()) {
626 LLDB_LOG(log, "reusing {0} cached memory region entries",
627 m_mem_region_cache.size());
631 struct kinfo_vmentry *vm;
633 vm = kinfo_getvmmap(GetID(), &count);
635 m_supports_mem_region = LazyBool::eLazyBoolNo;
637 error.SetErrorString("not supported");
640 for (i = 0; i < count; i++) {
641 MemoryRegionInfo info;
643 info.GetRange().SetRangeBase(vm[i].kve_start);
644 info.GetRange().SetRangeEnd(vm[i].kve_end);
645 info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
647 if (vm[i].kve_protection & VM_PROT_READ)
648 info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
650 info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
652 if (vm[i].kve_protection & VM_PROT_WRITE)
653 info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
655 info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
657 if (vm[i].kve_protection & VM_PROT_EXECUTE)
658 info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
660 info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
662 if (vm[i].kve_path[0])
663 info.SetName(vm[i].kve_path);
665 m_mem_region_cache.emplace_back(
666 info, FileSpec(info.GetName().GetCString()));
670 if (m_mem_region_cache.empty()) {
671 // No entries after attempting to read them. This shouldn't happen. Assume
672 // we don't support map entries.
673 LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
674 "for memory region metadata retrieval");
675 m_supports_mem_region = LazyBool::eLazyBoolNo;
677 error.SetErrorString("not supported");
680 LLDB_LOG(log, "read {0} memory region entries from process {1}",
681 m_mem_region_cache.size(), GetID());
682 // We support memory retrieval, remember that.
683 m_supports_mem_region = LazyBool::eLazyBoolYes;
687 Status NativeProcessNetBSD::AllocateMemory(size_t size, uint32_t permissions,
688 lldb::addr_t &addr) {
689 return Status("Unimplemented");
692 Status NativeProcessNetBSD::DeallocateMemory(lldb::addr_t addr) {
693 return Status("Unimplemented");
696 lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
697 // punt on this for now
698 return LLDB_INVALID_ADDRESS;
701 size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }
703 Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
706 return Status("NativeProcessNetBSD does not support hardware breakpoints");
708 return SetSoftwareBreakpoint(addr, size);
711 Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
712 FileSpec &file_spec) {
713 return Status("Unimplemented");
716 Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
717 lldb::addr_t &load_addr) {
718 load_addr = LLDB_INVALID_ADDRESS;
722 void NativeProcessNetBSD::SigchldHandler() {
723 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
724 // Process all pending waitpid notifications.
727 llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG);
730 return; // We are done.
732 if (wait_pid == -1) {
733 Status error(errno, eErrorTypePOSIX);
734 LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
737 WaitStatus wait_status = WaitStatus::Decode(status);
738 bool exited = wait_status.type == WaitStatus::Exit ||
739 (wait_status.type == WaitStatus::Signal &&
740 wait_pid == static_cast<::pid_t>(GetID()));
743 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
744 GetID(), wait_pid, status, exited);
747 MonitorExited(wait_pid, wait_status);
749 assert(wait_status.type == WaitStatus::Stop);
750 MonitorCallback(wait_pid, wait_status.status);
754 bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
755 for (const auto &thread : m_threads) {
756 assert(thread && "thread list should not contain NULL threads");
757 if (thread->GetID() == thread_id) {
758 // We have this thread.
763 // We don't have this thread.
767 NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
768 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
769 LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
771 assert(thread_id > 0);
772 assert(!HasThreadNoLock(thread_id) &&
773 "attempted to add a thread by id that already exists");
775 // If this is the first thread, save it as the current thread
776 if (m_threads.empty())
777 SetCurrentThreadID(thread_id);
779 m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*this, thread_id));
780 return static_cast<NativeThreadNetBSD &>(*m_threads.back());
783 void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
784 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
785 LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
787 assert(thread_id > 0);
788 assert(HasThreadNoLock(thread_id) &&
789 "attempted to remove a thread that does not exist");
791 for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
792 if ((*it)->GetID() == thread_id) {
799 Status NativeProcessNetBSD::Attach() {
800 // Attach to the requested process.
801 // An attach will cause the thread to stop with a SIGSTOP.
802 Status status = PtraceWrapper(PT_ATTACH, m_pid);
807 // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
808 // point we should have a thread stopped if waitpid succeeds.
809 if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid,
810 m_pid, nullptr, WALLSIG)) < 0)
811 return Status(errno, eErrorTypePOSIX);
813 /* Initialize threads */
814 status = ReinitializeThreads();
818 for (const auto &thread : m_threads)
819 static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
821 // Let our process instance know the thread has stopped.
822 SetState(StateType::eStateStopped);
826 Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
827 size_t size, size_t &bytes_read) {
828 unsigned char *dst = static_cast<unsigned char *>(buf);
829 struct ptrace_io_desc io;
831 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
832 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
835 io.piod_op = PIOD_READ_D;
839 io.piod_offs = (void *)(addr + bytes_read);
840 io.piod_addr = dst + bytes_read;
842 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
843 if (error.Fail() || io.piod_len == 0)
846 bytes_read += io.piod_len;
847 io.piod_len = size - bytes_read;
848 } while (bytes_read < size);
853 Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
854 size_t size, size_t &bytes_written) {
855 const unsigned char *src = static_cast<const unsigned char *>(buf);
857 struct ptrace_io_desc io;
859 Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
860 LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
863 io.piod_op = PIOD_WRITE_D;
867 io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
868 io.piod_offs = (void *)(addr + bytes_written);
870 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
871 if (error.Fail() || io.piod_len == 0)
874 bytes_written += io.piod_len;
875 io.piod_len = size - bytes_written;
876 } while (bytes_written < size);
881 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
882 NativeProcessNetBSD::GetAuxvData() const {
884 * ELF_AUX_ENTRIES is currently restricted to kernel
885 * (<sys/exec_elf.h> r. 1.155 specifies 15)
887 * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
888 * information isn't needed.
890 size_t auxv_size = 100 * sizeof(AuxInfo);
892 ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
893 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
895 struct ptrace_io_desc io;
896 io.piod_op = PIOD_READ_AUXV;
898 io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
899 io.piod_len = auxv_size;
901 Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
904 return std::error_code(error.GetError(), std::generic_category());
907 return std::error_code(ECANCELED, std::generic_category());
909 return std::move(buf);
912 Status NativeProcessNetBSD::ReinitializeThreads() {
916 // Initialize new thread
918 struct ptrace_lwpstatus info = {};
921 struct ptrace_lwpinfo info = {};
925 Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));
930 // Reinitialize from scratch threads and register them in process
931 while (info.pl_lwpid != 0) {
932 AddThread(info.pl_lwpid);
933 error = PtraceWrapper(op, GetID(), &info, sizeof(info));