18 #include "llvm/Support/Errno.h"
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <sys/sysctl.h>
27 #include <uvm/uvm_prot.h>
42 int status = fcntl(fd, F_GETFL);
44 error.SetErrorToErrno();
48 if (fcntl(fd, F_SETFL, status | flags) == -1) {
49 error.SetErrorToErrno();
58 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
70 LLDB_LOG(log,
"failed to launch process: {0}", status);
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");
88 if (!Host::GetProcessInfo(pid, Info)) {
89 return llvm::make_error<StringError>(
"Cannot get process architecture",
90 llvm::inconvertibleErrorCode());
94 LLDB_LOG(log,
"pid = {0:x}, detected architecture {1}", pid,
95 Info.GetArchitecture().GetArchitectureName());
99 Info.GetArchitecture(), mainloop));
101 status = process_up->SetupTrace();
105 for (
const auto &thread : process_up->m_threads)
109 return std::move(process_up);
112 llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
113 NativeProcessNetBSD::Factory::Attach(
121 if (!Host::GetProcessInfo(pid, Info)) {
122 return llvm::make_error<StringError>(
"Cannot get process architecture",
123 llvm::inconvertibleErrorCode());
127 pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
129 Status status = process_up->Attach();
133 return std::move(process_up);
137 NativeProcessNetBSD::Factory::GetSupportedExtensions()
const {
139 Extension::pass_signals | Extension::auxv | Extension::libraries_svr4 |
145 NativeProcessNetBSD::NativeProcessNetBSD(::
pid_t pid,
int terminal_fd,
150 m_main_loop(mainloop) {
177 LLDB_LOG(log,
"got exit signal({0}) , pid = {1}", status, pid);
189 ptrace_siginfo_t info;
191 const auto siginfo_err =
195 if (siginfo_err.Success()) {
197 if (info.psi_siginfo.si_code == SI_USER &&
198 info.psi_siginfo.si_pid == ::getpid()) {
211 ptrace_siginfo_t info;
213 const auto siginfo_err =
217 if (siginfo_err.Fail()) {
218 LLDB_LOG(log,
"PT_GET_SIGINFO failed {0}", siginfo_err);
222 LLDB_LOG(log,
"got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid,
223 info.psi_lwpid, info.psi_siginfo.si_code);
226 if (info.psi_lwpid > 0) {
228 if (t->GetID() ==
static_cast<lldb::tid_t>(info.psi_lwpid)) {
235 LLDB_LOG(log,
"thread not found in m_threads, pid = {0}, LWP = {1}", pid,
239 switch (info.psi_siginfo.si_code) {
276 if (pst.pe_report_event == PTRACE_VFORK_DONE) {
282 PtraceWrapper(PT_CONTINUE, pid,
reinterpret_cast<void *
>(1), 0);
287 assert(pst.pe_report_event == PTRACE_FORK ||
288 pst.pe_report_event == PTRACE_VFORK);
289 MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK,
302 switch (pst.pe_report_event) {
303 case PTRACE_LWP_CREATE: {
304 LLDB_LOG(log,
"monitoring new thread, pid = {0}, LWP = {1}", pid,
310 LLDB_LOG(log,
"failed to copy watchpoints to new thread {0}: {1}",
316 case PTRACE_LWP_EXIT:
317 LLDB_LOG(log,
"removing exited thread, pid = {0}, LWP = {1}", pid,
336 wp_index, (uintptr_t)info.psi_siginfo.si_addr);
339 "received error while checking for watchpoint hits, pid = "
340 "{0}, LWP = {1}, error = {2}",
341 pid, info.psi_lwpid,
error);
344 regctx.ClearWatchpointHit(wp_index);
357 LLDB_LOG(log,
"unknown SIGTRAP, passing to generic handler");
363 ptrace_siginfo_t info;
365 const auto siginfo_err =
367 if (siginfo_err.Fail()) {
368 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
372 for (
const auto &abs_thread :
m_threads) {
374 assert(info.psi_lwpid >= 0);
375 if (info.psi_lwpid == 0 ||
385 int data,
int *result) {
391 ret = ptrace(req,
static_cast<::
pid_t>(pid), addr, data);
394 error.SetErrorToErrno();
399 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
408 const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
417 size_t signaled_threads = 0;
420 for (
const auto &thread : threads) {
421 assert(thread &&
"thread list should not contain NULL threads");
427 if (action->
signal != signal) {
429 return Status(
"NetBSD does not support passing multiple signals "
433 signaled_lwp = thread->GetID();
439 if (signaled_threads == 0) {
440 ptrace_siginfo_t siginfo;
445 if (signaled_threads > 1 && signaled_threads < threads.size())
446 return Status(
"NetBSD does not support passing signal to 1<i<all threads")
449 ptrace_siginfo_t siginfo;
450 siginfo.psi_siginfo.si_signo = signal;
451 siginfo.psi_siginfo.si_code = SI_USER;
452 siginfo.psi_siginfo.si_pid = getpid();
453 siginfo.psi_siginfo.si_uid = getuid();
454 if (signaled_threads == 1)
455 siginfo.psi_lwpid = signaled_lwp;
457 siginfo.psi_lwpid = 0;
467 Expected<ptrace_siginfo_t> siginfo =
470 return Status(siginfo.takeError());
472 for (
const auto &abs_thread :
m_threads) {
473 assert(abs_thread &&
"thread list should not contain NULL threads");
483 if (action ==
nullptr) {
484 LLDB_LOG(log,
"no action specified for pid {0} tid {1}",
GetID(),
486 action = &suspend_action;
491 "processing resume action state {0} signal {1} for pid {2} tid {3}",
494 switch (action->
state) {
504 return Status(
"Passing signal to suspended thread unsupported");
510 return Status(
"NativeProcessNetBSD::%s (): unexpected state %s specified "
511 "for pid %" PRIu64
", tid %" PRIu64,
526 signal = siginfo->psi_siginfo.si_signo;
554 if (kill(
GetID(), signo))
555 error.SetErrorToErrno();
577 LLDB_LOG(log,
"ignored for PID {0} due to current state: {1}",
GetID(),
593 error.SetErrorToErrno();
605 return Status(
"unsupported");
622 "descending memory map entries detected, unexpected");
631 range_info.
SetReadable(MemoryRegionInfo::OptionalBool::eNo);
632 range_info.
SetWritable(MemoryRegionInfo::OptionalBool::eNo);
633 range_info.
SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
634 range_info.
SetMapped(MemoryRegionInfo::OptionalBool::eNo);
638 range_info = proc_entry_info;
649 range_info.
SetReadable(MemoryRegionInfo::OptionalBool::eNo);
650 range_info.
SetWritable(MemoryRegionInfo::OptionalBool::eNo);
651 range_info.
SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
652 range_info.
SetMapped(MemoryRegionInfo::OptionalBool::eNo);
661 LLDB_LOG(log,
"reusing {0} cached memory region entries",
666 struct kinfo_vmentry *vm;
668 vm = kinfo_getvmmap(
GetID(), &count);
672 error.SetErrorString(
"not supported");
675 for (i = 0; i < count; i++) {
680 info.
SetMapped(MemoryRegionInfo::OptionalBool::eYes);
682 if (vm[i].kve_protection & VM_PROT_READ)
683 info.
SetReadable(MemoryRegionInfo::OptionalBool::eYes);
685 info.
SetReadable(MemoryRegionInfo::OptionalBool::eNo);
687 if (vm[i].kve_protection & VM_PROT_WRITE)
688 info.
SetWritable(MemoryRegionInfo::OptionalBool::eYes);
690 info.
SetWritable(MemoryRegionInfo::OptionalBool::eNo);
692 if (vm[i].kve_protection & VM_PROT_EXECUTE)
697 if (vm[i].kve_path[0])
708 LLDB_LOG(log,
"failed to find any vmmap entries, assuming no support "
709 "for memory region metadata retrieval");
712 error.SetErrorString(
"not supported");
715 LLDB_LOG(log,
"read {0} memory region entries from process {1}",
732 return Status(
"NativeProcessNetBSD does not support hardware breakpoints");
743 FileSpec module_file_spec(module_path);
748 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
749 file_spec = it.second;
753 return Status(
"Module file (%s) not found in process' memory map!",
766 if (it.second == file) {
767 load_addr = it.first.GetRange().GetRangeBase();
771 return Status(
"No load address found for file %s.", file_name.str().c_str());
777 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid,
GetID(), &status,
783 if (wait_pid == -1) {
795 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
796 GetID(), wait_pid, status, exited);
808 assert(thread &&
"thread list should not contain NULL threads");
809 if (thread->GetID() == thread_id) {
821 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
823 assert(thread_id > 0);
825 "attempted to add a thread by id that already exists");
831 m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*
this, thread_id));
837 LLDB_LOG(log,
"pid {0} removing thread with tid {1}",
GetID(), thread_id);
839 assert(thread_id > 0);
841 "attempted to remove a thread that does not exist");
844 if ((*it)->GetID() == thread_id) {
861 if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid,
m_pid,
nullptr,
881 size_t size,
size_t &bytes_read) {
882 unsigned char *dst =
static_cast<unsigned char *
>(buf);
883 struct ptrace_io_desc io;
886 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
889 io.piod_op = PIOD_READ_D;
893 io.piod_offs = (
void *)(addr + bytes_read);
894 io.piod_addr = dst + bytes_read;
897 if (
error.Fail() || io.piod_len == 0)
900 bytes_read += io.piod_len;
901 io.piod_len = size - bytes_read;
902 }
while (bytes_read < size);
908 size_t size,
size_t &bytes_written) {
909 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
911 struct ptrace_io_desc io;
914 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
917 io.piod_op = PIOD_WRITE_D;
922 const_cast<void *
>(
static_cast<const void *
>(src + bytes_written));
923 io.piod_offs = (
void *)(addr + bytes_written);
926 if (
error.Fail() || io.piod_len == 0)
929 bytes_written += io.piod_len;
930 io.piod_len = size - bytes_written;
931 }
while (bytes_written < size);
936 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
945 size_t auxv_size = 100 *
sizeof(AuxInfo);
947 ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
948 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
950 struct ptrace_io_desc io;
951 io.piod_op = PIOD_READ_AUXV;
953 io.piod_addr =
static_cast<void *
>(buf.get()->getBufferStart());
954 io.piod_len = auxv_size;
959 return std::error_code(
error.GetError(), std::generic_category());
962 return std::error_code(ECANCELED, std::generic_category());
964 return std::move(buf);
969 ptrace_event_t events;
975 events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |
976 PTRACE_VFORK | PTRACE_VFORK_DONE;
990 struct ptrace_lwpstatus info = {};
993 struct ptrace_lwpinfo info = {};
1003 while (info.pl_lwpid != 0) {
1017 LLDB_LOG(log,
"clone, child_pid={0}", child_pid);
1021 llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
1022 if (wait_pid != child_pid) {
1024 "waiting for pid {0} failed. Assuming the pid has "
1025 "disappeared in the meantime",
1029 if (WIFEXITED(status)) {
1031 "waiting for pid {0} returned an 'exited' event. Not "
1037 ptrace_siginfo_t info;
1038 const auto siginfo_err =
1039 PtraceWrapper(PT_GET_SIGINFO, child_pid, &info,
sizeof(info));
1040 if (siginfo_err.Fail()) {
1041 LLDB_LOG(log,
"PT_GET_SIGINFO failed {0}", siginfo_err);
1044 assert(info.psi_lwpid >= 0);
1047 std::unique_ptr<NativeProcessNetBSD> child_process{
1055 child_process->SetupTrace();
1056 for (
const auto &thread : child_process->m_threads)
1067 child_process->Detach();
1070 if (pt_error.
Fail()) {
1072 "unable to resume parent process {1}: {0}",
GetID());
1078 llvm::Expected<std::string>
1080 llvm::SmallString<128> path{path_hint};
1084 if (!path.empty()) {
1087 return path.str().str();
1092 if (std::error_code errc =
1093 llvm::sys::fs::createTemporaryFile(
"lldb",
"core", path))
1094 return llvm::createStringError(errc,
"Unable to create a temporary file");
1098 return error.ToError();
1099 return path.str().str();