diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp | 730 |
1 files changed, 67 insertions, 663 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 048819c904f..325fdde029d 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -61,11 +61,6 @@ #include <sys/user.h> #include <sys/wait.h> -#if defined (__arm64__) || defined (__aarch64__) -// NT_PRSTATUS and NT_FPREGSET definition -#include <elf.h> -#endif - #include "lldb/Host/linux/Personality.h" #include "lldb/Host/linux/Ptrace.h" #include "lldb/Host/linux/Signalfd.h" @@ -78,16 +73,6 @@ #define TRAP_HWBKPT 4 #endif -// We disable the tracing of ptrace calls for integration builds to -// avoid the additional indirection and checks. -#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION -#define PTRACE(req, pid, addr, data, data_size, error) \ - PtraceWrapper((req), (pid), (addr), (data), (data_size), (error), #req, __FILE__, __LINE__) -#else -#define PTRACE(req, pid, addr, data, data_size, error) \ - PtraceWrapper((req), (pid), (addr), (data), (data_size), (error)) -#endif - using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; @@ -204,72 +189,6 @@ namespace } } - // Wrapper for ptrace to catch errors and log calls. - // Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) - long - PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error, - const char* reqName, const char* file, int line) - { - long int result; - - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); - - PtraceDisplayBytes(req, data, data_size); - - error.Clear(); - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); - else - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); - - if (result == -1) - error.SetErrorToErrno(); - - if (log) - log->Printf("ptrace(%s, %" PRIu64 ", %p, %p, %zu)=%lX called from file %s line %d", - reqName, pid, addr, data, data_size, result, file, line); - - PtraceDisplayBytes(req, data, data_size); - - if (log && error.GetError() != 0) - { - const char* str; - switch (error.GetError()) - { - case ESRCH: str = "ESRCH"; break; - case EINVAL: str = "EINVAL"; break; - case EBUSY: str = "EBUSY"; break; - case EPERM: str = "EPERM"; break; - default: str = error.AsCString(); - } - log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); - } - - return result; - } - -#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION - // Wrapper for ptrace when logging is not required. - // Sets errno to 0 prior to calling ptrace. - long - PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error) - { - long result = 0; - - error.Clear(); - errno = 0; - if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); - else - result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); - - if (result == -1) - error.SetErrorToErrno(); - return result; - } -#endif - //------------------------------------------------------------------------------ // Static implementations of NativeProcessLinux::ReadMemory and // NativeProcessLinux::WriteMemory. This enables mutual recursion between these @@ -300,7 +219,7 @@ namespace assert(sizeof(data) >= word_size); for (bytes_read = 0; bytes_read < size; bytes_read += remainder) { - data = PTRACE(PTRACE_PEEKDATA, pid, (void*)vm_addr, nullptr, 0, error); + data = NativeProcessLinux::PtraceWrapper(PTRACE_PEEKDATA, pid, (void*)vm_addr, nullptr, 0, error); if (error.Fail()) { if (log) @@ -377,7 +296,7 @@ namespace log->Printf ("NativeProcessLinux::%s() [%p]:0x%lx (0x%lx)", __FUNCTION__, (void*)vm_addr, *(const unsigned long*)src, data); - if (PTRACE(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0, error)) + if (NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, pid, (void*)vm_addr, (void*)data, 0, error)) { if (log) ProcessPOSIXLog::DecNestLevel(); @@ -422,38 +341,9 @@ namespace } //------------------------------------------------------------------------------ - /// @class Operation - /// @brief Represents a NativeProcessLinux operation. - /// - /// Under Linux, it is not possible to ptrace() from any other thread but the - /// one that spawned or attached to the process from the start. Therefore, when - /// a NativeProcessLinux is asked to deliver or change the state of an inferior - /// process the operation must be "funneled" to a specific thread to perform the - /// task. The Operation class provides an abstract base for all services the - /// NativeProcessLinux must perform via the single virtual function Execute, thus - /// encapsulating the code that needs to run in the privileged context. - class Operation - { - public: - Operation () : m_error() { } - - virtual - ~Operation() {} - - virtual void - Execute (NativeProcessLinux *process) = 0; - - const Error & - GetError () const { return m_error; } - - protected: - Error m_error; - }; - - //------------------------------------------------------------------------------ /// @class ReadOperation /// @brief Implements NativeProcessLinux::ReadMemory. - class ReadOperation : public Operation + class ReadOperation : public NativeProcessLinux::Operation { public: ReadOperation( @@ -487,7 +377,7 @@ namespace //------------------------------------------------------------------------------ /// @class WriteOperation /// @brief Implements NativeProcessLinux::WriteMemory. - class WriteOperation : public Operation + class WriteOperation : public NativeProcessLinux::Operation { public: WriteOperation( @@ -519,463 +409,9 @@ namespace } //------------------------------------------------------------------------------ - /// @class ReadRegOperation - /// @brief Implements NativeProcessLinux::ReadRegisterValue. - class ReadRegOperation : public Operation - { - public: - ReadRegOperation(lldb::tid_t tid, uint32_t offset, const char *reg_name, - RegisterValue &value) - : m_tid(tid), - m_offset(static_cast<uintptr_t> (offset)), - m_reg_name(reg_name), - m_value(value) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - uintptr_t m_offset; - const char *m_reg_name; - RegisterValue &m_value; - }; - - void - ReadRegOperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - if (m_offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = m_offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - m_error.SetErrorString("invalid offset value"); - return; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ArchSpec arch; - if (monitor->GetArchitecture(arch)) - m_value.SetBytes((void *)(((unsigned char *)(®s)) + offset), 16, arch.GetByteOrder()); - else - m_error.SetErrorString("failed to get architecture"); - } - } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ArchSpec arch; - if (monitor->GetArchitecture(arch)) - m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); - else - m_error.SetErrorString("failed to get architecture"); - } - } -#elif defined (__mips__) - elf_gregset_t regs; - PTRACE(PTRACE_GETREGS, m_tid, NULL, ®s, sizeof regs, m_error); - if (m_error.Success()) - { - lldb_private::ArchSpec arch; - if (monitor->GetArchitecture(arch)) - m_value.SetBytes((void *)(((unsigned char *)(regs)) + m_offset), 8, arch.GetByteOrder()); - else - m_error.SetErrorString("failed to get architecture"); - } -#else - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - - lldb::addr_t data = static_cast<unsigned long>(PTRACE(PTRACE_PEEKUSER, m_tid, (void*)m_offset, nullptr, 0, m_error)); - if (m_error.Success()) - m_value = data; - - if (log) - log->Printf ("NativeProcessLinux::%s() reg %s: 0x%" PRIx64, __FUNCTION__, - m_reg_name, data); -#endif - } - - //------------------------------------------------------------------------------ - /// @class WriteRegOperation - /// @brief Implements NativeProcessLinux::WriteRegisterValue. - class WriteRegOperation : public Operation - { - public: - WriteRegOperation(lldb::tid_t tid, unsigned offset, const char *reg_name, - const RegisterValue &value) - : m_tid(tid), - m_offset(offset), - m_reg_name(reg_name), - m_value(value) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - uintptr_t m_offset; - const char *m_reg_name; - const RegisterValue &m_value; - }; - - void - WriteRegOperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - if (m_offset > sizeof(struct user_pt_regs)) - { - uintptr_t offset = m_offset - sizeof(struct user_pt_regs); - if (offset > sizeof(struct user_fpsimd_state)) - { - m_error.SetErrorString("invalid offset value"); - return; - } - elf_fpregset_t regs; - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16); - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - } - } - else - { - elf_gregset_t regs; - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = ®s; - ioVec.iov_len = sizeof regs; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - if (m_error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error); - } - } -#elif defined (__mips__) - elf_gregset_t regs; - PTRACE(PTRACE_GETREGS, m_tid, NULL, ®s, sizeof regs, m_error); - if (m_error.Success()) - { - ::memcpy((void *)(((unsigned char *)(®s)) + m_offset), m_value.GetBytes(), 8); - PTRACE(PTRACE_SETREGS, m_tid, NULL, ®s, sizeof regs, m_error); - } -#else - void* buf; - Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS)); - - buf = (void*) m_value.GetAsUInt64(); - - if (log) - log->Printf ("NativeProcessLinux::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf); - PTRACE(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class ReadGPROperation - /// @brief Implements NativeProcessLinux::ReadGPR. - class ReadGPROperation : public Operation - { - public: - ReadGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - ReadGPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_GETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class ReadFPROperation - /// @brief Implements NativeProcessLinux::ReadFPR. - class ReadFPROperation : public Operation - { - public: - ReadFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), - m_buf(buf), - m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - ReadFPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_GETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class ReadDBGROperation - /// @brief Implements NativeProcessLinux::ReadHardwareDebugInfo. - class ReadDBGROperation : public Operation - { - public: - ReadDBGROperation(lldb::tid_t tid, unsigned int &count_wp, unsigned int &count_bp) - : m_tid(tid), - m_count_wp(count_wp), - m_count_bp(count_bp) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - unsigned int &m_count_wp; - unsigned int &m_count_bp; - }; - - void - ReadDBGROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_ARM_HW_WATCH; - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof (dreg_state); - - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); - - m_count_wp = dreg_state.dbg_info & 0xff; - regset = NT_ARM_HW_BREAK; - - PTRACE(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error); - m_count_bp = dreg_state.dbg_info & 0xff; -#endif - } - - - //------------------------------------------------------------------------------ - /// @class ReadRegisterSetOperation - /// @brief Implements NativeProcessLinux::ReadRegisterSet. - class ReadRegisterSetOperation : public Operation - { - public: - ReadRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - const unsigned int m_regset; - }; - - void - ReadRegisterSetOperation::Execute(NativeProcessLinux *monitor) - { - PTRACE(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); - } - - //------------------------------------------------------------------------------ - /// @class WriteGPROperation - /// @brief Implements NativeProcessLinux::WriteGPR. - class WriteGPROperation : public Operation - { - public: - WriteGPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - WriteGPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_PRSTATUS; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_SETREGS, m_tid, NULL, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class WriteFPROperation - /// @brief Implements NativeProcessLinux::WriteFPR. - class WriteFPROperation : public Operation - { - public: - WriteFPROperation(lldb::tid_t tid, void *buf, size_t buf_size) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - }; - - void - WriteFPROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - int regset = NT_FPREGSET; - struct iovec ioVec; - - ioVec.iov_base = m_buf; - ioVec.iov_len = m_buf_size; - PTRACE(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error); -#else - PTRACE(PTRACE_SETFPREGS, m_tid, NULL, m_buf, m_buf_size, m_error); -#endif - } - - //------------------------------------------------------------------------------ - /// @class WriteDBGROperation - /// @brief Implements NativeProcessLinux::WriteHardwareDebugRegs. - class WriteDBGROperation : public Operation - { - public: - WriteDBGROperation(lldb::tid_t tid, lldb::addr_t *addr_buf, - uint32_t *cntrl_buf, int type, int count) - : m_tid(tid), - m_address(addr_buf), - m_control(cntrl_buf), - m_type(type), - m_count(count) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - lldb::addr_t * m_address; - uint32_t * m_control; - int m_type; - int m_count; - }; - - void - WriteDBGROperation::Execute(NativeProcessLinux *monitor) - { -#if defined (__arm64__) || defined (__aarch64__) - struct iovec ioVec; - struct user_hwdebug_state dreg_state; - - memset (&dreg_state, 0, sizeof (dreg_state)); - ioVec.iov_base = &dreg_state; - ioVec.iov_len = sizeof (dreg_state); - - if (m_type == 0) - m_type = NT_ARM_HW_WATCH; - else - m_type = NT_ARM_HW_BREAK; - - for (int i = 0; i < m_count; i++) - { - dreg_state.dbg_regs[i].addr = m_address[i]; - dreg_state.dbg_regs[i].ctrl = m_control[i]; - } - - PTRACE(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error); -#endif - } - - - //------------------------------------------------------------------------------ - /// @class WriteRegisterSetOperation - /// @brief Implements NativeProcessLinux::WriteRegisterSet. - class WriteRegisterSetOperation : public Operation - { - public: - WriteRegisterSetOperation(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) - : m_tid(tid), m_buf(buf), m_buf_size(buf_size), m_regset(regset) - { } - - void Execute(NativeProcessLinux *monitor) override; - - private: - lldb::tid_t m_tid; - void *m_buf; - size_t m_buf_size; - const unsigned int m_regset; - }; - - void - WriteRegisterSetOperation::Execute(NativeProcessLinux *monitor) - { - PTRACE(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error); - } - - //------------------------------------------------------------------------------ /// @class ResumeOperation /// @brief Implements NativeProcessLinux::Resume. - class ResumeOperation : public Operation + class ResumeOperation : public NativeProcessLinux::Operation { public: ResumeOperation(lldb::tid_t tid, uint32_t signo) : @@ -996,7 +432,7 @@ namespace if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) data = m_signo; - PTRACE(PTRACE_CONT, m_tid, nullptr, (void*)data, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_CONT, m_tid, nullptr, (void*)data, 0, m_error); if (m_error.Fail()) { Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); @@ -1009,7 +445,7 @@ namespace //------------------------------------------------------------------------------ /// @class SingleStepOperation /// @brief Implements NativeProcessLinux::SingleStep. - class SingleStepOperation : public Operation + class SingleStepOperation : public NativeProcessLinux::Operation { public: SingleStepOperation(lldb::tid_t tid, uint32_t signo) @@ -1030,13 +466,13 @@ namespace if (m_signo != LLDB_INVALID_SIGNAL_NUMBER) data = m_signo; - PTRACE(PTRACE_SINGLESTEP, m_tid, nullptr, (void*)data, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_SINGLESTEP, m_tid, nullptr, (void*)data, 0, m_error); } //------------------------------------------------------------------------------ /// @class SiginfoOperation /// @brief Implements NativeProcessLinux::GetSignalInfo. - class SiginfoOperation : public Operation + class SiginfoOperation : public NativeProcessLinux::Operation { public: SiginfoOperation(lldb::tid_t tid, void *info) @@ -1052,13 +488,13 @@ namespace void SiginfoOperation::Execute(NativeProcessLinux *monitor) { - PTRACE(PTRACE_GETSIGINFO, m_tid, nullptr, m_info, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_GETSIGINFO, m_tid, nullptr, m_info, 0, m_error); } //------------------------------------------------------------------------------ /// @class EventMessageOperation /// @brief Implements NativeProcessLinux::GetEventMessage. - class EventMessageOperation : public Operation + class EventMessageOperation : public NativeProcessLinux::Operation { public: EventMessageOperation(lldb::tid_t tid, unsigned long *message) @@ -1074,10 +510,10 @@ namespace void EventMessageOperation::Execute(NativeProcessLinux *monitor) { - PTRACE(PTRACE_GETEVENTMSG, m_tid, nullptr, m_message, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_GETEVENTMSG, m_tid, nullptr, m_message, 0, m_error); } - class DetachOperation : public Operation + class DetachOperation : public NativeProcessLinux::Operation { public: DetachOperation(lldb::tid_t tid) : m_tid(tid) { } @@ -1091,7 +527,7 @@ namespace void DetachOperation::Execute(NativeProcessLinux *monitor) { - PTRACE(PTRACE_DETACH, m_tid, nullptr, 0, 0, m_error); + NativeProcessLinux::PtraceWrapper(PTRACE_DETACH, m_tid, nullptr, 0, 0, m_error); } } // end of anonymous namespace @@ -1833,7 +1269,7 @@ NativeProcessLinux::Launch(LaunchArgs *args, Error &error) // send log info to parent re: launch status, in place of the log lines removed here. // Start tracing this child that is about to exec. - PTRACE(PTRACE_TRACEME, 0, nullptr, nullptr, 0, error); + NativeProcessLinux::PtraceWrapper(PTRACE_TRACEME, 0, nullptr, nullptr, 0, error); if (error.Fail()) exit(ePtraceFailed); @@ -2070,7 +1506,7 @@ NativeProcessLinux::Attach(lldb::pid_t pid, Error &error) // Attach to the requested process. // An attach will cause the thread to stop with a SIGSTOP. - PTRACE(PTRACE_ATTACH, tid, nullptr, nullptr, 0, error); + NativeProcessLinux::PtraceWrapper(PTRACE_ATTACH, tid, nullptr, nullptr, 0, error); if (error.Fail()) { // No such thread. The thread may have exited. @@ -2162,7 +1598,7 @@ NativeProcessLinux::SetDefaultPtraceOpts(lldb::pid_t pid) ptrace_opts |= PTRACE_O_TRACEEXEC; Error error; - PTRACE(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts, 0, error); + NativeProcessLinux::PtraceWrapper(PTRACE_SETOPTIONS, pid, nullptr, (void*)ptrace_opts, 0, error); return error; } @@ -3842,88 +3278,6 @@ NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, } Error -NativeProcessLinux::ReadRegisterValue(lldb::tid_t tid, uint32_t offset, const char* reg_name, - uint32_t size, RegisterValue &value) -{ - ReadRegOperation op(tid, offset, reg_name, value); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteRegisterValue(lldb::tid_t tid, unsigned offset, - const char* reg_name, const RegisterValue &value) -{ - WriteRegOperation op(tid, offset, reg_name, value); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - ReadGPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - ReadFPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - ReadRegisterSetOperation op(tid, buf, buf_size, regset); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count , unsigned int &break_count) -{ - ReadDBGROperation op(tid, watch_count, break_count); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count) -{ - WriteDBGROperation op(tid, addr_buf, cntrl_buf, type, count); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - WriteGPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size) -{ - WriteFPROperation op(tid, buf, buf_size); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error -NativeProcessLinux::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset) -{ - WriteRegisterSetOperation op(tid, buf, buf_size, regset); - m_monitor_up->DoOperation(&op); - return op.GetError(); -} - -Error NativeProcessLinux::Resume (lldb::tid_t tid, uint32_t signo) { Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); @@ -4431,3 +3785,53 @@ NativeProcessLinux::ThreadWasCreated (lldb::tid_t tid) thread_sp->RequestStop(); } } + +Error +NativeProcessLinux::DoOperation(Operation* op) +{ + m_monitor_up->DoOperation(op); + return op->GetError(); +} + +// Wrapper for ptrace to catch errors and log calls. +// Note that ptrace sets errno on error because -1 can be a valid result (i.e. for PTRACE_PEEK*) +long +NativeProcessLinux::PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error) +{ + long int result; + + Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PTRACE)); + + PtraceDisplayBytes(req, data, data_size); + + error.Clear(); + errno = 0; + if (req == PTRACE_GETREGSET || req == PTRACE_SETREGSET) + result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), *(unsigned int *)addr, data); + else + result = ptrace(static_cast<__ptrace_request>(req), static_cast< ::pid_t>(pid), addr, data); + + if (result == -1) + error.SetErrorToErrno(); + + if (log) + log->Printf("ptrace(%d, %" PRIu64 ", %p, %p, %zu)=%lX", req, pid, addr, data, data_size, result); + + PtraceDisplayBytes(req, data, data_size); + + if (log && error.GetError() != 0) + { + const char* str; + switch (error.GetError()) + { + case ESRCH: str = "ESRCH"; break; + case EINVAL: str = "EINVAL"; break; + case EBUSY: str = "EBUSY"; break; + case EPERM: str = "EPERM"; break; + default: str = error.AsCString(); + } + log->Printf("ptrace() failed; errno=%d (%s)", error.GetError(), str); + } + + return result; +} |