summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp')
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp730
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 = &regs;
- ioVec.iov_len = sizeof regs;
- PTRACE(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
- if (m_error.Success())
- {
- ArchSpec arch;
- if (monitor->GetArchitecture(arch))
- m_value.SetBytes((void *)(((unsigned char *)(&regs)) + 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 = &regs;
- ioVec.iov_len = sizeof regs;
- PTRACE(PTRACE_GETREGSET, m_tid, &regset, &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, &regs, 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 = &regs;
- ioVec.iov_len = sizeof regs;
- PTRACE(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
- if (m_error.Success())
- {
- ::memcpy((void *)(((unsigned char *)(&regs)) + offset), m_value.GetBytes(), 16);
- PTRACE(PTRACE_SETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
- }
- }
- else
- {
- elf_gregset_t regs;
- int regset = NT_PRSTATUS;
- struct iovec ioVec;
-
- ioVec.iov_base = &regs;
- ioVec.iov_len = sizeof regs;
- PTRACE(PTRACE_GETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
- if (m_error.Success())
- {
- ::memcpy((void *)(((unsigned char *)(&regs)) + m_offset), m_value.GetBytes(), 8);
- PTRACE(PTRACE_SETREGSET, m_tid, &regset, &ioVec, sizeof regs, m_error);
- }
- }
-#elif defined (__mips__)
- elf_gregset_t regs;
- PTRACE(PTRACE_GETREGS, m_tid, NULL, &regs, sizeof regs, m_error);
- if (m_error.Success())
- {
- ::memcpy((void *)(((unsigned char *)(&regs)) + m_offset), m_value.GetBytes(), 8);
- PTRACE(PTRACE_SETREGS, m_tid, NULL, &regs, 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, &regset, &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, &regset, &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, &regset, &ioVec, ioVec.iov_len, m_error);
-
- m_count_wp = dreg_state.dbg_info & 0xff;
- regset = NT_ARM_HW_BREAK;
-
- PTRACE(PTRACE_GETREGSET, m_tid, &regset, &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, &regset, &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, &regset, &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;
+}
OpenPOWER on IntegriCloud