NativeProcessNetBSD.cpp revision 360784
114331Speter//===-- NativeProcessNetBSD.cpp ------------------------------- -*- C++ -*-===//
214456Ssos//
314331Speter// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
414331Speter// See https://llvm.org/LICENSE.txt for license information.
514331Speter// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
614331Speter//
714331Speter//===----------------------------------------------------------------------===//
814331Speter
9111798Sdes#include "NativeProcessNetBSD.h"
1014331Speter
1114331Speter#include "Plugins/Process/NetBSD/NativeRegisterContextNetBSD.h"
1214331Speter#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
1314331Speter#include "lldb/Host/HostProcess.h"
1414331Speter#include "lldb/Host/common/NativeRegisterContext.h"
1597748Sschweikh#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
1614331Speter#include "lldb/Target/Process.h"
1714331Speter#include "lldb/Utility/State.h"
1814331Speter#include "llvm/Support/Errno.h"
1914331Speter
2014331Speter// System includes - They have to be included after framework includes because
2114331Speter// they define some macros which collide with variable names in other modules
2214331Speter// clang-format off
2314331Speter#include <sys/types.h>
2414331Speter#include <sys/ptrace.h>
2514331Speter#include <sys/sysctl.h>
2614331Speter#include <sys/wait.h>
2714331Speter#include <uvm/uvm_prot.h>
2814331Speter#include <elf.h>
29115705Sobrien#include <util.h>
30115705Sobrien// clang-format on
31115705Sobrien
3214331Speterusing namespace lldb;
3348303Speterusing namespace lldb_private;
34123956Sbdeusing namespace lldb_private::process_netbsd;
35177785Skibusing namespace llvm;
3614331Speter
3739154Sjdp// Simple helper function to ensure flags are enabled on the given file
3814456Ssos// descriptor.
39123956Sbdestatic Status EnsureFDFlags(int fd, int flags) {
4084811Sjhb  Status error;
4176166Smarkm
42123956Sbde  int status = fcntl(fd, F_GETFL);
4376827Salfred  if (status == -1) {
4476166Smarkm    error.SetErrorToErrno();
4514331Speter    return error;
46102814Siedowse  }
4776166Smarkm
4876166Smarkm  if (fcntl(fd, F_SETFL, status | flags) == -1) {
49103050Speter    error.SetErrorToErrno();
50161310Snetchild    return error;
5176166Smarkm  }
5214331Speter
53123956Sbde  return error;
54123956Sbde}
55123956Sbde
56123956Sbde// Public Static Methods
57123956Sbde
5814331Speterllvm::Expected<std::unique_ptr<NativeProcessProtocol>>
59123956SbdeNativeProcessNetBSD::Factory::Launch(ProcessLaunchInfo &launch_info,
6014331Speter                                     NativeDelegate &native_delegate,
61189362Sdchagin                                     MainLoop &mainloop) const {
62103050Speter  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
63138126Sdas
6414331Speter  Status status;
6514331Speter  ::pid_t pid = ProcessLauncherPosixFork()
6668583Smarcel                    .LaunchProcess(launch_info, status)
67218658Sdchagin                    .GetProcessId();
68191741Sdchagin  LLDB_LOG(log, "pid = {0:x}", pid);
69112716Sjhb  if (status.Fail()) {
70189362Sdchagin    LLDB_LOG(log, "failed to launch process: {0}", status);
7168806Sgallatin    return status.ToError();
7264929Smarcel  }
7314331Speter
7460058Speter  // Wait for the child process to trap on its call to execve.
7560058Speter  int wstatus;
7654122Smarcel  ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
7754122Smarcel  assert(wpid == pid);
7859663Sdillon  (void)wpid;
7959663Sdillon  if (!WIFSTOPPED(wstatus)) {
8059663Sdillon    LLDB_LOG(log, "Could not sync with inferior process: wstatus={1}",
8159663Sdillon             WaitStatus::Decode(wstatus));
8259663Sdillon    return llvm::make_error<StringError>("Could not sync with inferior process",
8359663Sdillon                                         llvm::inconvertibleErrorCode());
8483278Smarcel  }
8583278Smarcel  LLDB_LOG(log, "inferior started, now in stopped state");
8683278Smarcel
8783278Smarcel  ProcessInstanceInfo Info;
8883278Smarcel  if (!Host::GetProcessInfo(pid, Info)) {
8983278Smarcel    return llvm::make_error<StringError>("Cannot get process architecture",
9083278Smarcel                                         llvm::inconvertibleErrorCode());
9183278Smarcel  }
9283278Smarcel
93219609Sdchagin  // Set the architecture to the exe architecture.
94219609Sdchagin  LLDB_LOG(log, "pid = {0:x}, detected architecture {1}", pid,
9554122Smarcel           Info.GetArchitecture().GetArchitectureName());
9654122Smarcel
9754122Smarcel  std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
9854122Smarcel      pid, launch_info.GetPTY().ReleaseMasterFileDescriptor(), native_delegate,
9954122Smarcel      Info.GetArchitecture(), mainloop));
10078161Speter
101158311Sambrisko  // Enable event reporting
10254122Smarcel  ptrace_event_t events;
10392765Salfred  status = PtraceWrapper(PT_GET_EVENT_MASK, pid, &events, sizeof(events));
10493074Sbde  if (status.Fail())
10592765Salfred    return status.ToError();
10693074Sbde  // TODO: PTRACE_FORK | PTRACE_VFORK | PTRACE_POSIX_SPAWN?
107151316Sdavidxu  events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT;
108205642Snwhitehorn  status = PtraceWrapper(PT_SET_EVENT_MASK, pid, &events, sizeof(events));
109205642Snwhitehorn  if (status.Fail())
110189362Sdchagin    return status.ToError();
111196512Sbz
11214456Ssos  status = process_up->ReinitializeThreads();
113189362Sdchagin  if (status.Fail())
114189362Sdchagin    return status.ToError();
115189362Sdchagin
116161310Snetchild  for (const auto &thread : process_up->m_threads)
117161310Snetchild    static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
118161310Snetchild  process_up->SetState(StateType::eStateStopped, false);
11914331Speter
12014331Speter  return std::move(process_up);
121161204Snetchild}
122161204Snetchild
123161204Snetchildllvm::Expected<std::unique_ptr<NativeProcessProtocol>>
124161204SnetchildNativeProcessNetBSD::Factory::Attach(
12514331Speter    lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
12641796Sdt    MainLoop &mainloop) const {
127111798Sdes  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
128111798Sdes  LLDB_LOG(log, "pid = {0:x}", pid);
129111798Sdes
130111798Sdes  // Retrieve the architecture for the running process.
131111798Sdes  ProcessInstanceInfo Info;
13214456Ssos  if (!Host::GetProcessInfo(pid, Info)) {
13314456Ssos    return llvm::make_error<StringError>("Cannot get process architecture",
13414456Ssos                                         llvm::inconvertibleErrorCode());
135161204Snetchild  }
136161204Snetchild
13714331Speter  std::unique_ptr<NativeProcessNetBSD> process_up(new NativeProcessNetBSD(
13814331Speter      pid, -1, native_delegate, Info.GetArchitecture(), mainloop));
13951793Smarcel
14051793Smarcel  Status status = process_up->Attach();
14151793Smarcel  if (!status.Success())
142111429Skan    return status.ToError();
14351793Smarcel
14451793Smarcel  return std::move(process_up);
14551793Smarcel}
14651793Smarcel
14751793Smarcel// Public Instance Methods
14814331Speter
14914331SpeterNativeProcessNetBSD::NativeProcessNetBSD(::pid_t pid, int terminal_fd,
15051793Smarcel                                         NativeDelegate &delegate,
15151793Smarcel                                         const ArchSpec &arch,
15251793Smarcel                                         MainLoop &mainloop)
15351793Smarcel    : NativeProcessELF(pid, terminal_fd, delegate), m_arch(arch) {
15451793Smarcel  if (m_terminal_fd != -1) {
15551793Smarcel    Status status = EnsureFDFlags(m_terminal_fd, O_NONBLOCK);
15651793Smarcel    assert(status.Success());
15751793Smarcel  }
158111429Skan
15914331Speter  Status status;
16014331Speter  m_sigchld_handle = mainloop.RegisterSignal(
16186647Spb      SIGCHLD, [this](MainLoopBase &) { SigchldHandler(); }, status);
16286647Spb  assert(m_sigchld_handle && status.Success());
16386647Spb}
16486647Spb
16586647Spb// Handles all waitpid events from the inferior process.
16686647Spbvoid NativeProcessNetBSD::MonitorCallback(lldb::pid_t pid, int signal) {
16786647Spb  switch (signal) {
16886647Spb  case SIGTRAP:
16986647Spb    return MonitorSIGTRAP(pid);
17086647Spb  case SIGSTOP:
17186647Spb    return MonitorSIGSTOP(pid);
17286647Spb  default:
17386647Spb    return MonitorSignal(pid, signal);
17486647Spb  }
17586647Spb}
17686647Spb
17786647Spbvoid NativeProcessNetBSD::MonitorExited(lldb::pid_t pid, WaitStatus status) {
17886647Spb  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
17986647Spb
18086647Spb  LLDB_LOG(log, "got exit signal({0}) , pid = {1}", status, pid);
18186647Spb
18286647Spb  /* Stop Tracking All Threads attached to Process */
18386647Spb  m_threads.clear();
18486647Spb
18586647Spb  SetExitStatus(status, true);
18686647Spb
18786647Spb  // Notify delegate that our process has exited.
18886647Spb  SetState(StateType::eStateExited, true);
18986647Spb}
19086647Spb
19186647Spbvoid NativeProcessNetBSD::MonitorSIGSTOP(lldb::pid_t pid) {
19286647Spb  ptrace_siginfo_t info;
19386647Spb
19486647Spb  const auto siginfo_err =
19586647Spb      PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
19686647Spb
19786647Spb  // Get details on the signal raised.
19886647Spb  if (siginfo_err.Success()) {
19986647Spb    // Handle SIGSTOP from LLGS (LLDB GDB Server)
20035496Seivind    if (info.psi_siginfo.si_code == SI_USER &&
20135496Seivind        info.psi_siginfo.si_pid == ::getpid()) {
20235496Seivind      /* Stop Tracking all Threads attached to Process */
20382585Sdillon      for (const auto &thread : m_threads) {
20482585Sdillon        static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(
20535496Seivind            SIGSTOP, &info.psi_siginfo);
20633181Seivind      }
20735496Seivind    }
20835496Seivind    SetState(StateType::eStateStopped, true);
20935820Seivind  }
21035820Seivind}
21135820Seivind
21235820Seivindvoid NativeProcessNetBSD::MonitorSIGTRAP(lldb::pid_t pid) {
21335820Seivind  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
21435820Seivind  ptrace_siginfo_t info;
21535820Seivind
21635820Seivind  const auto siginfo_err =
21735496Seivind      PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
21835496Seivind
21935496Seivind  // Get details on the signal raised.
22035496Seivind  if (siginfo_err.Fail()) {
22135496Seivind    return;
22235496Seivind  }
22355141Sbde
22414331Speter  NativeThreadNetBSD* thread = nullptr;
22555141Sbde  if (info.psi_lwpid > 0) {
22614331Speter    for (const auto &t : m_threads) {
22714456Ssos      if (t->GetID() == static_cast<lldb::tid_t>(info.psi_lwpid)) {
228140992Ssobomax        thread = static_cast<NativeThreadNetBSD *>(t.get());
22914456Ssos        break;
230232451Skib      }
23114456Ssos      static_cast<NativeThreadNetBSD *>(t.get())->SetStoppedWithNoReason();
232232451Skib    }
23314456Ssos    if (!thread)
234232451Skib      LLDB_LOG(log,
235189362Sdchagin               "thread not found in m_threads, pid = {0}, LWP = {1}", pid,
23614331Speter               info.psi_lwpid);
23714331Speter  }
23833181Seivind
23955141Sbde  switch (info.psi_siginfo.si_code) {
24014456Ssos  case TRAP_BRKPT:
241189362Sdchagin    if (thread) {
242112470Sjhb      thread->SetStoppedByBreakpoint();
243189362Sdchagin      FixupBreakpointPCAsNeeded(*thread);
244189362Sdchagin    }
24555141Sbde    SetState(StateType::eStateStopped, true);
246294905Sdelphij    break;
247111798Sdes  case TRAP_TRACE:
248177091Sjeff    if (thread)
249112470Sjhb      thread->SetStoppedByTrace();
250189362Sdchagin    SetState(StateType::eStateStopped, true);
251189362Sdchagin    break;
252294905Sdelphij  case TRAP_EXEC: {
253189362Sdchagin    Status error = ReinitializeThreads();
254220026Sdchagin    if (error.Fail()) {
255112470Sjhb      SetState(StateType::eStateInvalid);
256140992Ssobomax      return;
257111798Sdes    }
258189362Sdchagin
259191973Sdchagin    // Let our delegate know we have just exec'd.
260191973Sdchagin    NotifyDidExec();
261191973Sdchagin
262191973Sdchagin    for (const auto &thread : m_threads)
263191973Sdchagin      static_cast<NativeThreadNetBSD &>(*thread).SetStoppedByExec();
264191973Sdchagin    SetState(StateType::eStateStopped, true);
265191973Sdchagin  } break;
266191973Sdchagin  case TRAP_LWP: {
267191973Sdchagin    ptrace_state_t pst;
268191973Sdchagin    Status error = PtraceWrapper(PT_GET_PROCESS_STATE, pid, &pst, sizeof(pst));
269191973Sdchagin    if (error.Fail()) {
27014456Ssos      SetState(StateType::eStateInvalid);
27114456Ssos      return;
27214456Ssos    }
27314456Ssos
27414456Ssos    switch (pst.pe_report_event) {
27514456Ssos      case PTRACE_LWP_CREATE: {
27614456Ssos        LLDB_LOG(log,
277294905Sdelphij                 "monitoring new thread, pid = {0}, LWP = {1}", pid,
27877183Srwatson                 pst.pe_lwp);
27977183Srwatson        NativeThreadNetBSD& t = AddThread(pst.pe_lwp);
28077183Srwatson        error = t.CopyWatchpointsFrom(
28177183Srwatson            static_cast<NativeThreadNetBSD &>(*GetCurrentThread()));
282189362Sdchagin        if (error.Fail()) {
283189362Sdchagin          LLDB_LOG(log,
284189362Sdchagin                   "failed to copy watchpoints to new thread {0}: {1}",
28514456Ssos                   pst.pe_lwp, error);
286111798Sdes          SetState(StateType::eStateInvalid);
287111798Sdes          return;
28814456Ssos        }
28914331Speter      } break;
29014456Ssos      case PTRACE_LWP_EXIT:
291232451Skib        LLDB_LOG(log,
292189362Sdchagin                 "removing exited thread, pid = {0}, LWP = {1}", pid,
29314456Ssos                 pst.pe_lwp);
29414331Speter        RemoveThread(pst.pe_lwp);
295189362Sdchagin        break;
296189362Sdchagin    }
297189362Sdchagin
298189362Sdchagin    error = PtraceWrapper(PT_CONTINUE, pid, reinterpret_cast<void*>(1), 0);
299189362Sdchagin    if (error.Fail()) {
300189362Sdchagin      SetState(StateType::eStateInvalid);
301189362Sdchagin      return;
302189362Sdchagin    }
303189362Sdchagin  } break;
304189362Sdchagin  case TRAP_DBREG: {
305189362Sdchagin    if (!thread)
306189362Sdchagin      break;
307189362Sdchagin
308189362Sdchagin    auto &regctx = static_cast<NativeRegisterContextNetBSD &>(
309189362Sdchagin        thread->GetRegisterContext());
310189362Sdchagin    uint32_t wp_index = LLDB_INVALID_INDEX32;
311189362Sdchagin    Status error = regctx.GetWatchpointHitIndex(wp_index,
312189362Sdchagin        (uintptr_t)info.psi_siginfo.si_addr);
313189362Sdchagin    if (error.Fail())
314219609Sdchagin      LLDB_LOG(log,
315219609Sdchagin               "received error while checking for watchpoint hits, pid = "
316189362Sdchagin               "{0}, LWP = {1}, error = {2}", pid, info.psi_lwpid, error);
317189362Sdchagin    if (wp_index != LLDB_INVALID_INDEX32) {
318189362Sdchagin      thread->SetStoppedByWatchpoint(wp_index);
319189362Sdchagin      regctx.ClearWatchpointHit(wp_index);
320219609Sdchagin      SetState(StateType::eStateStopped, true);
321219609Sdchagin      break;
322189362Sdchagin    }
323189362Sdchagin
324189362Sdchagin    thread->SetStoppedByTrace();
325189362Sdchagin    SetState(StateType::eStateStopped, true);
326189362Sdchagin  } break;
327189362Sdchagin  }
328189362Sdchagin}
329189362Sdchagin
330189362Sdchaginvoid NativeProcessNetBSD::MonitorSignal(lldb::pid_t pid, int signal) {
331189362Sdchagin  ptrace_siginfo_t info;
332189362Sdchagin  const auto siginfo_err =
333189362Sdchagin      PtraceWrapper(PT_GET_SIGINFO, pid, &info, sizeof(info));
334189362Sdchagin
335189362Sdchagin  for (const auto &abs_thread : m_threads) {
336189362Sdchagin    NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
337189362Sdchagin    assert(info.psi_lwpid >= 0);
338189362Sdchagin    if (info.psi_lwpid == 0 ||
339189362Sdchagin        static_cast<lldb::tid_t>(info.psi_lwpid) == thread.GetID())
340189362Sdchagin      thread.SetStoppedBySignal(info.psi_siginfo.si_signo, &info.psi_siginfo);
341189362Sdchagin    else
342189362Sdchagin      thread.SetStoppedWithNoReason();
343189362Sdchagin  }
344189362Sdchagin  SetState(StateType::eStateStopped, true);
345189362Sdchagin}
346189362Sdchagin
347189362SdchaginStatus NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
348189362Sdchagin                                          int data, int *result) {
349189362Sdchagin  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
350189362Sdchagin  Status error;
351189362Sdchagin  int ret;
352189362Sdchagin
353189362Sdchagin  errno = 0;
354189362Sdchagin  ret = ptrace(req, static_cast<::pid_t>(pid), addr, data);
355189362Sdchagin
356189362Sdchagin  if (ret == -1)
357189362Sdchagin    error.SetErrorToErrno();
358189362Sdchagin
359189362Sdchagin  if (result)
360189362Sdchagin    *result = ret;
361189362Sdchagin
362189362Sdchagin  LLDB_LOG(log, "ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
363189362Sdchagin
364189362Sdchagin  if (error.Fail())
365189362Sdchagin    LLDB_LOG(log, "ptrace() failed: {0}", error);
366189362Sdchagin
367189362Sdchagin  return error;
368189362Sdchagin}
369189362Sdchagin
370189362Sdchaginstatic llvm::Expected<ptrace_siginfo_t> ComputeSignalInfo(
371189362Sdchagin    const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
372189362Sdchagin    const ResumeActionList &resume_actions) {
373189362Sdchagin  // We need to account for three possible scenarios:
374189362Sdchagin  // 1. no signal being sent.
375189362Sdchagin  // 2. a signal being sent to one thread.
376189362Sdchagin  // 3. a signal being sent to the whole process.
377189362Sdchagin
378189362Sdchagin  // Count signaled threads.  While at it, determine which signal is being sent
379189362Sdchagin  // and ensure there's only one.
380189362Sdchagin  size_t signaled_threads = 0;
381189362Sdchagin  int signal = LLDB_INVALID_SIGNAL_NUMBER;
382189362Sdchagin  lldb::tid_t signaled_lwp;
383189362Sdchagin  for (const auto &thread : threads) {
384189362Sdchagin    assert(thread && "thread list should not contain NULL threads");
385189362Sdchagin    const ResumeAction *action =
386189362Sdchagin        resume_actions.GetActionForThread(thread->GetID(), true);
387189362Sdchagin    if (action) {
388189362Sdchagin      if (action->signal != LLDB_INVALID_SIGNAL_NUMBER) {
389189362Sdchagin        signaled_threads++;
390189362Sdchagin        if (action->signal != signal) {
391189362Sdchagin          if (signal != LLDB_INVALID_SIGNAL_NUMBER)
392189362Sdchagin            return Status("NetBSD does not support passing multiple signals "
393189362Sdchagin                          "simultaneously")
394189362Sdchagin                .ToError();
395189362Sdchagin          signal = action->signal;
396189362Sdchagin          signaled_lwp = thread->GetID();
397189362Sdchagin        }
398189362Sdchagin      }
399189362Sdchagin    }
400189362Sdchagin  }
401189362Sdchagin
402189362Sdchagin  if (signaled_threads == 0) {
403189362Sdchagin    ptrace_siginfo_t siginfo;
40414331Speter    siginfo.psi_siginfo.si_signo = LLDB_INVALID_SIGNAL_NUMBER;
40573011Sjake    return siginfo;
40614331Speter  }
40767234Sgallatin
408151316Sdavidxu  if (signaled_threads > 1 && signaled_threads < threads.size())
40967234Sgallatin    return Status("NetBSD does not support passing signal to 1<i<all threads")
410111798Sdes        .ToError();
411111798Sdes
412114983Sjhb  ptrace_siginfo_t siginfo;
413111798Sdes  siginfo.psi_siginfo.si_signo = signal;
41483221Smarcel  siginfo.psi_siginfo.si_code = SI_USER;
415151316Sdavidxu  siginfo.psi_siginfo.si_pid = getpid();
41667234Sgallatin  siginfo.psi_siginfo.si_uid = getuid();
41767234Sgallatin  if (signaled_threads == 1)
418151316Sdavidxu    siginfo.psi_lwpid = signaled_lwp;
419151316Sdavidxu  else // signal for the whole process
42083163Sjhb    siginfo.psi_lwpid = 0;
421114983Sjhb  return siginfo;
422114983Sjhb}
42383366Sjulian
42469379SmarcelStatus NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
42567234Sgallatin  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
42667234Sgallatin  LLDB_LOG(log, "pid {0}", GetID());
42783221Smarcel
428151343Sjhb  Status ret;
42972543Sjlemon
43067234Sgallatin  Expected<ptrace_siginfo_t> siginfo =
43167234Sgallatin      ComputeSignalInfo(m_threads, resume_actions);
43267234Sgallatin  if (!siginfo)
43367234Sgallatin    return Status(siginfo.takeError());
434124092Sdavidxu
435114983Sjhb  for (const auto &abs_thread : m_threads) {
436124092Sdavidxu    assert(abs_thread && "thread list should not contain NULL threads");
437124092Sdavidxu    NativeThreadNetBSD &thread = static_cast<NativeThreadNetBSD &>(*abs_thread);
43869379Smarcel
43983221Smarcel    const ResumeAction *action =
440114983Sjhb        resume_actions.GetActionForThread(thread.GetID(), true);
44167234Sgallatin    // we need to explicit issue suspend requests, so it is simpler to map it
44267234Sgallatin    // into proper action
44367234Sgallatin    ResumeAction suspend_action{thread.GetID(), eStateSuspended,
44467234Sgallatin                                LLDB_INVALID_SIGNAL_NUMBER};
44567234Sgallatin
44667234Sgallatin    if (action == nullptr) {
44767234Sgallatin      LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
44867234Sgallatin               thread.GetID());
449106332Smarcel      action = &suspend_action;
450106332Smarcel    }
45167234Sgallatin
45267234Sgallatin    LLDB_LOG(
45367234Sgallatin        log,
45467234Sgallatin        "processing resume action state {0} signal {1} for pid {2} tid {3}",
45569081Smarcel        action->state, action->signal, GetID(), thread.GetID());
456103077Sjmallett
457184058Skib    switch (action->state) {
45869081Smarcel    case eStateRunning:
45967234Sgallatin      ret = thread.Resume();
46067234Sgallatin      break;
46167234Sgallatin    case eStateStepping:
46269081Smarcel      ret = thread.SingleStep();
46369081Smarcel      break;
46469081Smarcel    case eStateSuspended:
465124092Sdavidxu    case eStateStopped:
466124092Sdavidxu      if (action->signal != LLDB_INVALID_SIGNAL_NUMBER)
467124092Sdavidxu        return Status("Passing signal to suspended thread unsupported");
46869379Smarcel
46971497Sjhb      ret = thread.Suspend();
47069081Smarcel      break;
47169081Smarcel
47269081Smarcel    default:
47369081Smarcel      return Status("NativeProcessNetBSD::%s (): unexpected state %s specified "
47467234Sgallatin                    "for pid %" PRIu64 ", tid %" PRIu64,
47567234Sgallatin                    __FUNCTION__, StateAsCString(action->state), GetID(),
47667234Sgallatin                    thread.GetID());
47767234Sgallatin    }
47867234Sgallatin
47967234Sgallatin    if (!ret.Success())
48067234Sgallatin      return ret;
48167234Sgallatin  }
48267234Sgallatin
48367234Sgallatin  int signal = 0;
48467234Sgallatin  if (siginfo->psi_siginfo.si_signo != LLDB_INVALID_SIGNAL_NUMBER) {
48567234Sgallatin    ret = PtraceWrapper(PT_SET_SIGINFO, GetID(), &siginfo.get(),
48667234Sgallatin                        sizeof(*siginfo));
48767234Sgallatin    if (!ret.Success())
48867234Sgallatin      return ret;
48967234Sgallatin    signal = siginfo->psi_siginfo.si_signo;
49067234Sgallatin  }
491172255Skib
49286647Spb  ret = PtraceWrapper(PT_CONTINUE, GetID(), reinterpret_cast<void *>(1),
49367234Sgallatin                      signal);
49467234Sgallatin  if (ret.Success())
49583221Smarcel    SetState(eStateRunning, true);
49672543Sjlemon  return ret;
497124113Sdavidxu}
498124113Sdavidxu
49967234SgallatinStatus NativeProcessNetBSD::Halt() {
50067234Sgallatin  return PtraceWrapper(PT_STOP, GetID());
50167234Sgallatin}
50267234Sgallatin
50367234SgallatinStatus NativeProcessNetBSD::Detach() {
50467234Sgallatin  Status error;
50567234Sgallatin
50692642Salc  // Stop monitoring the inferior.
50792642Salc  m_sigchld_handle.reset();
50892642Salc
50992642Salc  // Tell ptrace to detach from the process.
51092642Salc  if (GetID() == LLDB_INVALID_PROCESS_ID)
51173929Sjhb    return error;
51283366Sjulian
51367234Sgallatin  return PtraceWrapper(PT_DETACH, GetID());
51467234Sgallatin}
51567234Sgallatin
51667234SgallatinStatus NativeProcessNetBSD::Signal(int signo) {
51767234Sgallatin  Status error;
51867234Sgallatin
519219609Sdchagin  if (kill(GetID(), signo))
520177145Skib    error.SetErrorToErrno();
52167234Sgallatin
52267234Sgallatin  return error;
52367234Sgallatin}
52467234Sgallatin
52567234SgallatinStatus NativeProcessNetBSD::Interrupt() {
52683163Sjhb  return PtraceWrapper(PT_STOP, GetID());
527114983Sjhb}
52867234Sgallatin
52967234SgallatinStatus NativeProcessNetBSD::Kill() {
53067234Sgallatin  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
53114331Speter  LLDB_LOG(log, "pid {0}", GetID());
53214331Speter
53314331Speter  Status error;
53414331Speter
53514331Speter  switch (m_state) {
53614331Speter  case StateType::eStateInvalid:
53714331Speter  case StateType::eStateExited:
53814331Speter  case StateType::eStateCrashed:
53914331Speter  case StateType::eStateDetached:
54014331Speter  case StateType::eStateUnloaded:
54133181Seivind    // Nothing to do - the process is already dead.
542151316Sdavidxu    LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(),
54314331Speter             StateAsCString(m_state));
544111798Sdes    return error;
545111798Sdes
546114983Sjhb  case StateType::eStateConnected:
547111798Sdes  case StateType::eStateAttaching:
54883221Smarcel  case StateType::eStateLaunching:
54983221Smarcel  case StateType::eStateStopped:
550151316Sdavidxu  case StateType::eStateRunning:
55168689Sgallatin  case StateType::eStateStepping:
55214331Speter  case StateType::eStateSuspended:
55383587Sjhb    // We can try to kill a process in these states.
554114983Sjhb    break;
555151316Sdavidxu  }
556151316Sdavidxu
557114983Sjhb  if (kill(GetID(), SIGKILL) != 0) {
558114983Sjhb    error.SetErrorToErrno();
55969081Smarcel    return error;
560151316Sdavidxu  }
56169081Smarcel
56269081Smarcel  return error;
56383366Sjulian}
56469379Smarcel
56514331SpeterStatus NativeProcessNetBSD::GetMemoryRegionInfo(lldb::addr_t load_addr,
56614331Speter                                                MemoryRegionInfo &range_info) {
56783221Smarcel
568151343Sjhb  if (m_supports_mem_region == LazyBool::eLazyBoolNo) {
56972543Sjlemon    // We're done.
57014331Speter    return Status("unsupported");
57167234Sgallatin  }
57214331Speter
57314331Speter  Status error = PopulateMemoryRegionCache();
57414331Speter  if (error.Fail()) {
575124092Sdavidxu    return error;
576114983Sjhb  }
577124092Sdavidxu
578124092Sdavidxu  lldb::addr_t prev_base_address = 0;
57969379Smarcel  // FIXME start by finding the last region that is <= target address using
58083221Smarcel  // binary search.  Data is sorted.
581114983Sjhb  // There can be a ton of regions on pthreads apps with lots of threads.
58271497Sjhb  for (auto it = m_mem_region_cache.begin(); it != m_mem_region_cache.end();
58314331Speter       ++it) {
58414331Speter    MemoryRegionInfo &proc_entry_info = it->first;
58514331Speter    // Sanity check assumption that memory map entries are ascending.
58614331Speter    assert((proc_entry_info.GetRange().GetRangeBase() >= prev_base_address) &&
58751793Smarcel           "descending memory map entries detected, unexpected");
58851793Smarcel    prev_base_address = proc_entry_info.GetRange().GetRangeBase();
58951793Smarcel    UNUSED_IF_ASSERT_DISABLED(prev_base_address);
59014331Speter    // If the target address comes before this entry, indicate distance to next
591106332Smarcel    // region.
592106332Smarcel    if (load_addr < proc_entry_info.GetRange().GetRangeBase()) {
59314331Speter      range_info.GetRange().SetRangeBase(load_addr);
59414331Speter      range_info.GetRange().SetByteSize(
59514331Speter          proc_entry_info.GetRange().GetRangeBase() - load_addr);
59669081Smarcel      range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
59769081Smarcel      range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
59814331Speter      range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
59914331Speter      range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
60014331Speter      return error;
60169081Smarcel    } else if (proc_entry_info.GetRange().Contains(load_addr)) {
60246129Sluoqi      // The target address is within the memory region we're processing here.
60346129Sluoqi      range_info = proc_entry_info;
60425553Speter      return error;
60525553Speter    }
60625553Speter    // The target memory address comes somewhere after the region we just
60725553Speter    // parsed.
60825553Speter  }
60925553Speter  // If we made it here, we didn't find an entry that contained the given
61025553Speter  // address. Return the load_addr as start and the amount of bytes betwwen
61125553Speter  // load address and the end of the memory as size.
61225553Speter  range_info.GetRange().SetRangeBase(load_addr);
61325553Speter  range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
61425553Speter  range_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
61525553Speter  range_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
61625553Speter  range_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
61725553Speter  range_info.SetMapped(MemoryRegionInfo::OptionalBool::eNo);
61825553Speter  return error;
619172255Skib}
620151316Sdavidxu
62169081SmarcelStatus NativeProcessNetBSD::PopulateMemoryRegionCache() {
62268689Sgallatin  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
62369081Smarcel  // If our cache is empty, pull the latest.  There should always be at least
62469081Smarcel  // one memory region if memory region handling is supported.
62514331Speter  if (!m_mem_region_cache.empty()) {
62614331Speter    LLDB_LOG(log, "reusing {0} cached memory region entries",
62714331Speter             m_mem_region_cache.size());
62814331Speter    return Status();
62914331Speter  }
63073929Sjhb
63183366Sjulian  struct kinfo_vmentry *vm;
63214331Speter  size_t count, i;
63314331Speter  vm = kinfo_getvmmap(GetID(), &count);
63414331Speter  if (vm == NULL) {
63514331Speter    m_supports_mem_region = LazyBool::eLazyBoolNo;
63614331Speter    Status error;
63725553Speter    error.SetErrorString("not supported");
638219609Sdchagin    return error;
639177145Skib  }
64025553Speter  for (i = 0; i < count; i++) {
64125553Speter    MemoryRegionInfo info;
64225553Speter    info.Clear();
64346129Sluoqi    info.GetRange().SetRangeBase(vm[i].kve_start);
64425553Speter    info.GetRange().SetRangeEnd(vm[i].kve_end);
64583221Smarcel    info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
646114983Sjhb
64714331Speter    if (vm[i].kve_protection & VM_PROT_READ)
64814331Speter      info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
64914331Speter    else
65014331Speter      info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
65114331Speter
65214331Speter    if (vm[i].kve_protection & VM_PROT_WRITE)
65314331Speter      info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
65414331Speter    else
65514331Speter      info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
65614331Speter
65714331Speter    if (vm[i].kve_protection & VM_PROT_EXECUTE)
65814331Speter      info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
65914331Speter    else
660105441Smarkm      info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
66114331Speter
66283221Smarcel    if (vm[i].kve_path[0])
663111798Sdes      info.SetName(vm[i].kve_path);
66483221Smarcel
665198507Skib    m_mem_region_cache.emplace_back(
66668689Sgallatin        info, FileSpec(info.GetName().GetCString()));
667151316Sdavidxu  }
66814331Speter  free(vm);
66983366Sjulian
67014331Speter  if (m_mem_region_cache.empty()) {
67114331Speter    // No entries after attempting to read them.  This shouldn't happen. Assume
67272543Sjlemon    // we don't support map entries.
67372543Sjlemon    LLDB_LOG(log, "failed to find any vmmap entries, assuming no support "
67414331Speter                  "for memory region metadata retrieval");
67514331Speter    m_supports_mem_region = LazyBool::eLazyBoolNo;
67669081Smarcel    Status error;
67714331Speter    error.SetErrorString("not supported");
67814331Speter    return error;
67914331Speter  }
680111797Sdes  LLDB_LOG(log, "read {0} memory region entries from process {1}",
68114331Speter           m_mem_region_cache.size(), GetID());
68214331Speter  // We support memory retrieval, remember that.
68314331Speter  m_supports_mem_region = LazyBool::eLazyBoolYes;
68414331Speter  return Status();
68514331Speter}
68614331Speter
68769081SmarcelStatus NativeProcessNetBSD::AllocateMemory(size_t size, uint32_t permissions,
688258685Semaste                                           lldb::addr_t &addr) {
689111798Sdes  return Status("Unimplemented");
69014331Speter}
69114331Speter
69214331SpeterStatus NativeProcessNetBSD::DeallocateMemory(lldb::addr_t addr) {
69314331Speter  return Status("Unimplemented");
69414331Speter}
69514331Speter
69628496Scharnierlldb::addr_t NativeProcessNetBSD::GetSharedLibraryInfoAddress() {
69769081Smarcel  // punt on this for now
698151316Sdavidxu  return LLDB_INVALID_ADDRESS;
699151316Sdavidxu}
700151316Sdavidxu
701151316Sdavidxusize_t NativeProcessNetBSD::UpdateThreads() { return m_threads.size(); }
702151316Sdavidxu
703151316SdavidxuStatus NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
70414331Speter                                          bool hardware) {
70514331Speter  if (hardware)
70614331Speter    return Status("NativeProcessNetBSD does not support hardware breakpoints");
70769081Smarcel  else
70869081Smarcel    return SetSoftwareBreakpoint(addr, size);
70969081Smarcel}
710198507Skib
711198507SkibStatus NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
71251793Smarcel                                                    FileSpec &file_spec) {
71314331Speter  return Status("Unimplemented");
71414331Speter}
71514331Speter
71646129SluoqiStatus NativeProcessNetBSD::GetFileLoadAddress(const llvm::StringRef &file_name,
71769081Smarcel                                               lldb::addr_t &load_addr) {
71869081Smarcel  load_addr = LLDB_INVALID_ADDRESS;
71969081Smarcel  return Status();
72069081Smarcel}
72169081Smarcel
72269081Smarcelvoid NativeProcessNetBSD::SigchldHandler() {
72369081Smarcel  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
72469081Smarcel  // Process all pending waitpid notifications.
72569081Smarcel  int status;
72669081Smarcel  ::pid_t wait_pid =
72769081Smarcel      llvm::sys::RetryAfterSignal(-1, waitpid, GetID(), &status, WALLSIG | WNOHANG);
72869081Smarcel
72925553Speter  if (wait_pid == 0)
73069081Smarcel    return; // We are done.
73169081Smarcel
73214331Speter  if (wait_pid == -1) {
73314331Speter    Status error(errno, eErrorTypePOSIX);
73414331Speter    LLDB_LOG(log, "waitpid ({0}, &status, _) failed: {1}", GetID(), error);
73514331Speter  }
73667234Sgallatin
73767234Sgallatin  WaitStatus wait_status = WaitStatus::Decode(status);
73867234Sgallatin  bool exited = wait_status.type == WaitStatus::Exit ||
73967234Sgallatin                (wait_status.type == WaitStatus::Signal &&
74067234Sgallatin                 wait_pid == static_cast<::pid_t>(GetID()));
74167234Sgallatin
74267234Sgallatin  LLDB_LOG(log,
74367234Sgallatin           "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
74467234Sgallatin           GetID(), wait_pid, status, exited);
74567234Sgallatin
74667234Sgallatin  if (exited)
747105441Smarkm    MonitorExited(wait_pid, wait_status);
74867234Sgallatin  else {
74983221Smarcel    assert(wait_status.type == WaitStatus::Stop);
75083221Smarcel    MonitorCallback(wait_pid, wait_status.status);
751198507Skib  }
75283221Smarcel}
753102814Siedowse
754111798Sdesbool NativeProcessNetBSD::HasThreadNoLock(lldb::tid_t thread_id) {
75567234Sgallatin  for (const auto &thread : m_threads) {
756151316Sdavidxu    assert(thread && "thread list should not contain NULL threads");
75767234Sgallatin    if (thread->GetID() == thread_id) {
75883366Sjulian      // We have this thread.
75967234Sgallatin      return true;
76067234Sgallatin    }
76172543Sjlemon  }
76272543Sjlemon
76367234Sgallatin  // We don't have this thread.
76467234Sgallatin  return false;
76569081Smarcel}
76667234Sgallatin
76767234SgallatinNativeThreadNetBSD &NativeProcessNetBSD::AddThread(lldb::tid_t thread_id) {
76867234Sgallatin  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
769111797Sdes  LLDB_LOG(log, "pid {0} adding thread with tid {1}", GetID(), thread_id);
77067234Sgallatin
77167234Sgallatin  assert(thread_id > 0);
77267234Sgallatin  assert(!HasThreadNoLock(thread_id) &&
77367234Sgallatin         "attempted to add a thread by id that already exists");
77467234Sgallatin
77567234Sgallatin  // If this is the first thread, save it as the current thread
77667234Sgallatin  if (m_threads.empty())
77767234Sgallatin    SetCurrentThreadID(thread_id);
77867234Sgallatin
779258685Semaste  m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*this, thread_id));
780111798Sdes  return static_cast<NativeThreadNetBSD &>(*m_threads.back());
78167234Sgallatin}
78267234Sgallatin
78367234Sgallatinvoid NativeProcessNetBSD::RemoveThread(lldb::tid_t thread_id) {
78467234Sgallatin  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_THREAD));
78567234Sgallatin  LLDB_LOG(log, "pid {0} removing thread with tid {1}", GetID(), thread_id);
78667234Sgallatin
78767234Sgallatin  assert(thread_id > 0);
78867234Sgallatin  assert(HasThreadNoLock(thread_id) &&
789151316Sdavidxu         "attempted to remove a thread that does not exist");
790151316Sdavidxu
791151316Sdavidxu  for (auto it = m_threads.begin(); it != m_threads.end(); ++it) {
792151316Sdavidxu    if ((*it)->GetID() == thread_id) {
793151316Sdavidxu      m_threads.erase(it);
794151316Sdavidxu      break;
79567234Sgallatin    }
79667234Sgallatin  }
79767234Sgallatin}
798198507Skib
799198507SkibStatus NativeProcessNetBSD::Attach() {
80067234Sgallatin  // Attach to the requested process.
80167234Sgallatin  // An attach will cause the thread to stop with a SIGSTOP.
80269081Smarcel  Status status = PtraceWrapper(PT_ATTACH, m_pid);
80367234Sgallatin  if (status.Fail())
80467234Sgallatin    return status;
80567234Sgallatin
80667234Sgallatin  int wstatus;
80767234Sgallatin  // Need to use WALLSIG otherwise we receive an error with errno=ECHLD At this
80867234Sgallatin  // point we should have a thread stopped if waitpid succeeds.
80967234Sgallatin  if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid,
81067234Sgallatin          m_pid, nullptr, WALLSIG)) < 0)
81167234Sgallatin    return Status(errno, eErrorTypePOSIX);
81267234Sgallatin
81367234Sgallatin  /* Initialize threads */
81467234Sgallatin  status = ReinitializeThreads();
81567234Sgallatin  if (status.Fail())
81667234Sgallatin    return status;
81767234Sgallatin
81867234Sgallatin  for (const auto &thread : m_threads)
81967234Sgallatin    static_cast<NativeThreadNetBSD &>(*thread).SetStoppedBySignal(SIGSTOP);
82067234Sgallatin
82167234Sgallatin  // Let our process instance know the thread has stopped.
82267234Sgallatin  SetState(StateType::eStateStopped);
82367234Sgallatin  return Status();
82467234Sgallatin}
825102814Siedowse
826102814SiedowseStatus NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
827102814Siedowse                                       size_t size, size_t &bytes_read) {
82867234Sgallatin  unsigned char *dst = static_cast<unsigned char *>(buf);
82967234Sgallatin  struct ptrace_io_desc io;
83072543Sjlemon
83172543Sjlemon  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
832102814Siedowse  LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
83367234Sgallatin
834102814Siedowse  bytes_read = 0;
83567234Sgallatin  io.piod_op = PIOD_READ_D;
83667234Sgallatin  io.piod_len = size;
83767234Sgallatin
83867234Sgallatin  do {
839208453Skib    io.piod_offs = (void *)(addr + bytes_read);
840208453Skib    io.piod_addr = dst + bytes_read;
84114331Speter
842208453Skib    Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
843208453Skib    if (error.Fail() || io.piod_len == 0)
844208453Skib      return error;
845208453Skib
846208453Skib    bytes_read += io.piod_len;
847208453Skib    io.piod_len = size - bytes_read;
848208453Skib  } while (bytes_read < size);
849208453Skib
850208453Skib  return Status();
851208453Skib}
852208453Skib
853208453SkibStatus NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
854208453Skib                                        size_t size, size_t &bytes_written) {
855208453Skib  const unsigned char *src = static_cast<const unsigned char *>(buf);
856208453Skib  Status error;
857208453Skib  struct ptrace_io_desc io;
858208453Skib
859208453Skib  Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY));
860208453Skib  LLDB_LOG(log, "addr = {0}, buf = {1}, size = {2}", addr, buf, size);
861208453Skib
862208453Skib  bytes_written = 0;
863208453Skib  io.piod_op = PIOD_WRITE_D;
864208453Skib  io.piod_len = size;
865208453Skib
86614331Speter  do {
86714331Speter    io.piod_addr = const_cast<void *>(static_cast<const void *>(src + bytes_written));
86859663Sdillon    io.piod_offs = (void *)(addr + bytes_written);
869111798Sdes
87059663Sdillon    Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
87159663Sdillon    if (error.Fail() || io.piod_len == 0)
87259663Sdillon      return error;
87359663Sdillon
87492765Salfred    bytes_written += io.piod_len;
87559663Sdillon    io.piod_len = size - bytes_written;
87659663Sdillon  } while (bytes_written < size);
877105441Smarkm
87859663Sdillon  return error;
87959663Sdillon}
880141469Sjhb
881210555Salcllvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
88259663SdillonNativeProcessNetBSD::GetAuxvData() const {
88359663Sdillon  /*
88459663Sdillon   * ELF_AUX_ENTRIES is currently restricted to kernel
88559663Sdillon   * (<sys/exec_elf.h> r. 1.155 specifies 15)
88659663Sdillon   *
88759663Sdillon   * ptrace(2) returns the whole AUXV including extra fiels after AT_NULL this
88859663Sdillon   * information isn't needed.
88959663Sdillon   */
89059663Sdillon  size_t auxv_size = 100 * sizeof(AuxInfo);
89159663Sdillon
89259663Sdillon  ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
89359663Sdillon      llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
89459663Sdillon
895141469Sjhb  struct ptrace_io_desc io;
896177997Skib  io.piod_op = PIOD_READ_AUXV;
897210555Salc  io.piod_offs = 0;
898210555Salc  io.piod_addr = static_cast<void *>(buf.get()->getBufferStart());
899210555Salc  io.piod_len = auxv_size;
90059663Sdillon
90159663Sdillon  Status error = NativeProcessNetBSD::PtraceWrapper(PT_IO, GetID(), &io);
902210555Salc
90359663Sdillon  if (error.Fail())
90459663Sdillon    return std::error_code(error.GetError(), std::generic_category());
905114915Smdodd
906114915Smdodd  if (io.piod_len < 1)
907114915Smdodd    return std::error_code(ECANCELED, std::generic_category());
908114915Smdodd
909114915Smdodd  return std::move(buf);
910114915Smdodd}
911205642Snwhitehorn
912114915SmdoddStatus NativeProcessNetBSD::ReinitializeThreads() {
913114915Smdodd  // Clear old threads
914114915Smdodd  m_threads.clear();
915205642Snwhitehorn
916114915Smdodd  // Initialize new thread
917114915Smdodd#ifdef PT_LWPSTATUS
918189423Sjhb  struct ptrace_lwpstatus info = {};
919189423Sjhb  int op = PT_LWPNEXT;
920141407Sdas#else
921189423Sjhb  struct ptrace_lwpinfo info = {};
922114915Smdodd  int op = PT_LWPINFO;
923114915Smdodd#endif
924189362Sdchagin
925189362Sdchagin  Status error = PtraceWrapper(op, GetID(), &info, sizeof(info));
926189362Sdchagin
927189362Sdchagin  if (error.Fail()) {
928189362Sdchagin    return error;
929189362Sdchagin  }
930189362Sdchagin  // Reinitialize from scratch threads and register them in process
931189362Sdchagin  while (info.pl_lwpid != 0) {
932189362Sdchagin    AddThread(info.pl_lwpid);
933189362Sdchagin    error = PtraceWrapper(op, GetID(), &info, sizeof(info));
934189362Sdchagin    if (error.Fail()) {
935189362Sdchagin      return error;
936189362Sdchagin    }
937189362Sdchagin  }
938189362Sdchagin
939189362Sdchagin  return error;
940189362Sdchagin}
941189362Sdchagin