brintos

brintos / llvm-project-archived public Read only

0
0
Text · 35.1 KiB · 8fb15d8 Raw
1126 lines · cpp
1//===-- NativeProcessNetBSD.cpp -------------------------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "NativeProcessNetBSD.h"10 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"19 20// System includes - They have to be included after framework includes because21// they define some macros which collide with variable names in other modules22// clang-format off23#include <sys/types.h>24#include <sys/ptrace.h>25#include <sys/sysctl.h>26#include <sys/wait.h>27#include <uvm/uvm_prot.h>28#include <elf.h>29#include <util.h>30// clang-format on31 32using namespace lldb;33using namespace lldb_private;34using namespace lldb_private::process_netbsd;35using namespace llvm;36 37// Simple helper function to ensure flags are enabled on the given file38// descriptor.39static Status EnsureFDFlags(int fd, int flags) {40  Status error;41 42  int status = fcntl(fd, F_GETFL);43  if (status == -1) {44    error = Status::FromErrno();45    return error;46  }47 48  if (fcntl(fd, F_SETFL, status | flags) == -1) {49    error = Status::FromErrno();50    return error;51  }52 53  return error;54}55 56// Public Static Methods57 58llvm::Expected<std::unique_ptr<NativeProcessProtocol>>59NativeProcessNetBSD::Manager::Launch(ProcessLaunchInfo &launch_info,60                                     NativeDelegate &native_delegate) {61  Log *log = GetLog(POSIXLog::Process);62 63  Status status;64  ::pid_t pid = ProcessLauncherPosixFork()65                    .LaunchProcess(launch_info, status)66                    .GetProcessId();67  LLDB_LOG(log, "pid = {0:x}", pid);68  if (status.Fail()) {69    LLDB_LOG(log, "failed to launch process: {0}", status);70    return status.ToError();71  }72 73  // Wait for the child process to trap on its call to execve.74  int wstatus;75  ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);76  assert(wpid == pid);77  (void)wpid;78  if (!WIFSTOPPED(wstatus)) {79    LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",80             WaitStatus::Decode(wstatus));81    return llvm::make_error<StringError>("Could not sync with inferior process",82                                         llvm::inconvertibleErrorCode());83  }84  LLDB_LOG(log, "inferior started, now in stopped state");85 86  ProcessInstanceInfo Info;87  if (!Host::GetProcessInfo(pid, Info)) {88    return llvm::make_error<StringError>("Cannot get process architecture",89                                         llvm::inconvertibleErrorCode());90  }91 92  // Set the architecture to the exe architecture.93  LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,94           Info.GetArchitecture().GetArchitectureName());95 96  std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(97      pid, launch_info.GetPTY().ReleasePrimaryFileDescriptor(), native_delegate,98      Info.GetArchitecture(), m_mainloop));99 100  status = process_up->SetupTrace();101  if (status.Fail())102    return status.ToError();103 104  for (const auto &thread : process_up->m_threads)105    static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);106  process_up->SetState(StateType::eStateStopped, false);107 108  return std::move(process_up);109}110 111llvm::Expected<std::unique_ptr<NativeProcessProtocol>>112NativeProcessNetBSD::Manager::Attach(113    lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate) {114  Log *log = GetLog(POSIXLog::Process);115  LLDB_LOG(log, "pid = {0:x}", pid);116 117  // Retrieve the architecture for the running process.118  ProcessInstanceInfo Info;119  if (!Host::GetProcessInfo(pid, Info)) {120    return llvm::make_error<StringError>("Cannot get process architecture",121                                         llvm::inconvertibleErrorCode());122  }123 124  std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(125      pid, -1, native_delegate, Info.GetArchitecture(), m_mainloop));126 127  Status status = process_up->Attach();128  if (!status.Success())129    return status.ToError();130 131  return std::move(process_up);132}133 134NativeProcessNetBSD::Extension135NativeProcessNetBSD::Manager::GetSupportedExtensions() const {136  return Extension::multiprocess | Extension::fork | Extension::vfork |137         Extension::pass_signals | Extension::auxv | Extension::libraries_svr4 |138         Extension::savecore;139}140 141// Public Instance Methods142 143NativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,144                                         NativeDelegate &delegate,145                                         const ArchSpec &arch,146                                         MainLoop &mainloop)147    : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch),148      m_main_loop(mainloop) {149  if (m_terminal_fd != -1) {150    Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);151    assert(status.Success());152  }153 154  Status status;155  m_sigchld_handle = mainloop.RegisterSignal(156      SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);157  assert(m_sigchld_handle && status.Success());158}159 160// Handles all waitpid events from the inferior process.161void NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {162  switch (signal) {163  case SIGTRAP:164    return MonitorSIGTRAP(pid);165  case SIGSTOP:166    return MonitorSIGSTOP(pid);167  default:168    return MonitorSignal(pid, signal);169  }170}171 172void NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {173  Log *log = GetLog(POSIXLog::Process);174 175  LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);176 177  /* Stop Tracking All Threads attached to Process */178  m_threads.clear();179 180  SetExitStatus(status, true);181 182  // Notify delegate that our process has exited.183  SetState(StateType::eStateExited, true);184}185 186void NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {187  ptrace_siginfo_t info;188 189  const auto siginfo_err =190      PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));191 192  // Get details on the signal raised.193  if (siginfo_err.Success()) {194    // Handle SIGSTOP from LLGS (LLDB GDB Server)195    if (info.psi_siginfo.si_code == SI_USER &&196        info.psi_siginfo.si_pid == ::getpid()) {197      /* Stop Tracking all Threads attached to Process */198      for (const auto &thread : m_threads) {199        static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(200            SIGSTOP, &info.psi_siginfo);201      }202    }203    SetState(StateType::eStateStopped, true);204  }205}206 207void NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {208  Log *log = GetLog(POSIXLog::Process);209  ptrace_siginfo_t info;210 211  const auto siginfo_err =212      PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));213 214  // Get details on the signal raised.215  if (siginfo_err.Fail()) {216    LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);217    return;218  }219 220  LLDB_LOG(log, "got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid,221           info.psi_lwpid, info.psi_siginfo.si_code);222  NativeThreadNetBSD *thread = nullptr;223 224  if (info.psi_lwpid > 0) {225    for (const auto &t : m_threads) {226      if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {227        thread = static_cast<NativeThreadNetBSD *>(t.get());228        break;229      }230      static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();231    }232    if (!thread)233      LLDB_LOG(log, "thread not found in m_threads, pid = {0}, LWP = {1}", pid,234               info.psi_lwpid);235  }236 237  switch (info.psi_siginfo.si_code) {238  case TRAP_BRKPT:239    if (thread) {240      thread->SetStoppedByBreakpoint();241      FixupBreakpointPCAsNeeded(*thread);242    }243    SetState(StateType::eStateStopped, true);244    return;245  case TRAP_TRACE:246    if (thread)247      thread->SetStoppedByTrace();248    SetState(StateType::eStateStopped, true);249    return;250  case TRAP_EXEC: {251    Status error = ReinitializeThreads();252    if (error.Fail()) {253      SetState(StateType::eStateInvalid);254      return;255    }256 257    // Let our delegate know we have just exec'd.258    NotifyDidExec();259 260    for (const auto &thread : m_threads)261      static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();262    SetState(StateType::eStateStopped, true);263    return;264  }265  case TRAP_CHLD: {266    ptrace_state_t pst;267    Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));268    if (error.Fail()) {269      SetState(StateType::eStateInvalid);270      return;271    }272 273    assert(thread);274    if (pst.pe_report_event == PTRACE_VFORK_DONE) {275      if ((m_enabled_extensions & Extension::vfork) == Extension::vfork) {276        thread->SetStoppedByVForkDone();277        SetState(StateType::eStateStopped, true);278      } else {279        Status error =280            PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);281        if (error.Fail())282          SetState(StateType::eStateInvalid);283      }284    } else {285      assert(pst.pe_report_event == PTRACE_FORK ||286             pst.pe_report_event == PTRACE_VFORK);287      MonitorClone(pst.pe_other_pid, pst.pe_report_event == PTRACE_VFORK,288                   *thread);289    }290    return;291  }292  case TRAP_LWP: {293    ptrace_state_t pst;294    Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));295    if (error.Fail()) {296      SetState(StateType::eStateInvalid);297      return;298    }299 300    switch (pst.pe_report_event) {301    case PTRACE_LWP_CREATE: {302      LLDB_LOG(log, "monitoring new thread, pid = {0}, LWP = {1}", pid,303               pst.pe_lwp);304      NativeThreadNetBSD &t = AddThread(pst.pe_lwp);305      error = t.CopyWatchpointsFrom(306          static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));307      if (error.Fail()) {308        LLDB_LOG(log, "failed to copy watchpoints to new thread {0}: {1}",309                 pst.pe_lwp, error);310        SetState(StateType::eStateInvalid);311        return;312      }313    } break;314    case PTRACE_LWP_EXIT:315      LLDB_LOG(log, "removing exited thread, pid = {0}, LWP = {1}", pid,316               pst.pe_lwp);317      RemoveThread(pst.pe_lwp);318      break;319    }320 321    error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void *>(1), 0);322    if (error.Fail())323      SetState(StateType::eStateInvalid);324    return;325  }326  case TRAP_DBREG: {327    if (!thread)328      break;329 330    auto &regctx = static_cast<NativeRegisterContextNetBSD &>(331        thread->GetRegisterContext());332    uint32_t wp_index = LLDB_INVALID_INDEX32;333    Status error = regctx.GetWatchpointHitIndex(334        wp_index, (uintptr_t)info.psi_siginfo.si_addr);335    if (error.Fail())336      LLDB_LOG(log,337               "received error while checking for watchpoint hits, pid = "338               "{0}, LWP = {1}, error = {2}",339               pid, info.psi_lwpid, error);340    if (wp_index != LLDB_INVALID_INDEX32) {341      thread->SetStoppedByWatchpoint(wp_index);342      regctx.ClearWatchpointHit(wp_index);343      SetState(StateType::eStateStopped, true);344      return;345    }346 347    thread->SetStoppedByTrace();348    SetState(StateType::eStateStopped, true);349    return;350  }351  }352 353  // Either user-generated SIGTRAP or an unknown event that would354  // otherwise leave the debugger hanging.355  LLDB_LOG(log, "unknown SIGTRAP, passing to generic handler");356  MonitorSignal(pid, SIGTRAP);357}358 359void NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {360  Log *log = GetLog(POSIXLog::Process);361  ptrace_siginfo_t info;362 363  const auto siginfo_err =364      PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));365  if (siginfo_err.Fail()) {366    LLDB_LOG(log, "PT_LWPINFO failed {0}", siginfo_err);367    return;368  }369 370  for (const auto &abs_thread : m_threads) {371    NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);372    assert(info.psi_lwpid >= 0);373    if (info.psi_lwpid == 0 ||374        static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())375      thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);376    else377      thread.SetStoppedWithNoReason();378  }379  SetState(StateType::eStateStopped, true);380}381 382Status NativeProcessNetBSD::StopProcess(lldb::pid_t pid) {383#ifdef PT_STOP384  return PtraceWrapper(PT_STOP, pid);385#else386  Log *log = GetLog(POSIXLog::Ptrace);387  Status error;388  int ret;389 390  errno = 0;391  ret = kill(pid, SIGSTOP);392 393  if (ret == -1)394    error = Status::FromErrno();395 396  LLDB_LOG(log, "kill({0}, SIGSTOP)", pid);397 398  if (error.Fail())399    LLDB_LOG(log, "kill() failed: {0}", error);400 401  return error;402#endif403}404 405Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,406                                          int data, int *result) {407  Log *log = GetLog(POSIXLog::Ptrace);408  Status error;409  int ret;410 411  errno = 0;412  ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);413 414  if (ret == -1)415    error = Status::FromErrno();416 417  if (result)418    *result = ret;419 420  LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);421 422  if (error.Fail())423    LLDB_LOG(log, "ptrace() failed: {0}", error);424 425  return error;426}427 428static llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(429    const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,430    const ResumeActionList &resume_actions) {431  // We need to account for three possible scenarios:432  // 1. no signal being sent.433  // 2. a signal being sent to one thread.434  // 3. a signal being sent to the whole process.435 436  // Count signaled threads.  While at it, determine which signal is being sent437  // and ensure there's only one.438  size_t signaled_threads = 0;439  int signal = LLDB_INVALID_SIGNAL_NUMBER;440  lldb::tid_t signaled_lwp;441  for (const auto &thread : threads) {442    assert(thread && "thread list should not contain NULL threads");443    const ResumeAction *action =444        resume_actions.GetActionForThread(thread->GetID(), true);445    if (action) {446      if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {447        signaled_threads++;448        if (action->signal != signal) {449          if (signal != LLDB_INVALID_SIGNAL_NUMBER)450            return Status::FromErrorString(451                       "NetBSD does not support passing multiple signals "452                       "simultaneously")453                .ToError();454          signal = action->signal;455          signaled_lwp = thread->GetID();456        }457      }458    }459  }460 461  if (signaled_threads == 0) {462    ptrace_siginfo_t siginfo;463    siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;464    return siginfo;465  }466 467  if (signaled_threads > 1 && signaled_threads < threads.size())468    return Status::FromErrorString(469               "NetBSD does not support passing signal to 1<i<all threads")470        .ToError();471 472  ptrace_siginfo_t siginfo;473  siginfo.psi_siginfo.si_signo = signal;474  siginfo.psi_siginfo.si_code = SI_USER;475  siginfo.psi_siginfo.si_pid = getpid();476  siginfo.psi_siginfo.si_uid = getuid();477  if (signaled_threads == 1)478    siginfo.psi_lwpid = signaled_lwp;479  else // signal for the whole process480    siginfo.psi_lwpid = 0;481  return siginfo;482}483 484Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {485  Log *log = GetLog(POSIXLog::Process);486  LLDB_LOG(log, "pid {0}", GetID());487 488  Status ret;489 490  Expected<ptrace_siginfo_t> siginfo =491      ComputeSignalInfo(m_threads, resume_actions);492  if (!siginfo)493    return Status(siginfo.takeError());494 495  for (const auto &abs_thread : m_threads) {496    assert(abs_thread && "thread list should not contain NULL threads");497    NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);498 499    const ResumeAction *action =500        resume_actions.GetActionForThread(thread.GetID(), true);501    // we need to explicit issue suspend requests, so it is simpler to map it502    // into proper action503    ResumeAction suspend_action{thread.GetID(), eStateSuspended,504                                LLDB_INVALID_SIGNAL_NUMBER};505 506    if (action == nullptr) {507      LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),508               thread.GetID());509      action = &suspend_action;510    }511 512    LLDB_LOG(513        log,514        "processing resume action state {0} signal {1} for pid {2} tid {3}",515        action->state, action->signal, GetID(), thread.GetID());516 517    switch (action->state) {518    case eStateRunning:519      ret = thread.Resume();520      break;521    case eStateStepping:522      ret = thread.SingleStep();523      break;524    case eStateSuspended:525    case eStateStopped:526      if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)527        return Status::FromErrorString(528            "Passing signal to suspended thread unsupported");529 530      ret = thread.Suspend();531      break;532 533    default:534      return Status::FromErrorStringWithFormat(535          "NativeProcessNetBSD::%s (): unexpected state %s specified "536          "for pid %" PRIu64 ", tid %" PRIu64,537          __FUNCTION__, StateAsCString(action->state), GetID(), thread.GetID());538    }539 540    if (!ret.Success())541      return ret;542  }543 544  int signal = 0;545  if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {546    ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),547                        sizeof(*siginfo));548    if (!ret.Success())549      return ret;550    signal = siginfo->psi_siginfo.si_signo;551  }552 553  ret =554      PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), signal);555  if (ret.Success())556    SetState(eStateRunning, true);557  return ret;558}559 560Status NativeProcessNetBSD::Halt() { return StopProcess(GetID()); }561 562Status NativeProcessNetBSD::Detach() {563  Status error;564 565  // Stop monitoring the inferior.566  m_sigchld_handle.reset();567 568  // Tell ptrace to detach from the process.569  if (GetID() == LLDB_INVALID_PROCESS_ID)570    return error;571 572  return PtraceWrapper(PT_DETACH, GetID(), reinterpret_cast<void *>(1));573}574 575Status NativeProcessNetBSD::Signal(int signo) {576  Status error;577 578  if (kill(GetID(), signo))579    error = Status::FromErrno();580 581  return error;582}583 584Status NativeProcessNetBSD::Interrupt() { return StopProcess(GetID()); }585 586Status NativeProcessNetBSD::Kill() {587  Log *log = GetLog(POSIXLog::Process);588  LLDB_LOG(log, "pid {0}", GetID());589 590  Status error;591 592  switch (m_state) {593  case StateType::eStateInvalid:594  case StateType::eStateExited:595  case StateType::eStateCrashed:596  case StateType::eStateDetached:597  case StateType::eStateUnloaded:598    // Nothing to do - the process is already dead.599    LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),600             StateAsCString(m_state));601    return error;602 603  case StateType::eStateConnected:604  case StateType::eStateAttaching:605  case StateType::eStateLaunching:606  case StateType::eStateStopped:607  case StateType::eStateRunning:608  case StateType::eStateStepping:609  case StateType::eStateSuspended:610    // We can try to kill a process in these states.611    break;612  }613 614  if (kill(GetID(), SIGKILL) != 0) {615    error = Status::FromErrno();616    return error;617  }618 619  return error;620}621 622Status NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,623                                                MemoryRegionInfo &range_info) {624 625  if (m_supports_mem_region == LazyBool::eLazyBoolNo) {626    // We're done.627    return Status::FromErrorString("unsupported");628  }629 630  Status error = PopulateMemoryRegionCache();631  if (error.Fail()) {632    return error;633  }634 635  lldb::addr_t prev_base_address = 0;636  // FIXME start by finding the last region that is <= target address using637  // binary search.  Data is sorted.638  // There can be a ton of regions on pthreads apps with lots of threads.639  for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();640       ++it) {641    MemoryRegionInfo &proc_entry_info = it->first;642    // Sanity check assumption that memory map entries are ascending.643    assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&644           "descending memory map entries detected, unexpected");645    prev_base_address = proc_entry_info.GetRange().GetRangeBase();646    UNUSED_IF_ASSERT_DISABLED(prev_base_address);647    // If the target address comes before this entry, indicate distance to next648    // region.649    if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {650      range_info.GetRange().SetRangeBase(load_addr);651      range_info.GetRange().SetByteSize(652          proc_entry_info.GetRange().GetRangeBase() - load_addr);653      range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);654      range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);655      range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);656      range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);657      return error;658    } else if (proc_entry_info.GetRange().Contains(load_addr)) {659      // The target address is within the memory region we're processing here.660      range_info = proc_entry_info;661      return error;662    }663    // The target memory address comes somewhere after the region we just664    // parsed.665  }666  // If we made it here, we didn't find an entry that contained the given667  // address. Return the load_addr as start and the amount of bytes betwwen668  // load address and the end of the memory as size.669  range_info.GetRange().SetRangeBase(load_addr);670  range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);671  range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);672  range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);673  range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);674  range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);675  return error;676}677 678Status NativeProcessNetBSD::PopulateMemoryRegionCache() {679  Log *log = GetLog(POSIXLog::Process);680  // If our cache is empty, pull the latest.  There should always be at least681  // one memory region if memory region handling is supported.682  if (!m_mem_region_cache.empty()) {683    LLDB_LOG(log, "reusing {0} cached memory region entries",684             m_mem_region_cache.size());685    return Status();686  }687 688  struct kinfo_vmentry *vm;689  size_t count, i;690  vm = kinfo_getvmmap(GetID(), &count);691  if (vm == NULL) {692    m_supports_mem_region = LazyBool::eLazyBoolNo;693    Status error;694    error = Status::FromErrorString("not supported");695    return error;696  }697  for (i = 0; i < count; i++) {698    MemoryRegionInfo info;699    info.Clear();700    info.GetRange().SetRangeBase(vm[i].kve_start);701    info.GetRange().SetRangeEnd(vm[i].kve_end);702    info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);703 704    if (vm[i].kve_protection & VM_PROT_READ)705      info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);706    else707      info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);708 709    if (vm[i].kve_protection & VM_PROT_WRITE)710      info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);711    else712      info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);713 714    if (vm[i].kve_protection & VM_PROT_EXECUTE)715      info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);716    else717      info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);718 719    if (vm[i].kve_path[0])720      info.SetName(vm[i].kve_path);721 722    m_mem_region_cache.emplace_back(info,723                                    FileSpec(info.GetName().GetCString()));724  }725  free(vm);726 727  if (m_mem_region_cache.empty()) {728    // No entries after attempting to read them.  This shouldn't happen. Assume729    // we don't support map entries.730    LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "731                  "for memory region metadata retrieval");732    m_supports_mem_region = LazyBool::eLazyBoolNo;733    Status error;734    error = Status::FromErrorString("not supported");735    return error;736  }737  LLDB_LOG(log, "read {0} memory region entries from process {1}",738           m_mem_region_cache.size(), GetID());739  // We support memory retrieval, remember that.740  m_supports_mem_region = LazyBool::eLazyBoolYes;741  return Status();742}743 744lldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {745  // punt on this for now746  return LLDB_INVALID_ADDRESS;747}748 749size_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }750 751Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,752                                          bool hardware) {753  if (hardware)754    return Status::FromErrorString(755        "NativeProcessNetBSD does not support hardware breakpoints");756  else757    return SetSoftwareBreakpoint(addr, size);758}759 760Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,761                                                    FileSpec &file_spec) {762  Status error = PopulateMemoryRegionCache();763  if (error.Fail())764    return error;765 766  FileSpec module_file_spec(module_path);767  FileSystem::Instance().Resolve(module_file_spec);768 769  file_spec.Clear();770  for (const auto &it : m_mem_region_cache) {771    if (it.second.GetFilename() == module_file_spec.GetFilename()) {772      file_spec = it.second;773      return Status();774    }775  }776  return Status::FromErrorStringWithFormat(777      "Module file (%s) not found in process' memory map!",778      module_file_spec.GetFilename().AsCString());779}780 781Status NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,782                                               lldb::addr_t &load_addr) {783  load_addr = LLDB_INVALID_ADDRESS;784  Status error = PopulateMemoryRegionCache();785  if (error.Fail())786    return error;787 788  FileSpec file(file_name);789  for (const auto &it : m_mem_region_cache) {790    if (it.second == file) {791      load_addr = it.first.GetRange().GetRangeBase();792      return Status();793    }794  }795  return Status::FromErrorStringWithFormat("No load address found for file %s.",796                                           file_name.str().c_str());797}798 799void NativeProcessNetBSD::SigchldHandler() {800  Log *log = GetLog(POSIXLog::Process);801  int status;802  ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status,803                                                 WALLSIG | WNOHANG);804 805  if (wait_pid == 0)806    return;807 808  if (wait_pid == -1) {809    Status error(errno, eErrorTypePOSIX);810    LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);811    return;812  }813 814  WaitStatus wait_status = WaitStatus::Decode(status);815  bool exited = wait_status.type == WaitStatus::Exit ||816                (wait_status.type == WaitStatus::Signal &&817                 wait_pid == static_cast<::pid_t>(GetID()));818 819  LLDB_LOG(log,820           "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",821           GetID(), wait_pid, status, exited);822 823  if (exited)824    MonitorExited(wait_pid, wait_status);825  else {826    assert(wait_status.type == WaitStatus::Stop);827    MonitorCallback(wait_pid, wait_status.status);828  }829}830 831bool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {832  for (const auto &thread : m_threads) {833    assert(thread && "thread list should not contain NULL threads");834    if (thread->GetID() == thread_id) {835      // We have this thread.836      return true;837    }838  }839 840  // We don't have this thread.841  return false;842}843 844NativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {845  Log *log = GetLog(POSIXLog::Thread);846  LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);847 848  assert(thread_id > 0);849  assert(!HasThreadNoLock(thread_id) &&850         "attempted to add a thread by id that already exists");851 852  // If this is the first thread, save it as the current thread853  if (m_threads.empty())854    SetCurrentThreadID(thread_id);855 856  m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*this, thread_id));857  return static_cast<NativeThreadNetBSD &>(*m_threads.back());858}859 860void NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {861  Log *log = GetLog(POSIXLog::Thread);862  LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);863 864  assert(thread_id > 0);865  assert(HasThreadNoLock(thread_id) &&866         "attempted to remove a thread that does not exist");867 868  for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {869    if ((*it)->GetID() == thread_id) {870      m_threads.erase(it);871      break;872    }873  }874}875 876Status NativeProcessNetBSD::Attach() {877  // Attach to the requested process.878  // An attach will cause the thread to stop with a SIGSTOP.879  Status status = PtraceWrapper(PT_ATTACH, m_pid);880  if (status.Fail())881    return status;882 883  int wstatus;884  // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this885  // point we should have a thread stopped if waitpid succeeds.886  if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid, m_pid, nullptr,887                                             WALLSIG)) < 0)888    return Status(errno, eErrorTypePOSIX);889 890  // Initialize threads and tracing status891  // NB: this needs to be called before we set thread state892  status = SetupTrace();893  if (status.Fail())894    return status;895 896  for (const auto &thread : m_threads)897    static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);898 899  // Let our process instance know the thread has stopped.900  SetCurrentThreadID(m_threads.front()->GetID());901  SetState(StateType::eStateStopped, false);902  return Status();903}904 905Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,906                                       size_t size, size_t &bytes_read) {907  unsigned char *dst = static_cast<unsigned char *>(buf);908  struct ptrace_io_desc io;909 910  Log *log = GetLog(POSIXLog::Memory);911  LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);912 913  bytes_read = 0;914  io.piod_op = PIOD_READ_D;915  io.piod_len = size;916 917  do {918    io.piod_offs = (void *)(addr + bytes_read);919    io.piod_addr = dst + bytes_read;920 921    Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);922    if (error.Fail() || io.piod_len == 0)923      return error;924 925    bytes_read += io.piod_len;926    io.piod_len = size - bytes_read;927  } while (bytes_read < size);928 929  return Status();930}931 932Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,933                                        size_t size, size_t &bytes_written) {934  const unsigned char *src = static_cast<const unsigned char *>(buf);935  Status error;936  struct ptrace_io_desc io;937 938  Log *log = GetLog(POSIXLog::Memory);939  LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);940 941  bytes_written = 0;942  io.piod_op = PIOD_WRITE_D;943  io.piod_len = size;944 945  do {946    io.piod_addr =947        const_cast<void *>(static_cast<const void *>(src + bytes_written));948    io.piod_offs = (void *)(addr + bytes_written);949 950    Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);951    if (error.Fail() || io.piod_len == 0)952      return error;953 954    bytes_written += io.piod_len;955    io.piod_len = size - bytes_written;956  } while (bytes_written < size);957 958  return error;959}960 961llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>962NativeProcessNetBSD::GetAuxvData() const {963  /*964   * ELF_AUX_ENTRIES is currently restricted to kernel965   * (<sys/exec_elf.h> r. 1.155 specifies 15)966   *967   * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this968   * information isn't needed.969   */970  size_t auxv_size = 100 * sizeof(AuxInfo);971 972  ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =973      llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);974 975  struct ptrace_io_desc io;976  io.piod_op = PIOD_READ_AUXV;977  io.piod_offs = 0;978  io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());979  io.piod_len = auxv_size;980 981  Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);982 983  if (error.Fail())984    return std::error_code(error.GetError(), std::generic_category());985 986  if (io.piod_len < 1)987    return std::error_code(ECANCELED, std::generic_category());988 989  return std::move(buf);990}991 992Status NativeProcessNetBSD::SetupTrace() {993  // Enable event reporting994  ptrace_event_t events;995  Status status =996      PtraceWrapper(PT_GET_EVENT_MASK, GetID(), &events, sizeof(events));997  if (status.Fail())998    return status;999  // TODO: PTRACE_POSIX_SPAWN?1000  events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |1001                         PTRACE_VFORK | PTRACE_VFORK_DONE;1002  status = PtraceWrapper(PT_SET_EVENT_MASK, GetID(), &events, sizeof(events));1003  if (status.Fail())1004    return status;1005 1006  return ReinitializeThreads();1007}1008 1009Status NativeProcessNetBSD::ReinitializeThreads() {1010  // Clear old threads1011  m_threads.clear();1012 1013  // Initialize new thread1014#ifdef PT_LWPSTATUS1015  struct ptrace_lwpstatus info = {};1016  int op = PT_LWPNEXT;1017#else1018  struct ptrace_lwpinfo info = {};1019  int op = PT_LWPINFO;1020#endif1021 1022  Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));1023 1024  if (error.Fail()) {1025    return error;1026  }1027  // Reinitialize from scratch threads and register them in process1028  while (info.pl_lwpid != 0) {1029    AddThread(info.pl_lwpid);1030    error = PtraceWrapper(op, GetID(), &info, sizeof(info));1031    if (error.Fail()) {1032      return error;1033    }1034  }1035 1036  return error;1037}1038 1039void NativeProcessNetBSD::MonitorClone(::pid_t child_pid, bool is_vfork,1040                                       NativeThreadNetBSD &parent_thread) {1041  Log *log = GetLog(POSIXLog::Process);1042  LLDB_LOG(log, "clone, child_pid={0}", child_pid);1043 1044  int status;1045  ::pid_t wait_pid =1046      llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);1047  if (wait_pid != child_pid) {1048    LLDB_LOG(log,1049             "waiting for pid {0} failed. Assuming the pid has "1050             "disappeared in the meantime",1051             child_pid);1052    return;1053  }1054  if (WIFEXITED(status)) {1055    LLDB_LOG(log,1056             "waiting for pid {0} returned an 'exited' event. Not "1057             "tracking it.",1058             child_pid);1059    return;1060  }1061 1062  ptrace_siginfo_t info;1063  const auto siginfo_err =1064      PtraceWrapper(PT_GET_SIGINFO, child_pid, &info, sizeof(info));1065  if (siginfo_err.Fail()) {1066    LLDB_LOG(log, "PT_GET_SIGINFO failed {0}", siginfo_err);1067    return;1068  }1069  assert(info.psi_lwpid >= 0);1070  lldb::tid_t child_tid = info.psi_lwpid;1071 1072  std::unique_ptr<NativeProcessNetBSD> child_process{1073      new NativeProcessNetBSD(static_cast<::pid_t>(child_pid), m_terminal_fd,1074                              m_delegate, m_arch, m_main_loop)};1075  if (!is_vfork)1076    child_process->m_software_breakpoints = m_software_breakpoints;1077 1078  Extension expected_ext = is_vfork ? Extension::vfork : Extension::fork;1079  if ((m_enabled_extensions & expected_ext) == expected_ext) {1080    child_process->SetupTrace();1081    for (const auto &thread : child_process->m_threads)1082      static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);1083    child_process->SetState(StateType::eStateStopped, false);1084 1085    m_delegate.NewSubprocess(this, std::move(child_process));1086    if (is_vfork)1087      parent_thread.SetStoppedByVFork(child_pid, child_tid);1088    else1089      parent_thread.SetStoppedByFork(child_pid, child_tid);1090    SetState(StateType::eStateStopped, true);1091  } else {1092    child_process->Detach();1093    Status pt_error =1094        PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1), 0);1095    if (pt_error.Fail()) {1096      LLDB_LOG_ERROR(log, std::move(pt_error.ToError()),1097                     "unable to resume parent process {1}: {0}", GetID());1098      SetState(StateType::eStateInvalid);1099    }1100  }1101}1102 1103llvm::Expected<std::string>1104NativeProcessNetBSD::SaveCore(llvm::StringRef path_hint) {1105  llvm::SmallString<128> path{path_hint};1106  Status error;1107 1108  // Try with the suggested path first.1109  if (!path.empty()) {1110    error = PtraceWrapper(PT_DUMPCORE, GetID(), path.data(), path.size());1111    if (!error.Fail())1112      return path.str().str();1113 1114    // If the request errored, fall back to a generic temporary file.1115  }1116 1117  if (std::error_code errc =1118          llvm::sys::fs::createTemporaryFile("lldb", "core", path))1119    return llvm::createStringError(errc, "Unable to create a temporary file");1120 1121  error = PtraceWrapper(PT_DUMPCORE, GetID(), path.data(), path.size());1122  if (error.Fail())1123    return error.ToError();1124  return path.str().str();1125}1126