18#include "llvm/Support/Errno.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();
58llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
69 LLDB_LOG(log,
"failed to launch process: {0}", status);
75 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
78 if (!WIFSTOPPED(wstatus)) {
79 LLDB_LOG(log,
"Could not sync with inferior process: wstatus={1}",
81 return llvm::make_error<StringError>(
"Could not sync with inferior process",
82 llvm::inconvertibleErrorCode());
84 LLDB_LOG(log,
"inferior started, now in stopped state");
88 return llvm::make_error<StringError>(
"Cannot get process architecture",
89 llvm::inconvertibleErrorCode());
93 LLDB_LOG(log,
"pid = {0:x}, detected architecture {1}", pid,
94 Info.GetArchitecture().GetArchitectureName());
100 status = process_up->SetupTrace();
104 for (
const auto &thread : process_up->m_threads)
106 process_up->SetState(StateType::eStateStopped,
false);
108 return std::move(process_up);
111llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
120 return llvm::make_error<StringError>(
"Cannot get process architecture",
121 llvm::inconvertibleErrorCode());
125 pid, -1, native_delegate, Info.GetArchitecture(), m_mainloop));
127 Status status = process_up->Attach();
131 return std::move(process_up);
175 LLDB_LOG(log,
"got exit signal({0}) , pid = {1}", status, pid);
183 SetState(StateType::eStateExited,
true);
187 ptrace_siginfo_t info;
189 const auto siginfo_err =
193 if (siginfo_err.Success()) {
195 if (info.psi_siginfo.si_code == SI_USER &&
196 info.psi_siginfo.si_pid == ::getpid()) {
203 SetState(StateType::eStateStopped,
true);
209 ptrace_siginfo_t info;
211 const auto siginfo_err =
215 if (siginfo_err.Fail()) {
216 LLDB_LOG(log,
"PT_GET_SIGINFO failed {0}", siginfo_err);
220 LLDB_LOG(log,
"got SIGTRAP, pid = {0}, lwpid = {1}, si_code = {2}", pid,
221 info.psi_lwpid, info.psi_siginfo.si_code);
224 if (info.psi_lwpid > 0) {
226 if (t->GetID() ==
static_cast<lldb::tid_t>(info.psi_lwpid)) {
233 LLDB_LOG(log,
"thread not found in m_threads, pid = {0}, LWP = {1}", pid,
237 switch (info.psi_siginfo.si_code) {
243 SetState(StateType::eStateStopped,
true);
248 SetState(StateType::eStateStopped,
true);
262 SetState(StateType::eStateStopped,
true);
274 if (pst.pe_report_event == PTRACE_VFORK_DONE) {
277 SetState(StateType::eStateStopped,
true);
280 PtraceWrapper(PT_CONTINUE, pid,
reinterpret_cast<void *
>(1), 0);
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,
300 switch (pst.pe_report_event) {
301 case PTRACE_LWP_CREATE: {
302 LLDB_LOG(log,
"monitoring new thread, pid = {0}, LWP = {1}", pid,
308 LLDB_LOG(log,
"failed to copy watchpoints to new thread {0}: {1}",
314 case PTRACE_LWP_EXIT:
315 LLDB_LOG(log,
"removing exited thread, pid = {0}, LWP = {1}", pid,
334 wp_index, (uintptr_t)info.psi_siginfo.si_addr);
337 "received error while checking for watchpoint hits, pid = "
338 "{0}, LWP = {1}, error = {2}",
339 pid, info.psi_lwpid,
error);
342 regctx.ClearWatchpointHit(wp_index);
343 SetState(StateType::eStateStopped,
true);
348 SetState(StateType::eStateStopped,
true);
355 LLDB_LOG(log,
"unknown SIGTRAP, passing to generic handler");
361 ptrace_siginfo_t info;
363 const auto siginfo_err =
365 if (siginfo_err.Fail()) {
366 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
370 for (
const auto &abs_thread :
m_threads) {
372 assert(info.psi_lwpid >= 0);
373 if (info.psi_lwpid == 0 ||
379 SetState(StateType::eStateStopped,
true);
394 error.SetErrorToErrno();
396 LLDB_LOG(log,
"kill({0}, SIGSTOP)", pid);
406 int data,
int *result) {
412 ret = ptrace(req,
static_cast<::
pid_t>(pid), addr, data);
415 error.SetErrorToErrno();
420 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
429 const std::vector<std::unique_ptr<NativeThreadProtocol>> &threads,
438 size_t signaled_threads = 0;
441 for (
const auto &thread : threads) {
442 assert(thread &&
"thread list should not contain NULL threads");
448 if (action->
signal != signal) {
450 return Status(
"NetBSD does not support passing multiple signals "
454 signaled_lwp = thread->GetID();
460 if (signaled_threads == 0) {
461 ptrace_siginfo_t siginfo;
466 if (signaled_threads > 1 && signaled_threads < threads.size())
467 return Status(
"NetBSD does not support passing signal to 1<i<all threads")
470 ptrace_siginfo_t siginfo;
471 siginfo.psi_siginfo.si_signo = signal;
472 siginfo.psi_siginfo.si_code = SI_USER;
473 siginfo.psi_siginfo.si_pid = getpid();
474 siginfo.psi_siginfo.si_uid = getuid();
475 if (signaled_threads == 1)
476 siginfo.psi_lwpid = signaled_lwp;
478 siginfo.psi_lwpid = 0;
488 Expected<ptrace_siginfo_t> siginfo =
491 return Status(siginfo.takeError());
493 for (
const auto &abs_thread :
m_threads) {
494 assert(abs_thread &&
"thread list should not contain NULL threads");
504 if (action ==
nullptr) {
505 LLDB_LOG(log,
"no action specified for pid {0} tid {1}",
GetID(),
507 action = &suspend_action;
512 "processing resume action state {0} signal {1} for pid {2} tid {3}",
515 switch (action->
state) {
525 return Status(
"Passing signal to suspended thread unsupported");
531 return Status(
"NativeProcessNetBSD::%s (): unexpected state %s specified "
532 "for pid %" PRIu64
", tid %" PRIu64,
547 signal = siginfo->psi_siginfo.si_signo;
575 if (kill(
GetID(), signo))
576 error.SetErrorToErrno();
590 case StateType::eStateInvalid:
591 case StateType::eStateExited:
592 case StateType::eStateCrashed:
593 case StateType::eStateDetached:
594 case StateType::eStateUnloaded:
596 LLDB_LOG(log,
"ignored for PID {0} due to current state: {1}",
GetID(),
600 case StateType::eStateConnected:
601 case StateType::eStateAttaching:
602 case StateType::eStateLaunching:
603 case StateType::eStateStopped:
604 case StateType::eStateRunning:
605 case StateType::eStateStepping:
606 case StateType::eStateSuspended:
612 error.SetErrorToErrno();
624 return Status(
"unsupported");
641 "descending memory map entries detected, unexpected");
657 range_info = proc_entry_info;
680 LLDB_LOG(log,
"reusing {0} cached memory region entries",
685 struct kinfo_vmentry *vm;
687 vm = kinfo_getvmmap(
GetID(), &count);
691 error.SetErrorString(
"not supported");
694 for (i = 0; i < count; i++) {
701 if (vm[i].kve_protection & VM_PROT_READ)
706 if (vm[i].kve_protection & VM_PROT_WRITE)
711 if (vm[i].kve_protection & VM_PROT_EXECUTE)
716 if (vm[i].kve_path[0])
727 LLDB_LOG(log,
"failed to find any vmmap entries, assuming no support "
728 "for memory region metadata retrieval");
731 error.SetErrorString(
"not supported");
734 LLDB_LOG(log,
"read {0} memory region entries from process {1}",
751 return Status(
"NativeProcessNetBSD does not support hardware breakpoints");
762 FileSpec module_file_spec(module_path);
767 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
768 file_spec = it.second;
772 return Status(
"Module file (%s) not found in process' memory map!",
785 if (it.second == file) {
786 load_addr = it.first.GetRange().GetRangeBase();
790 return Status(
"No load address found for file %s.", file_name.str().c_str());
796 ::pid_t wait_pid = llvm::sys::RetryAfterSignal(-1, waitpid,
GetID(), &status,
802 if (wait_pid == -1) {
814 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
815 GetID(), wait_pid, status, exited);
827 assert(thread &&
"thread list should not contain NULL threads");
828 if (thread->GetID() == thread_id) {
840 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
842 assert(thread_id > 0);
844 "attempted to add a thread by id that already exists");
850 m_threads.push_back(std::make_unique<NativeThreadNetBSD>(*
this, thread_id));
856 LLDB_LOG(log,
"pid {0} removing thread with tid {1}",
GetID(), thread_id);
858 assert(thread_id > 0);
860 "attempted to remove a thread that does not exist");
863 if ((*it)->GetID() == thread_id) {
880 if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid,
m_pid,
nullptr,
895 SetState(StateType::eStateStopped,
false);
900 size_t size,
size_t &bytes_read) {
901 unsigned char *dst =
static_cast<unsigned char *
>(buf);
902 struct ptrace_io_desc io;
905 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
908 io.piod_op = PIOD_READ_D;
912 io.piod_offs = (
void *)(addr + bytes_read);
913 io.piod_addr = dst + bytes_read;
916 if (
error.Fail() || io.piod_len == 0)
919 bytes_read += io.piod_len;
920 io.piod_len = size - bytes_read;
921 }
while (bytes_read < size);
927 size_t size,
size_t &bytes_written) {
928 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
930 struct ptrace_io_desc io;
933 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
936 io.piod_op = PIOD_WRITE_D;
941 const_cast<void *
>(
static_cast<const void *
>(src + bytes_written));
942 io.piod_offs = (
void *)(addr + bytes_written);
945 if (
error.Fail() || io.piod_len == 0)
948 bytes_written += io.piod_len;
949 io.piod_len = size - bytes_written;
950 }
while (bytes_written < size);
955llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
964 size_t auxv_size = 100 *
sizeof(AuxInfo);
966 ErrorOr<std::unique_ptr<WritableMemoryBuffer>> buf =
967 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
969 struct ptrace_io_desc io;
970 io.piod_op = PIOD_READ_AUXV;
972 io.piod_addr =
static_cast<void *
>(buf.get()->getBufferStart());
973 io.piod_len = auxv_size;
978 return std::error_code(
error.GetError(), std::generic_category());
981 return std::error_code(ECANCELED, std::generic_category());
983 return std::move(buf);
988 ptrace_event_t events;
994 events.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT | PTRACE_FORK |
995 PTRACE_VFORK | PTRACE_VFORK_DONE;
1009 struct ptrace_lwpstatus info = {};
1010 int op = PT_LWPNEXT;
1012 struct ptrace_lwpinfo info = {};
1013 int op = PT_LWPINFO;
1022 while (info.pl_lwpid != 0) {
1036 LLDB_LOG(log,
"clone, child_pid={0}", child_pid);
1040 llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
1041 if (wait_pid != child_pid) {
1043 "waiting for pid {0} failed. Assuming the pid has "
1044 "disappeared in the meantime",
1048 if (WIFEXITED(status)) {
1050 "waiting for pid {0} returned an 'exited' event. Not "
1056 ptrace_siginfo_t info;
1057 const auto siginfo_err =
1058 PtraceWrapper(PT_GET_SIGINFO, child_pid, &info,
sizeof(info));
1059 if (siginfo_err.Fail()) {
1060 LLDB_LOG(log,
"PT_GET_SIGINFO failed {0}", siginfo_err);
1063 assert(info.psi_lwpid >= 0);
1066 std::unique_ptr<NativeProcessNetBSD> child_process{
1074 child_process->SetupTrace();
1075 for (
const auto &thread : child_process->m_threads)
1077 child_process->SetState(StateType::eStateStopped,
false);
1084 SetState(StateType::eStateStopped,
true);
1086 child_process->Detach();
1089 if (pt_error.
Fail()) {
1091 "unable to resume parent process {1}: {0}",
GetID());
1092 SetState(StateType::eStateInvalid);
1097llvm::Expected<std::string>
1099 llvm::SmallString<128> path{path_hint};
1103 if (!path.empty()) {
1106 return path.str().str();
1111 if (std::error_code errc =
1112 llvm::sys::fs::createTemporaryFile(
"lldb",
"core", path))
1113 return llvm::createStringError(errc,
"Unable to create a temporary file");
1117 return error.ToError();
1118 return path.str().str();
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOG_ERROR(log, error,...)
static Status EnsureFDFlags(int fd, int flags)
static Status EnsureFDFlags(int fd, int flags)
static llvm::Expected< ptrace_siginfo_t > ComputeSignalInfo(const std::vector< std::unique_ptr< NativeThreadProtocol > > &threads, const ResumeActionList &resume_actions)
An architecture specification class.
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
const char * GetCString() const
Get the string value as a C string.
const ConstString & GetFilename() const
Filename string const get accessor.
void Clear()
Clears the object state.
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
static FileSystem & Instance()
lldb::pid_t GetProcessId() const
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
SignalHandleUP RegisterSignal(int signo, const Callback &callback, Status &error)
void SetMapped(OptionalBool val)
ConstString GetName() const
void SetReadable(OptionalBool val)
void SetExecutable(OptionalBool val)
void SetName(const char *name)
void SetWritable(OptionalBool val)
Abstract class that extends NativeProcessProtocol with ELF specific logic.
void NotifyDidExec() override
Notify the delegate that an exec occurred.
virtual void NewSubprocess(NativeProcessProtocol *parent_process, std::unique_ptr< NativeProcessProtocol > child_process)=0
lldb::pid_t GetID() const
Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint)
void SetState(lldb::StateType state, bool notify_delegates=true)
NativeThreadProtocol * GetCurrentThread()
void SetCurrentThreadID(lldb::tid_t tid)
std::vector< std::unique_ptr< NativeThreadProtocol > > m_threads
virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange)
NativeDelegate & m_delegate
void FixupBreakpointPCAsNeeded(NativeThreadProtocol &thread)
Extension
Extension flag constants, returned by Manager::GetSupportedExtensions() and passed to SetEnabledExten...
Extension m_enabled_extensions
std::unordered_map< lldb::addr_t, SoftwareBreakpoint > m_software_breakpoints
lldb::tid_t GetID() const
PseudoTerminal & GetPTY()
HostProcess LaunchProcess(const ProcessLaunchInfo &launch_info, Status &error) override
int ReleasePrimaryFileDescriptor()
Release the primary file descriptor.
const ResumeAction * GetActionForThread(lldb::tid_t tid, bool default_ok) const
llvm::Error ToError() const
bool Fail() const
Test for error condition.
bool Success() const
Test for success condition.
llvm::Expected< std::unique_ptr< NativeProcessProtocol > > Attach(lldb::pid_t pid, NativeDelegate &native_delegate) override
Attach to an existing process.
Extension GetSupportedExtensions() const override
Get the bitmask of extensions supported by this process plugin.
llvm::Expected< std::unique_ptr< NativeProcessProtocol > > Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate) override
Launch a process for debugging.
Manages communication with the inferior (debugee) process.
llvm::Expected< std::string > SaveCore(llvm::StringRef path_hint) override
Write a core dump (without crashing the program).
lldb::addr_t GetSharedLibraryInfoAddress() override
void MonitorClone(::pid_t child_pid, bool is_vfork, NativeThreadNetBSD &parent_thread)
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override
Status Interrupt() override
Tells a process to interrupt all operations as if by a Ctrl-C.
Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override
Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) override
MainLoop::SignalHandleUP m_sigchld_handle
Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > GetAuxvData() const override
bool HasThreadNoLock(lldb::tid_t thread_id)
void MonitorSIGTRAP(lldb::pid_t pid)
Status ReinitializeThreads()
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override
Status PopulateMemoryRegionCache()
std::vector< std::pair< MemoryRegionInfo, FileSpec > > m_mem_region_cache
Status Resume(const ResumeActionList &resume_actions) override
NativeProcessNetBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, const ArchSpec &arch, MainLoop &mainloop)
size_t UpdateThreads() override
void MonitorExited(lldb::pid_t pid, WaitStatus status)
void MonitorCallback(lldb::pid_t pid, int signal)
NativeThreadNetBSD & AddThread(lldb::tid_t thread_id)
Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override
LazyBool m_supports_mem_region
void MonitorSIGSTOP(lldb::pid_t pid)
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, int data=0, int *result=nullptr)
void RemoveThread(lldb::tid_t thread_id)
Status Signal(int signo) override
Sends a process a UNIX signal signal.
static Status StopProcess(lldb::pid_t pid)
void MonitorSignal(lldb::pid_t pid, int signal)
void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid)
void SetStoppedBySignal(uint32_t signo, const siginfo_t *info=nullptr)
void SetStoppedWithNoReason()
NativeRegisterContextNetBSD & GetRegisterContext() override
void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid)
void SetStoppedByVForkDone()
void SetStoppedByBreakpoint()
llvm::Error CopyWatchpointsFrom(NativeThreadNetBSD &source)
void SetStoppedByWatchpoint(uint32_t wp_index)
#define LLDB_INVALID_SIGNAL_NUMBER
#define LLDB_INVALID_INDEX32
#define UNUSED_IF_ASSERT_DISABLED(x)
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_PROCESS_ID
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
const char * StateAsCString(lldb::StateType state)
Converts a StateType to a C string.
@ eStateStopped
Process or thread is stopped and can be examined.
@ eStateSuspended
Process or thread is in a suspended state as far as the debugger is concerned while other processes o...
@ eStateRunning
Process or thread is running and can't be examined.
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
@ eErrorTypePOSIX
POSIX error codes.
bool Contains(BaseType r) const
BaseType GetRangeBase() const
void SetRangeEnd(BaseType end)
void SetRangeBase(BaseType b)
Set the start value for the range, and keep the same size.
void SetByteSize(SizeType s)
static WaitStatus Decode(int wstatus)