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);
39 error.SetErrorToErrno();
43 if (fcntl(fd, F_SETFL, status | flags) == -1) {
44 error.SetErrorToErrno();
53llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
64 LLDB_LOG(log,
"failed to launch process: {0}", status);
70 ::pid_t wpid = llvm::sys::RetryAfterSignal(-1, ::waitpid, pid, &wstatus, 0);
73 if (!WIFSTOPPED(wstatus)) {
74 LLDB_LOG(log,
"Could not sync with inferior process: wstatus={1}",
76 return llvm::make_error<StringError>(
"Could not sync with inferior process",
77 llvm::inconvertibleErrorCode());
79 LLDB_LOG(log,
"inferior started, now in stopped state");
83 return llvm::make_error<StringError>(
"Cannot get process architecture",
84 llvm::inconvertibleErrorCode());
88 LLDB_LOG(log,
"pid = {0:x}, detected architecture {1}", pid,
89 Info.GetArchitecture().GetArchitectureName());
95 status = process_up->SetupTrace();
99 for (
const auto &thread : process_up->m_threads)
101 process_up->SetState(StateType::eStateStopped,
false);
103 return std::move(process_up);
106llvm::Expected<std::unique_ptr<NativeProcessProtocol>>
115 return llvm::make_error<StringError>(
"Cannot get process architecture",
116 llvm::inconvertibleErrorCode());
120 pid, -1, native_delegate, Info.GetArchitecture(), m_mainloop));
122 Status status = process_up->Attach();
126 return std::move(process_up);
132#if defined(PT_COREDUMP)
174 LLDB_LOG(log,
"got exit signal({0}) , pid = {1}", status, pid);
182 SetState(StateType::eStateExited,
true);
191 SetState(StateType::eStateStopped,
true);
196 struct ptrace_lwpinfo info;
198 const auto siginfo_err =
PtraceWrapper(PT_LWPINFO, pid, &info,
sizeof(info));
199 if (siginfo_err.Fail()) {
200 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
203 assert(info.pl_event == PL_EVENT_SIGNAL);
205 LLDB_LOG(log,
"got SIGTRAP, pid = {0}, lwpid = {1}, flags = {2:x}", pid,
206 info.pl_lwpid, info.pl_flags);
209 if (info.pl_flags & (PL_FLAG_BORN | PL_FLAG_EXITED)) {
210 if (info.pl_flags & PL_FLAG_BORN) {
211 LLDB_LOG(log,
"monitoring new thread, tid = {0}", info.pl_lwpid);
227 "failed to copy watchpoints to new thread {1}: {0}",
233 LLDB_LOG(log,
"thread exited, tid = {0}", info.pl_lwpid);
238 PtraceWrapper(PT_CONTINUE, pid,
reinterpret_cast<void *
>(1), 0);
244 if (info.pl_flags & PL_FLAG_EXEC) {
257 SetState(StateType::eStateStopped,
true);
261 if (info.pl_lwpid > 0) {
263 if (t->GetID() ==
static_cast<lldb::tid_t>(info.pl_lwpid))
268 LLDB_LOG(log,
"thread not found in m_threads, pid = {0}, LWP = {1}", pid,
272 if (info.pl_flags & PL_FLAG_FORKED) {
274 MonitorClone(info.pl_child_pid, info.pl_flags & PL_FLAG_VFORKED, *thread);
278 if (info.pl_flags & PL_FLAG_VFORK_DONE) {
282 SetState(StateType::eStateStopped,
true);
285 PtraceWrapper(PT_CONTINUE, pid,
reinterpret_cast<void *
>(1), 0);
292 if (info.pl_flags & PL_FLAG_SI) {
293 assert(info.pl_siginfo.si_signo ==
SIGTRAP);
294 LLDB_LOG(log,
"SIGTRAP siginfo: si_code = {0}, pid = {1}",
295 info.pl_siginfo.si_code, info.pl_siginfo.si_pid);
297 switch (info.pl_siginfo.si_code) {
299 LLDB_LOG(log,
"SIGTRAP/TRAP_BRKPT: si_addr: {0}",
300 info.pl_siginfo.si_addr);
308 if (brkpt_error.
Fail())
309 LLDB_LOG(log,
"pid = {0} remove stepping breakpoint: {1}",
310 thread_info->first, brkpt_error);
317 SetState(StateType::eStateStopped,
true);
320 LLDB_LOG(log,
"SIGTRAP/TRAP_TRACE: si_addr: {0}",
321 info.pl_siginfo.si_addr);
328 wp_index,
reinterpret_cast<uintptr_t
>(info.pl_siginfo.si_addr));
331 "received error while checking for watchpoint hits, pid = "
332 "{0}, LWP = {1}, error = {2}",
333 pid, info.pl_lwpid,
error);
335 regctx.ClearWatchpointHit(wp_index);
338 SetState(StateType::eStateStopped,
true);
346 SetState(StateType::eStateStopped,
true);
353 LLDB_LOG(log,
"unknown SIGTRAP, passing to generic handler");
359 struct ptrace_lwpinfo info;
361 const auto siginfo_err =
PtraceWrapper(PT_LWPINFO, pid, &info,
sizeof(info));
362 if (siginfo_err.Fail()) {
363 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
366 assert(info.pl_event == PL_EVENT_SIGNAL);
368 assert(info.pl_flags & PL_FLAG_SI);
369 assert(info.pl_siginfo.si_signo == signal);
371 for (
const auto &abs_thread :
m_threads) {
374 assert(info.pl_lwpid >= 0);
375 if (info.pl_lwpid == 0 ||
382 SetState(StateType::eStateStopped,
true);
386 int data,
int *result) {
393 ptrace(req,
static_cast<::
pid_t>(pid),
static_cast<caddr_t
>(addr), data);
396 error.SetErrorToErrno();
401 LLDB_LOG(log,
"ptrace({0}, {1}, {2}, {3})={4:x}", req, pid, addr, data, ret);
409llvm::Expected<llvm::ArrayRef<uint8_t>>
411 static const uint8_t g_arm_opcode[] = {0xfe, 0xde, 0xff, 0xe7};
412 static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
415 case llvm::Triple::arm:
418 return llvm::ArrayRef(g_thumb_opcode);
420 return llvm::ArrayRef(g_arm_opcode);
422 return llvm::createStringError(llvm::inconvertibleErrorCode(),
423 "Unrecognised trap opcode size hint!");
437 for (
const auto &abs_thread :
m_threads) {
438 assert(abs_thread &&
"thread list should not contain NULL threads");
449 if (action ==
nullptr) {
450 LLDB_LOG(log,
"no action specified for pid {0} tid {1}",
GetID(),
452 action = &suspend_action;
457 "processing resume action state {0} signal {1} for pid {2} tid {3}",
460 switch (action->
state) {
470 return Status(
"Passing signal to suspended thread unsupported");
477 "NativeProcessFreeBSD::%s (): unexpected state %s specified "
478 "for pid %" PRIu64
", tid %" PRIu64,
503 error.SetErrorToErrno();
523 if (kill(
GetID(), signo))
524 error.SetErrorToErrno();
538 case StateType::eStateInvalid:
539 case StateType::eStateExited:
540 case StateType::eStateCrashed:
541 case StateType::eStateDetached:
542 case StateType::eStateUnloaded:
544 LLDB_LOG(log,
"ignored for PID {0} due to current state: {1}",
GetID(),
548 case StateType::eStateConnected:
549 case StateType::eStateAttaching:
550 case StateType::eStateLaunching:
551 case StateType::eStateStopped:
552 case StateType::eStateRunning:
553 case StateType::eStateStepping:
554 case StateType::eStateSuspended:
567 return Status(
"unsupported");
584 "descending memory map entries detected, unexpected");
600 range_info = proc_entry_info;
623 LLDB_LOG(log,
"reusing {0} cached memory region entries",
628 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP,
static_cast<int>(
m_pid)};
632 ret = ::sysctl(mib, 4,
nullptr, &len,
nullptr, 0);
635 return Status(
"sysctl() for KERN_PROC_VMMAP failed");
638 std::unique_ptr<WritableMemoryBuffer> buf =
639 llvm::WritableMemoryBuffer::getNewMemBuffer(len);
640 ret = ::sysctl(mib, 4, buf->getBufferStart(), &len,
nullptr, 0);
643 return Status(
"sysctl() for KERN_PROC_VMMAP failed");
646 char *bp = buf->getBufferStart();
647 char *end = bp + len;
649 auto *kv =
reinterpret_cast<struct kinfo_vmentry *
>(bp);
650 if (kv->kve_structsize == 0)
652 bp += kv->kve_structsize;
660 if (kv->kve_protection & VM_PROT_READ)
665 if (kv->kve_protection & VM_PROT_WRITE)
670 if (kv->kve_protection & VM_PROT_EXECUTE)
685 LLDB_LOG(log,
"failed to find any vmmap entries, assuming no support "
686 "for memory region metadata retrieval");
688 return Status(
"not supported");
690 LLDB_LOG(log,
"read {0} memory region entries from process {1}",
713 FileSpec module_file_spec(module_path);
718 if (it.second.GetFilename() == module_file_spec.
GetFilename()) {
719 file_spec = it.second;
723 return Status(
"Module file (%s) not found in process' memory map!",
737 if (it.second == file) {
738 load_addr = it.first.GetRange().GetRangeBase();
742 return Status(
"No load address found for file %s.", file_name.str().c_str());
749 llvm::sys::RetryAfterSignal(-1, waitpid,
GetID(), &status, WNOHANG);
754 if (wait_pid == -1) {
766 "waitpid ({0}, &status, _) => pid = {1}, status = {2}, exited = {3}",
767 GetID(), wait_pid, status, exited);
779 assert(thread &&
"thread list should not contain NULL threads");
780 if (thread->GetID() == thread_id) {
792 LLDB_LOG(log,
"pid {0} adding thread with tid {1}",
GetID(), thread_id);
794 assert(thread_id > 0);
796 "attempted to add a thread by id that already exists");
802 m_threads.push_back(std::make_unique<NativeThreadFreeBSD>(*
this, thread_id));
808 LLDB_LOG(log,
"pid {0} removing thread with tid {1}",
GetID(), thread_id);
810 assert(thread_id > 0);
812 "attempted to remove a thread that does not exist");
815 if ((*it)->GetID() == thread_id) {
835 if ((wstatus = llvm::sys::RetryAfterSignal(-1, waitpid,
m_pid,
nullptr, 0)) <
850 SetState(StateType::eStateStopped,
false);
855 size_t size,
size_t &bytes_read) {
856 unsigned char *dst =
static_cast<unsigned char *
>(buf);
857 struct ptrace_io_desc io;
860 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
863 io.piod_op = PIOD_READ_D;
867 io.piod_offs = (
void *)(addr + bytes_read);
868 io.piod_addr = dst + bytes_read;
871 if (
error.Fail() || io.piod_len == 0)
874 bytes_read += io.piod_len;
875 io.piod_len = size - bytes_read;
876 }
while (bytes_read < size);
882 size_t size,
size_t &bytes_written) {
883 const unsigned char *src =
static_cast<const unsigned char *
>(buf);
885 struct ptrace_io_desc io;
888 LLDB_LOG(log,
"addr = {0}, buf = {1}, size = {2}", addr, buf, size);
891 io.piod_op = PIOD_WRITE_D;
896 const_cast<void *
>(
static_cast<const void *
>(src + bytes_written));
897 io.piod_offs = (
void *)(addr + bytes_written);
900 if (
error.Fail() || io.piod_len == 0)
903 bytes_written += io.piod_len;
904 io.piod_len = size - bytes_written;
905 }
while (bytes_written < size);
910llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
912 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_AUXV,
static_cast<int>(
GetID())};
913 size_t auxv_size = AT_COUNT *
sizeof(Elf_Auxinfo);
914 std::unique_ptr<WritableMemoryBuffer> buf =
915 llvm::WritableMemoryBuffer::getNewMemBuffer(auxv_size);
917 if (::sysctl(mib, 4, buf->getBufferStart(), &auxv_size,
nullptr, 0) != 0)
918 return std::error_code(errno, std::generic_category());
930 events |= PTRACE_LWP | PTRACE_FORK | PTRACE_VFORK;
947 std::vector<lwpid_t> lwp_ids;
948 lwp_ids.resize(num_lwps);
950 lwp_ids.size() *
sizeof(lwpid_t), &num_lwps);
955 for (lwpid_t lwp : lwp_ids)
968 LLDB_LOG(log,
"fork, child_pid={0}", child_pid);
972 llvm::sys::RetryAfterSignal(-1, ::waitpid, child_pid, &status, 0);
973 if (wait_pid != child_pid) {
975 "waiting for pid {0} failed. Assuming the pid has "
976 "disappeared in the meantime",
980 if (WIFEXITED(status)) {
982 "waiting for pid {0} returned an 'exited' event. Not "
988 struct ptrace_lwpinfo info;
989 const auto siginfo_err =
PtraceWrapper(PT_LWPINFO, child_pid, &info,
sizeof(info));
990 if (siginfo_err.Fail()) {
991 LLDB_LOG(log,
"PT_LWPINFO failed {0}", siginfo_err);
994 assert(info.pl_event == PL_EVENT_SIGNAL);
997 std::unique_ptr<NativeProcessFreeBSD> child_process{
1005 child_process->SetupTrace();
1006 for (
const auto &thread : child_process->m_threads)
1008 child_process->SetState(StateType::eStateStopped,
false);
1015 SetState(StateType::eStateStopped,
true);
1017 child_process->Detach();
1020 if (pt_error.
Fail()) {
1022 "unable to resume parent process {1}: {0}",
GetID());
1023 SetState(StateType::eStateInvalid);
1028llvm::Expected<std::string>
1030#if defined(PT_COREDUMP)
1031 using namespace llvm::sys::fs;
1033 llvm::SmallString<128> path{path_hint};
1035 struct ptrace_coredump
pc = {};
1040 openFile(path,
pc.pc_fd, CD_CreateNew, FA_Write, OF_None)) {
1041 if (std::error_code errc =
1042 createTemporaryFile(
"lldb",
"core",
pc.pc_fd, path))
1043 return llvm::createStringError(errc,
"Unable to create a temporary file");
1047 std::error_code close_err = closeFile(
pc.pc_fd);
1049 return error.ToError();
1051 return llvm::createStringError(
1052 close_err,
"Unable to close the core dump after writing");
1053 return path.str().str();
1055 return llvm::createStringError(
1056 llvm::inconvertibleErrorCode(),
1057 "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.
bool IsMIPS() const
if MIPS architecture return true.
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)
virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware=false)
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
std::map< lldb::tid_t, lldb::addr_t > m_threads_stepping_with_breakpoint
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 > > 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.
Manages communication with the inferior (debugee) process.
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)
std::vector< std::pair< MemoryRegionInfo, FileSpec > > m_mem_region_cache
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, size_t &bytes_written) override
bool SupportHardwareSingleStepping() const
Status SetBreakpoint(lldb::addr_t addr, uint32_t size, bool hardware) override
void SetStoppedByVForkDone()
NativeRegisterContextFreeBSD & GetRegisterContext() 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)
void SetStoppedByWatchpoint(uint32_t wp_index)
void SetStoppedByBreakpoint()
#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.
@ 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)