13#include <sys/ptrace.h>
14#include <sys/sysctl.h>
17#include <machine/elf.h>
25#include "llvm/Support/Errno.h"
37 int status = fcntl(fd, F_GETFL);
43 if (fcntl(fd, F_SETFL, status | flags) == -1) {
53 size_t len =
sizeof(proc_debug);
54 ret = ::sysctlbyname(
"security.bsd.unprivileged_proc_debug", &proc_debug,
58 "sysctlbyname() security.bsd.unprivileged_proc_debug failed");
62 "process debug disabled by security.bsd.unprivileged_proc_debug oid");
69llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
80 LLDB_LOG(log,
"failed to launch process: {0}", status);
83 return error.ToError();
89 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
92 if (!WIFSTOPPED(wstatus)) {
93 LLDB_LOG(log,
"Could not sync with inferior process: wstatus={1}",
95 return llvm::createStringError(
"could not sync with inferior process");
97 LLDB_LOG(log,
"inferior started, now in stopped state");
101 return llvm::createStringError(
"cannot get process architecture");
105 LLDB_LOG(log,
"pid = {0:x}, detected architecture {1}", pid,
106 Info.GetArchitecture().GetArchitectureName());
112 status = process_up->SetupTrace();
116 for (
const auto &thread : process_up->m_threads)
120 return std::move(process_up);
123llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
132 return llvm::createStringError(
"cannot get process architecture");
136 pid, -1, native_delegate, Info.GetArchitecture(),
m_mainloop));
138 Status status = process_up->Attach();
142 return std::move(process_up);
148#if defined(PT_COREDUMP)
190 LLDB_LOG(log,
"got exit signal({0}) , pid = {1}", status, pid);
212 struct ptrace_lwpinfo info;
214 const auto siginfo_err =
PtraceWrapper(PT_LWPINFO, pid, &info,
sizeof(info));
215 if (siginfo_err.Fail()) {
216 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
219 assert(info.pl_event == PL_EVENT_SIGNAL);
221 LLDB_LOG(log,
"got SIGTRAP, pid = {0}, lwpid = {1}, flags = {2:x}", pid,
222 info.pl_lwpid, info.pl_flags);
225 if (info.pl_flags & (PL_FLAG_BORN | PL_FLAG_EXITED)) {
226 if (info.pl_flags & PL_FLAG_BORN) {
227 LLDB_LOG(log,
"monitoring new thread, tid = {0}", info.pl_lwpid);
243 "failed to copy watchpoints to new thread {1}: {0}",
249 LLDB_LOG(log,
"thread exited, tid = {0}", info.pl_lwpid);
254 PtraceWrapper(PT_CONTINUE, pid,
reinterpret_cast<void *
>(1), 0);
260 if (info.pl_flags & PL_FLAG_EXEC) {
277 if (info.pl_lwpid > 0) {
279 if (t->GetID() ==
static_cast<lldb::tid_t>(info.pl_lwpid))
284 LLDB_LOG(log,
"thread not found in m_threads, pid = {0}, LWP = {1}", pid,
288 if (info.pl_flags & PL_FLAG_FORKED) {
290 MonitorClone(info.pl_child_pid, info.pl_flags & PL_FLAG_VFORKED, *thread);
294 if (info.pl_flags & PL_FLAG_VFORK_DONE) {
297 thread->SetStoppedByVForkDone();
301 PtraceWrapper(PT_CONTINUE, pid,
reinterpret_cast<void *
>(1), 0);
308 if (info.pl_flags & PL_FLAG_SI) {
309 assert(info.pl_siginfo.si_signo ==
SIGTRAP);
310 LLDB_LOG(log,
"SIGTRAP siginfo: si_code = {0}, pid = {1}",
311 info.pl_siginfo.si_code, info.pl_siginfo.si_pid);
313 switch (info.pl_siginfo.si_code) {
315 LLDB_LOG(log,
"SIGTRAP/TRAP_BRKPT: si_addr: {0}",
316 info.pl_siginfo.si_addr);
319 thread->SetStoppedByBreakpoint();
326 LLDB_LOG(log,
"SIGTRAP/TRAP_TRACE: si_addr: {0}",
327 info.pl_siginfo.si_addr);
331 thread->GetRegisterContext());
334 wp_index,
reinterpret_cast<uintptr_t
>(info.pl_siginfo.si_addr));
337 "received error while checking for watchpoint hits, pid = "
338 "{0}, LWP = {1}, error = {2}",
339 pid, info.pl_lwpid,
error);
341 regctx.ClearWatchpointHit(wp_index);
342 thread->SetStoppedByWatchpoint(wp_index);
348 thread->SetStoppedByTrace();
359 LLDB_LOG(log,
"unknown SIGTRAP, passing to generic handler");
365 struct ptrace_lwpinfo info;
367 const auto siginfo_err =
PtraceWrapper(PT_LWPINFO, pid, &info,
sizeof(info));
368 if (siginfo_err.Fail()) {
369 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
372 assert(info.pl_event == PL_EVENT_SIGNAL);
374 assert(info.pl_flags & PL_FLAG_SI);
375 assert(info.pl_siginfo.si_signo == signal);
377 for (
const auto &abs_thread :
m_threads) {
380 assert(info.pl_lwpid >= 0);
381 if (info.pl_lwpid == 0 ||
382 static_cast<lldb::tid_t>(info.pl_lwpid) == thread.GetID()) {
383 thread.SetStoppedBySignal(info.pl_siginfo.si_signo, &info.pl_siginfo);
386 thread.SetStoppedWithNoReason();
392 int data,
int *result) {
399 ptrace(req,
static_cast<::
pid_t>(pid),
static_cast<caddr_t
>(addr), data);
410 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
418llvm::Expected<llvm::ArrayRef<uint8_t>>
420 static const uint8_t g_arm_opcode[] = {0xfe, 0xde, 0xff, 0xe7};
421 static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
424 case llvm::Triple::arm:
427 return llvm::ArrayRef(g_thumb_opcode);
429 return llvm::ArrayRef(g_arm_opcode);
431 return llvm::createStringError(llvm::inconvertibleErrorCode(),
432 "Unrecognised trap opcode size hint!");
446 for (
const auto &abs_thread :
m_threads) {
447 assert(abs_thread &&
"thread list should not contain NULL threads");
458 if (action ==
nullptr) {
459 LLDB_LOG(log,
"no action specified for pid {0} tid {1}",
GetID(),
461 action = &suspend_action;
466 "processing resume action state {0} signal {1} for pid {2} tid {3}",
469 switch (action->
state) {
471 ret = thread.Resume();
474 ret = thread.SingleStep();
480 "Passing signal to suspended thread unsupported");
482 ret = thread.Suspend();
487 "NativeProcessFreeBSD::%s (): unexpected state %s specified "
488 "for pid %" PRIu64
", tid %" PRIu64,
533 if (kill(
GetID(), signo))
554 LLDB_LOG(log,
"ignored for PID {0} due to current state: {1}",
GetID(),
594 "descending memory map entries detected, unexpected");
610 range_info = proc_entry_info;
633 LLDB_LOG(log,
"reusing {0} cached memory region entries",
638 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP,
static_cast<int>(
m_pid)};
642 ret = ::sysctl(mib, 4,
nullptr, &len,
nullptr, 0);
648 std::unique_ptr<WritableMemoryBuffer> buf =
649 llvm::WritableMemoryBuffer::getNewMemBuffer(len);
650 ret = ::sysctl(mib, 4, buf->getBufferStart(), &len,
nullptr, 0);
656 char *bp = buf->getBufferStart();
657 char *end = bp + len;
659 auto *kv =
reinterpret_cast<struct kinfo_vmentry *
>(bp);
660 if (kv->kve_structsize == 0)
662 bp += kv->kve_structsize;
670 if (kv->kve_protection & VM_PROT_READ)
675 if (kv->kve_protection & VM_PROT_WRITE)
680 if (kv->kve_protection & VM_PROT_EXECUTE)
695 LLDB_LOG(log,
"failed to find any vmmap entries, assuming no support "
696 "for memory region metadata retrieval");
700 LLDB_LOG(log,
"read {0} memory region entries from process {1}",
727 FileSpec module_file_spec(module_path);
732 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
733 file_spec = it.second;
738 "Module file ({0}) not found in process' memory map!",
756 if (it.second == file) {
757 load_addr = it.first.GetRange().GetRangeBase();
762 file_name.str().c_str());
769 llvm::sys::RetryAfterSignal(-1, waitpid,
GetID(), &status, WNOHANG);
774 if (wait_pid == -1) {
786 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
787 GetID(), wait_pid, status, exited);
799 assert(thread &&
"thread list should not contain NULL threads");
800 if (thread->GetID() == thread_id) {
812 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
814 assert(thread_id > 0);
816 "attempted to add a thread by id that already exists");
822 m_threads.push_back(std::make_unique<NativeThreadFreeBSD>(*
this, thread_id));
828 LLDB_LOG(log,
"pid {0} removing thread with tid {1}",
GetID(), thread_id);
830 assert(thread_id > 0);
832 "attempted to remove a thread that does not exist");
835 if ((*it)->GetID() == thread_id) {
855 if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid,
m_pid,
nullptr, 0)) <
875 size_t size,
size_t &bytes_read) {
876 unsigned char *dst =
static_cast<unsigned char *
>(buf);
877 struct ptrace_io_desc io;
880 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
883 io.piod_op = PIOD_READ_D;
887 io.piod_offs = (
void *)(addr + bytes_read);
888 io.piod_addr = dst + bytes_read;
891 if (
error.Fail() || io.piod_len == 0)
894 bytes_read += io.piod_len;
895 io.piod_len = size - bytes_read;
896 }
while (bytes_read < size);
902 size_t size,
size_t &bytes_written) {
903 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
905 struct ptrace_io_desc io;
908 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
911 io.piod_op = PIOD_WRITE_D;
916 const_cast<void *
>(
static_cast<const void *
>(src + bytes_written));
917 io.piod_offs = (
void *)(addr + bytes_written);
920 if (
error.Fail() || io.piod_len == 0)
923 bytes_written += io.piod_len;
924 io.piod_len = size - bytes_written;
925 }
while (bytes_written < size);
930llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
932 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV,
static_cast<int>(
GetID())};
933 size_t auxv_size = AT_COUNT *
sizeof(Elf_Auxinfo);
934 std::unique_ptr<WritableMemoryBuffer> buf =
935 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
937 if (::sysctl(mib, 4, buf->getBufferStart(), &auxv_size,
nullptr, 0) != 0)
938 return std::error_code(errno, std::generic_category());
950 events |= PTRACE_LWP | PTRACE_FORK | PTRACE_VFORK;
967 std::vector<lwpid_t> lwp_ids;
968 lwp_ids.resize(num_lwps);
970 lwp_ids.size() *
sizeof(lwpid_t), &num_lwps);
975 for (lwpid_t lwp : lwp_ids)
984 LLDB_LOG(log,
"fork, child_pid={0}", child_pid);
988 llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
989 if (wait_pid != child_pid) {
991 "waiting for pid {0} failed. Assuming the pid has "
992 "disappeared in the meantime",
996 if (WIFEXITED(status)) {
998 "waiting for pid {0} returned an 'exited' event. Not "
1004 struct ptrace_lwpinfo info;
1005 const auto siginfo_err =
1007 if (siginfo_err.Fail()) {
1008 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
1011 assert(info.pl_event == PL_EVENT_SIGNAL);
1014 std::unique_ptr<NativeProcessFreeBSD> child_process{
1022 child_process->SetupTrace();
1023 for (
const auto &thread : child_process->m_threads)
1027 m_delegate.NewSubprocess(
this, std::move(child_process));
1034 child_process->Detach();
1037 if (pt_error.
Fail()) {
1039 "unable to resume parent process {1}: {0}",
GetID());
1045llvm::Expected<std::string>
1047#if defined(PT_COREDUMP)
1048 using namespace llvm::sys::fs;
1050 llvm::SmallString<128> path{path_hint};
1052 struct ptrace_coredump
pc = {};
1057 openFile(path,
pc.pc_fd, CD_CreateNew, FA_Write, OF_None)) {
1058 if (std::error_code errc =
1059 createTemporaryFile(
"lldb",
"core",
pc.pc_fd, path))
1060 return llvm::createStringError(errc,
"unable to create a temporary file");
1064 std::error_code close_err = closeFile(
pc.pc_fd);
1066 return error.ToError();
1068 return llvm::createStringError(
1069 close_err,
"Unable to close the core dump after writing");
1070 return path.str().str();
1072 return llvm::createStringError(
1073 llvm::inconvertibleErrorCode(),
1074 "PT_COREDUMP not supported in the FreeBSD version used to build LLDB");
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)
An architecture specification class.
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.
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
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 SetReadable(LazyBool val)
ConstString GetName() const
void SetName(const char *name)
void SetMapped(LazyBool val)
void SetExecutable(LazyBool val)
void SetWritable(LazyBool val)
Abstract class that extends NativeProcessProtocol with ELF specific logic.
std::vector< std::pair< MemoryRegionInfo, FileSpec > > m_mem_region_cache
void NotifyDidExec() override
Notify the delegate that an exec occurred.
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)
lldb::tid_t GetCurrentThreadID() const
Extension
Extension flag constants, returned by Manager::GetSupportedExtensions() and passed to SetEnabledExten...
virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size)
virtual llvm::Expected< llvm::ArrayRef< uint8_t > > GetSoftwareBreakpointTrapOpcode(size_t size_hint)
Extension m_enabled_extensions
std::unordered_map< lldb::addr_t, SoftwareBreakpoint > m_software_breakpoints
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
static Status FromErrno()
Set the current error to errno.
llvm::Error ToError() const
FIXME: Replace all uses with takeError() instead.
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
bool Fail() const
Test for error condition.
static Status static Status FromErrorStringWithFormatv(const char *format, Args &&...args)
bool Success() const
Test for success condition.
llvm::Expected< std::unique_ptr< NativeProcessProtocol > > Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate) override
Launch a process for debugging.
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.
NativeThreadFreeBSD & AddThread(lldb::tid_t thread_id)
void MonitorCallback(lldb::pid_t pid, int signal)
void RemoveThread(lldb::tid_t thread_id)
void MonitorSIGSTOP(lldb::pid_t pid)
Status GetMemoryRegionInfo(lldb::addr_t load_addr, MemoryRegionInfo &range_info) override
void MonitorSignal(lldb::pid_t pid, int signal)
void MonitorSIGTRAP(lldb::pid_t pid)
MainLoop::SignalHandleUP m_sigchld_handle
Status Resume(const ResumeActionList &resume_actions) override
Status PopulateMemoryRegionCache()
llvm::Expected< std::string > SaveCore(llvm::StringRef path_hint) override
Write a core dump (without crashing the program).
Status GetFileLoadAddress(const llvm::StringRef &file_name, lldb::addr_t &load_addr) override
size_t UpdateThreads() override
LazyBool m_supports_mem_region
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > GetAuxvData() const override
const ArchSpec & GetArchitecture() const override
void MonitorClone(::pid_t child_pid, bool is_vfork, NativeThreadFreeBSD &parent_thread)
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr=nullptr, int data=0, int *result=nullptr)
Status Interrupt() override
Tells a process to interrupt all operations as if by a Ctrl-C.
Status ReinitializeThreads()
Status Signal(int signo) override
Sends a process a UNIX signal signal.
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, size_t &bytes_read) override
Status GetLoadedModuleFileSpec(const char *module_path, FileSpec &file_spec) override
llvm::Expected< llvm::ArrayRef< uint8_t > > GetSoftwareBreakpointTrapOpcode(size_t size_hint) override
void MonitorExited(lldb::pid_t pid, WaitStatus status)
NativeProcessFreeBSD(::pid_t pid, int terminal_fd, NativeDelegate &delegate, const ArchSpec &arch, MainLoop &mainloop)
bool HasThreadNoLock(lldb::tid_t thread_id)
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override
Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override
llvm::Error CopyWatchpointsFrom(NativeThreadFreeBSD &source)
void SetStoppedWithNoReason()
void SetStoppedByVFork(lldb::pid_t child_pid, lldb::tid_t child_tid)
void SetStoppedByFork(lldb::pid_t child_pid, lldb::tid_t child_tid)
void SetStoppedBySignal(uint32_t signo, const siginfo_t *info=nullptr)
#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.
bool StateIsStoppedState(lldb::StateType state, bool must_exist)
Check if a state represents a state where the process or thread is stopped.
const char * StateAsCString(lldb::StateType state)
Converts a StateType to a C string.
@ eStateUnloaded
Process is object is valid, but not currently loaded.
@ eStateConnected
Process is connected to remote debug services, but not launched or attached to anything yet.
@ eStateDetached
Process has been detached and can't be examined.
@ 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.
@ eStateLaunching
Process is in the process of launching.
@ eStateAttaching
Process is currently trying to attach.
@ eStateExited
Process has exited and can't be examined.
@ eStateStepping
Process or thread is in the process of stepping and can not be examined.
@ eStateCrashed
Process or thread has crashed and can 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)