add_lldb_library(lldbPluginProcessLinux
LinuxThread.cpp
NativeProcessLinux.cpp
+ NativeRegisterContextLinux.cpp
NativeRegisterContextLinux_arm.cpp
NativeRegisterContextLinux_arm64.cpp
NativeRegisterContextLinux_x86_64.cpp
ProcessMonitor.cpp
ProcFileReader.cpp
)
-
#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"
#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;
}
}
- // 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
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)
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();
}
//------------------------------------------------------------------------------
- /// @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(
//------------------------------------------------------------------------------
/// @class WriteOperation
/// @brief Implements NativeProcessLinux::WriteMemory.
- class WriteOperation : public Operation
+ class WriteOperation : public NativeProcessLinux::Operation
{
public:
WriteOperation(
}
//------------------------------------------------------------------------------
- /// @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) :
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));
//------------------------------------------------------------------------------
/// @class SingleStepOperation
/// @brief Implements NativeProcessLinux::SingleStep.
- class SingleStepOperation : public Operation
+ class SingleStepOperation : public NativeProcessLinux::Operation
{
public:
SingleStepOperation(lldb::tid_t tid, uint32_t signo)
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)
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)
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) { }
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
// 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);
// 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.
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;
}
}
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));
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;
+}
NativeProcessProtocol::NativeDelegate &native_delegate,
NativeProcessProtocolSP &native_process_sp);
+ //------------------------------------------------------------------------------
+ /// @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;
+ };
+
+ typedef std::unique_ptr<Operation> OperationUP;
+
// ---------------------------------------------------------------------
// NativeProcessProtocol Interface
// ---------------------------------------------------------------------
void
Terminate () override;
+ Error
+ GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override;
+
// ---------------------------------------------------------------------
// Interface used by NativeRegisterContext-derived classes.
// ---------------------------------------------------------------------
-
- /// Reads the contents from the register identified by the given (architecture
- /// dependent) offset.
- ///
- /// This method is provided for use by RegisterContextLinux derivatives.
- Error
- ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
- unsigned size, RegisterValue &value);
-
- /// Writes the given value to the register identified by the given
- /// (architecture dependent) offset.
- ///
- /// This method is provided for use by RegisterContextLinux derivatives.
Error
- WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
- const RegisterValue &value);
+ DoOperation(Operation* op);
- /// Reads all general purpose registers into the specified buffer.
Error
- ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
+ DoOperation(OperationUP op) { return DoOperation(op.get()); }
- /// Reads generic floating point registers into the specified buffer.
- Error
- ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Reads hardware breakpoints and watchpoints capability information.
- Error
- ReadHardwareDebugInfo (lldb::tid_t tid, unsigned int &watch_count ,
- unsigned int &break_count);
-
- /// Write hardware breakpoint/watchpoint control and address registers.
- Error
- WriteHardwareDebugRegs (lldb::tid_t tid, lldb::addr_t *addr_buf,
- uint32_t *cntrl_buf, int type, int count);
-
- /// Reads the specified register set into the specified buffer.
- /// For instance, the extended floating-point register set.
- Error
- ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
-
- /// Writes all general purpose registers into the specified buffer.
- Error
- WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Writes generic floating point registers into the specified buffer.
- Error
- WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
-
- /// Writes the specified register set into the specified buffer.
- /// For instance, the extended floating-point register set.
- Error
- WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
-
- Error
- GetLoadedModuleFileSpec(const char* module_path, FileSpec& file_spec) override;
+ static long
+ PtraceWrapper(int req, lldb::pid_t pid, void *addr, void *data, size_t data_size, Error& error);
protected:
// ---------------------------------------------------------------------
--- /dev/null
+//===-- NativeRegisterContextLinux.cpp --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NativeRegisterContextLinux.h"
+
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/Host/linux/Ptrace.h"
+
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+
+using namespace lldb_private;
+using namespace lldb_private::process_linux;
+
+namespace
+{
+
+class ReadRegOperation : public NativeProcessLinux::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;
+};
+
+class WriteRegOperation : public NativeProcessLinux::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;
+};
+
+class ReadGPROperation : public NativeProcessLinux::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;
+};
+
+class WriteGPROperation : public NativeProcessLinux::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;
+};
+
+class ReadFPROperation : public NativeProcessLinux::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;
+};
+
+class WriteFPROperation : public NativeProcessLinux::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;
+};
+
+class ReadRegisterSetOperation : public NativeProcessLinux::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;
+};
+
+class WriteRegisterSetOperation : public NativeProcessLinux::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;
+};
+
+} // end of anonymous namespace
+
+void
+ReadRegOperation::Execute(NativeProcessLinux *monitor)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+
+ lldb::addr_t data = static_cast<unsigned long>(NativeProcessLinux::PtraceWrapper(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);
+}
+
+void
+WriteRegOperation::Execute(NativeProcessLinux *monitor)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+
+ void* buf = (void*)m_value.GetAsUInt64();
+
+ if (log)
+ log->Printf ("NativeProcessLinux::%s() reg %s: %p", __FUNCTION__, m_reg_name, buf);
+ NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSER, m_tid, (void*)m_offset, buf, 0, m_error);
+}
+
+void
+ReadGPROperation::Execute(NativeProcessLinux *monitor)
+{
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
+}
+
+void
+WriteGPROperation::Execute(NativeProcessLinux *monitor)
+{
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
+}
+
+void
+ReadFPROperation::Execute(NativeProcessLinux *monitor)
+{
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
+}
+
+void
+WriteFPROperation::Execute(NativeProcessLinux *monitor)
+{
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETFPREGS, m_tid, nullptr, m_buf, m_buf_size, m_error);
+}
+
+void
+ReadRegisterSetOperation::Execute(NativeProcessLinux *monitor)
+{
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error);
+}
+
+void
+WriteRegisterSetOperation::Execute(NativeProcessLinux *monitor)
+{
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, (void *)&m_regset, m_buf, m_buf_size, m_error);
+}
+
+NativeRegisterContextLinux::NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *reg_info_interface_p) :
+ NativeRegisterContextRegisterInfo(native_thread, concrete_frame_idx, reg_info_interface_p)
+{}
+
+lldb::ByteOrder
+NativeRegisterContextLinux::GetByteOrder() const
+{
+ // Get the target process whose privileged thread was used for the register read.
+ lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return byte_order;
+
+ if (!process_sp->GetByteOrder (byte_order))
+ {
+ // FIXME log here
+ }
+
+ return byte_order;
+}
+
+Error
+NativeRegisterContextLinux::ReadRegisterRaw(uint32_t reg_index, RegisterValue ®_value)
+{
+ const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info)
+ return Error("register %" PRIu32 " not found", reg_index);
+
+ NativeProcessProtocolSP process_sp(m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation(GetReadRegisterValueOperation(reg_info->byte_offset,
+ reg_info->name,
+ reg_info->byte_size,
+ reg_value));
+}
+
+Error
+NativeRegisterContextLinux::WriteRegisterRaw(uint32_t reg_index, const RegisterValue ®_value)
+{
+ uint32_t reg_to_write = reg_index;
+ RegisterValue value_to_write = reg_value;
+
+ // Check if this is a subregister of a full register.
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
+ if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+ {
+ Error error;
+
+ RegisterValue full_value;
+ uint32_t full_reg = reg_info->invalidate_regs[0];
+ const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+ // Read the full register.
+ error = ReadRegister(full_reg_info, full_value);
+ if (error.Fail ())
+ return error;
+
+ lldb::ByteOrder byte_order = GetByteOrder();
+ uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the full register.
+ const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+ dst,
+ sizeof(dst),
+ byte_order,
+ error);
+ if (error.Success() && dest_size)
+ {
+ uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+ // Get the bytes for the source data.
+ const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
+ if (error.Success() && src_size && (src_size < dest_size))
+ {
+ // Copy the src bytes to the destination.
+ memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+ // Set this full register as the value to write.
+ value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+ value_to_write.SetType(full_reg_info);
+ reg_to_write = full_reg;
+ }
+ }
+ }
+
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
+ const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
+ assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
+ if (!register_to_write_info_p)
+ return Error("NativeRegisterContextLinux::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
+
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*> (process_sp.get ());
+ return process_p->DoOperation(GetWriteRegisterValueOperation(reg_info->byte_offset,
+ reg_info->name,
+ reg_value));
+}
+
+Error
+NativeRegisterContextLinux::ReadGPR()
+{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
+ void* buf = GetGPRBuffer();
+ if (!buf)
+ return Error("GPR buffer is NULL");
+ size_t buf_size = GetGPRSize();
+
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation(GetReadGPROperation(buf, buf_size));
+}
+
+Error
+NativeRegisterContextLinux::WriteGPR()
+{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
+ void* buf = GetGPRBuffer();
+ if (!buf)
+ return Error("GPR buffer is NULL");
+ size_t buf_size = GetGPRSize();
+
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation(GetWriteGPROperation(buf, buf_size));
+}
+
+Error
+NativeRegisterContextLinux::ReadFPR()
+{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
+ void* buf = GetFPRBuffer();
+ if (!buf)
+ return Error("GPR buffer is NULL");
+ size_t buf_size = GetFPRSize();
+
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation(GetReadFPROperation(buf, buf_size));
+}
+
+Error
+NativeRegisterContextLinux::WriteFPR()
+{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+
+ void* buf = GetFPRBuffer();
+ if (!buf)
+ return Error("GPR buffer is NULL");
+ size_t buf_size = GetFPRSize();
+
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+ return process_p->DoOperation(GetWriteFPROperation(buf, buf_size));
+}
+
+Error
+NativeRegisterContextLinux::ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset)
+{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+
+ ReadRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset);
+ return process_p->DoOperation(&op);
+}
+
+Error
+NativeRegisterContextLinux::WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset)
+{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux* process_p = static_cast<NativeProcessLinux*>(process_sp.get());
+
+ WriteRegisterSetOperation op(m_thread.GetID(), buf, buf_size, regset);
+ return process_p->DoOperation(&op);
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux::GetReadRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value)
+{
+ return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux::GetWriteRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ const RegisterValue &value)
+{
+ return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux::GetReadGPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux::GetWriteGPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux::GetReadFPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux::GetWriteFPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size));
+}
--- /dev/null
+//===-- NativeRegisterContextLinux.h ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_NativeRegisterContextLinux_h
+#define lldb_NativeRegisterContextLinux_h
+
+#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h"
+#include "lldb/Host/common/NativeThreadProtocol.h"
+
+#include "Plugins/Process/Linux/NativeProcessLinux.h"
+
+namespace lldb_private {
+namespace process_linux {
+
+class NativeRegisterContextLinux : public NativeRegisterContextRegisterInfo
+{
+public:
+ NativeRegisterContextLinux(NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx,
+ RegisterInfoInterface *reg_info_interface_p);
+
+ // This function is implemented in the NativeRegisterContextLinux_* subclasses to create a new
+ // instance of the host specific NativeRegisterContextLinux. The implementations can't collide
+ // as only one NativeRegisterContextLinux_* variant should be compiled into the final
+ // executable.
+ static NativeRegisterContextLinux*
+ CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
+
+protected:
+ lldb::ByteOrder
+ GetByteOrder() const;
+
+ virtual Error
+ ReadRegisterRaw(uint32_t reg_index, RegisterValue& reg_value);
+
+ virtual Error
+ WriteRegisterRaw(uint32_t reg_index, const RegisterValue& reg_value);
+
+ virtual Error
+ ReadRegisterSet(void *buf, size_t buf_size, unsigned int regset);
+
+ virtual Error
+ WriteRegisterSet(void *buf, size_t buf_size, unsigned int regset);
+
+ virtual Error
+ ReadGPR();
+
+ virtual Error
+ WriteGPR();
+
+ virtual Error
+ ReadFPR();
+
+ virtual Error
+ WriteFPR();
+
+ virtual void*
+ GetGPRBuffer() { return nullptr; };
+
+ virtual size_t
+ GetGPRSize() { return GetRegisterInfoInterface().GetGPRSize(); }
+
+ virtual void*
+ GetFPRBuffer() { return nullptr; }
+
+ virtual size_t
+ GetFPRSize() { return 0; }
+
+ virtual NativeProcessLinux::OperationUP
+ GetReadRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value);
+
+ virtual NativeProcessLinux::OperationUP
+ GetWriteRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ const RegisterValue &value);
+
+ virtual NativeProcessLinux::OperationUP
+ GetReadGPROperation(void *buf, size_t buf_size);
+
+ virtual NativeProcessLinux::OperationUP
+ GetWriteGPROperation(void *buf, size_t buf_size);
+
+ virtual NativeProcessLinux::OperationUP
+ GetReadFPROperation(void *buf, size_t buf_size);
+
+ virtual NativeProcessLinux::OperationUP
+ GetWriteFPROperation(void *buf, size_t buf_size);
+};
+
+} // namespace process_linux
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextLinux_h
+
//
//===----------------------------------------------------------------------===//
+#if defined(__arm__)
+
#include "NativeRegisterContextLinux_arm.h"
-#include "lldb/lldb-private-forward.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/RegisterValue.h"
-#include "lldb/Host/common/NativeProcessProtocol.h"
-#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "Plugins/Process/Linux/NativeProcessLinux.h"
+
+#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
{ "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
};
-NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx,
- RegisterInfoInterface *reg_info_interface_p) :
- NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p)
+NativeRegisterContextLinux*
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+{
+ return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
+}
+
+NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) :
+ NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm(target_arch))
{
- switch (reg_info_interface_p->m_target_arch.GetMachine())
+ switch (target_arch.GetMachine())
{
case llvm::Triple::arm:
m_reg_info.num_registers = k_num_registers_arm;
if (IsFPR(reg))
{
- if (!ReadFPR())
- {
- error.SetErrorString ("failed to read floating point register");
+ error = ReadFPR();
+ if (error.Fail())
return error;
- }
}
else
{
return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
}
- if (!WriteFPR())
- {
- return Error ("NativeRegisterContextLinux_arm::WriteRegister: WriteFPR failed");
- }
+ Error error = WriteFPR();
+ if (error.Fail())
+ return error;
return Error ();
}
if (!data_sp)
return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, (uint64_t)REG_CONTEXT_SIZE);
- if (!ReadGPR ())
- {
- error.SetErrorString ("ReadGPR() failed");
+ error = ReadGPR();
+ if (error.Fail())
return error;
- }
- if (!ReadFPR ())
- {
- error.SetErrorString ("ReadFPR() failed");
+ error = ReadFPR();
+ if (error.Fail())
return error;
- }
uint8_t *dst = data_sp->GetBytes ();
if (dst == nullptr)
}
::memcpy (&m_gpr_arm, src, GetRegisterInfoInterface ().GetGPRSize ());
- if (!WriteGPR ())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__);
+ error = WriteGPR();
+ if (error.Fail())
return error;
- }
src += GetRegisterInfoInterface ().GetGPRSize ();
::memcpy (&m_fpr, src, sizeof(m_fpr));
- if (!WriteFPR ())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__);
+ error = WriteFPR();
+ if (error.Fail())
return error;
- }
return error;
}
-Error
-NativeRegisterContextLinux_arm::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value)
-{
- Error error;
-
- uint32_t reg_to_write = reg_index;
- RegisterValue value_to_write = reg_value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
- if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
- {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- error = ReadRegister(full_reg_info, full_value);
- if (error.Fail ())
- return error;
-
- lldb::ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
- dst,
- sizeof(dst),
- byte_order,
- error);
- if (error.Success() && dest_size)
- {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size))
- {
- // Copy the src bytes to the destination.
- memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
- assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
- if (!register_to_write_info_p)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->WriteRegisterValue(m_thread.GetID(),
- register_to_write_info_p->byte_offset,
- register_to_write_info_p->name,
- value_to_write);
-}
-
-Error
-NativeRegisterContextLinux_arm::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value)
-{
- Error error;
- const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index);
- if (!reg_info)
- {
- error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index);
- return error;
- }
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->ReadRegisterValue(m_thread.GetID(),
- reg_info->byte_offset,
- reg_info->name,
- reg_info->byte_size,
- reg_value);
-}
-
bool
NativeRegisterContextLinux_arm::IsGPR(unsigned reg) const
{
}
bool
-NativeRegisterContextLinux_arm::ReadGPR()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
- return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success();
-}
-
-bool
-NativeRegisterContextLinux_arm::WriteGPR()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
- return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm, GetRegisterInfoInterface ().GetGPRSize ()).Success();
-}
-
-bool
NativeRegisterContextLinux_arm::IsFPR(unsigned reg) const
{
return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
}
-bool
-NativeRegisterContextLinux_arm::ReadFPR ()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success();
-}
-
-bool
-NativeRegisterContextLinux_arm::WriteFPR ()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success();
-}
-
-lldb::ByteOrder
-NativeRegisterContextLinux_arm::GetByteOrder() const
-{
- // Get the target process whose privileged thread was used for the register read.
- lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return byte_order;
-
- if (!process_sp->GetByteOrder (byte_order))
- {
- // FIXME log here
- }
-
- return byte_order;
-}
-
-size_t
-NativeRegisterContextLinux_arm::GetGPRSize() const
-{
- return GetRegisterInfoInterface().GetGPRSize();
-}
+#endif // defined(__arm__)
//
//===----------------------------------------------------------------------===//
+#if defined(__arm__) // arm register context only needed on arm devices
#ifndef lldb_NativeRegisterContextLinux_arm_h
#define lldb_NativeRegisterContextLinux_arm_h
-#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h"
+#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
namespace lldb_private {
class NativeProcessLinux;
- class NativeRegisterContextLinux_arm : public NativeRegisterContextRegisterInfo
+ class NativeRegisterContextLinux_arm : public NativeRegisterContextLinux
{
public:
- NativeRegisterContextLinux_arm (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p);
+ NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
uint32_t
GetRegisterSetCount () const override;
Error
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
+ protected:
+ void*
+ GetGPRBuffer() override { return &m_gpr_arm; }
+
+ void*
+ GetFPRBuffer() override { return &m_fpr; }
+
+ size_t
+ GetFPRSize() override { return sizeof(m_fpr); }
+
private:
struct RegInfo
{
IsGPR(unsigned reg) const;
bool
- ReadGPR ();
-
- bool
- WriteGPR ();
-
- bool
IsFPR(unsigned reg) const;
-
- bool
- ReadFPR ();
-
- bool
- WriteFPR ();
-
- Error
- ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value);
-
- Error
- WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value);
-
- lldb::ByteOrder
- GetByteOrder() const;
-
- size_t
- GetGPRSize() const;
};
} // namespace process_linux
#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h
+#endif // defined(__arm__)
//
//===----------------------------------------------------------------------===//
+#if defined (__arm64__) || defined (__aarch64__)
+
#include "NativeRegisterContextLinux_arm64.h"
-#include "lldb/lldb-private-forward.h"
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
-#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
-#include "lldb/Host/common/NativeThreadProtocol.h"
+
#include "Plugins/Process/Linux/NativeProcessLinux.h"
-#include "lldb/Core/Log.h"
+#include "Plugins/Process/Linux/Procfs.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
+
+// System includes - They have to be included after framework includes because they define some
+// macros which collide with variable names in other modules
+#include <sys/socket.h>
+// NT_PRSTATUS and NT_FPREGSET definition
+#include <elf.h>
-#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
+#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
using namespace lldb;
using namespace lldb_private;
{ "Floating Point Registers", "fpu", k_num_fpr_registers_arm64, g_fpu_regnums_arm64 }
};
-NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (
- NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx,
- RegisterInfoInterface *reg_info_interface_p) :
- NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p)
+namespace
+{
+
+class ReadRegOperation : public NativeProcessLinux::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;
+};
+
+class WriteRegOperation : public NativeProcessLinux::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;
+};
+
+class ReadGPROperation : public NativeProcessLinux::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;
+};
+
+class WriteGPROperation : public NativeProcessLinux::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;
+};
+
+class ReadFPROperation : public NativeProcessLinux::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;
+};
+
+class WriteFPROperation : public NativeProcessLinux::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;
+};
+
+class ReadDBGROperation : public NativeProcessLinux::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;
+};
+
+class WriteDBGROperation : public NativeProcessLinux::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;
+};
+
+} // end of anonymous namespace
+
+void
+ReadRegOperation::Execute(NativeProcessLinux *monitor)
+{
+ 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;
+ NativeProcessLinux::PtraceWrapper(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;
+ NativeProcessLinux::PtraceWrapper(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");
+ }
+ }
+}
+
+void
+WriteRegOperation::Execute(NativeProcessLinux *monitor)
+{
+ 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;
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error);
+ if (m_error.Success())
+ {
+ ::memcpy((void *)(((unsigned char *)(®s)) + offset), m_value.GetBytes(), 16);
+ NativeProcessLinux::PtraceWrapper(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;
+ NativeProcessLinux::PtraceWrapper(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);
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, sizeof regs, m_error);
+ }
+ }
+}
+
+void
+ReadGPROperation::Execute(NativeProcessLinux *monitor)
+{
+ int regset = NT_PRSTATUS;
+ struct iovec ioVec;
+
+ ioVec.iov_base = m_buf;
+ ioVec.iov_len = m_buf_size;
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error);
+}
+
+void
+WriteGPROperation::Execute(NativeProcessLinux *monitor)
+{
+ int regset = NT_PRSTATUS;
+ struct iovec ioVec;
+
+ ioVec.iov_base = m_buf;
+ ioVec.iov_len = m_buf_size;
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error);
+}
+
+void
+ReadFPROperation::Execute(NativeProcessLinux *monitor)
+{
+ int regset = NT_FPREGSET;
+ struct iovec ioVec;
+
+ ioVec.iov_base = m_buf;
+ ioVec.iov_len = m_buf_size;
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error);
+}
+
+void
+WriteFPROperation::Execute(NativeProcessLinux *monitor)
{
- switch (reg_info_interface_p->m_target_arch.GetMachine())
+ int regset = NT_FPREGSET;
+ struct iovec ioVec;
+
+ ioVec.iov_base = m_buf;
+ ioVec.iov_len = m_buf_size;
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, ®set, &ioVec, m_buf_size, m_error);
+}
+
+void
+ReadDBGROperation::Execute(NativeProcessLinux *monitor)
+{
+ 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);
+
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error);
+
+ m_count_wp = dreg_state.dbg_info & 0xff;
+ regset = NT_ARM_HW_BREAK;
+
+ NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, m_tid, ®set, &ioVec, ioVec.iov_len, m_error);
+ m_count_bp = dreg_state.dbg_info & 0xff;
+}
+
+void
+WriteDBGROperation::Execute(NativeProcessLinux *monitor)
+{
+ 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];
+ }
+
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_tid, &m_type, &ioVec, ioVec.iov_len, m_error);
+}
+
+NativeRegisterContextLinux*
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+{
+ return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx);
+}
+
+NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) :
+ NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_arm64(target_arch))
+{
+ switch (target_arch.GetMachine())
{
case llvm::Triple::aarch64:
m_reg_info.num_registers = k_num_registers_arm64;
if (IsFPR(reg))
{
- if (!ReadFPR())
- {
- error.SetErrorString ("failed to read floating point register");
+ error = ReadFPR();
+ if (error.Fail())
return error;
- }
}
else
{
return Error ("unhandled register data size %" PRIu32, reg_info->byte_size);
}
- if (!WriteFPR())
- {
- return Error ("NativeRegisterContextLinux_arm64::WriteRegister: WriteFPR failed");
- }
+ Error error = WriteFPR();
+ if (error.Fail())
+ return error;
return Error ();
}
if (!data_sp)
return Error ("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
- if (!ReadGPR ())
- {
- error.SetErrorString ("ReadGPR() failed");
+ error = ReadGPR();
+ if (error.Fail())
return error;
- }
- if (!ReadFPR ())
- {
- error.SetErrorString ("ReadFPR() failed");
+ error = ReadFPR();
+ if (error.Fail())
return error;
- }
uint8_t *dst = data_sp->GetBytes ();
if (dst == nullptr)
}
::memcpy (&m_gpr_arm64, src, GetRegisterInfoInterface ().GetGPRSize ());
- if (!WriteGPR ())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__);
+ error = WriteGPR();
+ if (error.Fail())
return error;
- }
src += GetRegisterInfoInterface ().GetGPRSize ();
::memcpy (&m_fpr, src, sizeof(m_fpr));
- if (!WriteFPR ())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__);
+ error = WriteFPR();
+ if (error.Fail())
return error;
- }
return error;
}
-Error
-NativeRegisterContextLinux_arm64::WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value)
-{
- Error error;
-
- uint32_t reg_to_write = reg_index;
- RegisterValue value_to_write = reg_value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_index);
- if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
- {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- error = ReadRegister(full_reg_info, full_value);
- if (error.Fail ())
- return error;
-
- lldb::ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
- dst,
- sizeof(dst),
- byte_order,
- error);
- if (error.Success() && dest_size)
- {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = reg_value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size))
- {
- // Copy the src bytes to the destination.
- memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
- assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
- if (!register_to_write_info_p)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_arm64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->WriteRegisterValue(m_thread.GetID(),
- register_to_write_info_p->byte_offset,
- register_to_write_info_p->name,
- value_to_write);
-}
-
-Error
-NativeRegisterContextLinux_arm64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value)
-{
- Error error;
- const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index);
- if (!reg_info)
- {
- error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index);
- return error;
- }
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->ReadRegisterValue(m_thread.GetID(),
- reg_info->byte_offset,
- reg_info->name,
- reg_info->byte_size,
- reg_value);
-}
-
bool
NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const
{
}
bool
-NativeRegisterContextLinux_arm64::ReadGPR()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
- return process_p->ReadGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success();
-}
-
-bool
-NativeRegisterContextLinux_arm64::WriteGPR()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
- return process_p->WriteGPR (m_thread.GetID (), &m_gpr_arm64, GetRegisterInfoInterface ().GetGPRSize ()).Success();
-}
-
-bool
NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const
{
return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
}
-bool
-NativeRegisterContextLinux_arm64::ReadFPR ()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->ReadFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success();
-}
-
-bool
-NativeRegisterContextLinux_arm64::WriteFPR ()
-{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->WriteFPR (m_thread.GetID (), &m_fpr, sizeof (m_fpr)).Success();
-}
-
-lldb::ByteOrder
-NativeRegisterContextLinux_arm64::GetByteOrder() const
-{
- // Get the target process whose privileged thread was used for the register read.
- lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return byte_order;
-
- if (!process_sp->GetByteOrder (byte_order))
- {
- // FIXME log here
- }
-
- return byte_order;
-}
-
-size_t
-NativeRegisterContextLinux_arm64::GetGPRSize() const
-{
- return GetRegisterInfoInterface().GetGPRSize();
-}
-
uint32_t
NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
{
if (!process_sp)
return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
// Check if our hardware breakpoint and watchpoint information is updated.
if (m_refresh_hwdebug_info)
{
- process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported,
- m_max_hbp_supported);
+ ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported);
m_refresh_hwdebug_info = false;
}
if (!process_sp)
return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
+
// Check if our hardware breakpoint and watchpoint information is updated.
if (m_refresh_hwdebug_info)
{
- process_p->ReadHardwareDebugInfo (m_thread.GetID (), m_max_hwp_supported,
- m_max_hbp_supported);
+ ReadHardwareDebugInfo (m_max_hwp_supported, m_max_hbp_supported);
m_refresh_hwdebug_info = false;
}
m_hwp_regs[wp_index].refcount = 1;
// PTRACE call to set corresponding watchpoint register.
- process_p->WriteHardwareDebugRegs(m_thread.GetID (), &addr,
- &control_value, 0, wp_index);
+ WriteHardwareDebugRegs(&addr, &control_value, 0, wp_index);
}
else
m_hwp_regs[wp_index].refcount++;
if (!process_sp)
return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
if (wp_index >= m_max_hwp_supported)
return false;
m_hwp_regs[wp_index].refcount = 0;
//TODO: PTRACE CALL HERE for an UPDATE
- process_p->WriteHardwareDebugRegs(m_thread.GetID (),
- &m_hwp_regs[wp_index].address,
- &m_hwp_regs[wp_index].control,
- 0, wp_index);
+ WriteHardwareDebugRegs(&m_hwp_regs[wp_index].address, &m_hwp_regs[wp_index].control, 0, wp_index);
return true;
}
if (!process_sp)
return ml_error;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
for (uint32_t i = 0; i < m_max_hwp_supported; i++)
{
if (m_hwp_regs[i].control & 0x01)
m_hwp_regs[i].address = 0;
m_hwp_regs[i].refcount = 0;
- process_p->WriteHardwareDebugRegs(m_thread.GetID (),
- &m_hwp_regs[i].address,
- &m_hwp_regs[i].control,
- 0, i);
+ WriteHardwareDebugRegs(&m_hwp_regs[i].address, &m_hwp_regs[i].control, 0, i);
}
}
return LLDB_INVALID_ADDRESS;
}
-bool
-NativeRegisterContextLinux_arm64::HardwareSingleStep (bool enable)
+Error
+NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo(unsigned int &watch_count,
+ unsigned int &break_count)
{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
- if (log)
- log->Printf ("NativeRegisterContextLinux_arm64::%s()", __FUNCTION__);
+ ReadDBGROperation op(m_thread.GetID(), watch_count, break_count);
+ return process_p->DoOperation(&op);
+}
- return false;
+Error
+NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(lldb::addr_t *addr_buf,
+ uint32_t *cntrl_buf,
+ int type,
+ int count)
+{
+ NativeProcessProtocolSP process_sp (m_thread.GetProcess());
+ if (!process_sp)
+ return Error("NativeProcessProtocol is NULL");
+ NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*>(process_sp.get());
+
+ WriteDBGROperation op(m_thread.GetID(), addr_buf, cntrl_buf, type, count);
+ return process_p->DoOperation(&op);
}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_arm64::GetReadRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value)
+{
+ return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, reg_name, value));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_arm64::GetWriteRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ const RegisterValue &value)
+{
+ return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_arm64::GetReadGPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new ReadGPROperation(m_thread.GetID(), buf, buf_size));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_arm64::GetWriteGPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new WriteGPROperation(m_thread.GetID(), buf, buf_size));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_arm64::GetReadFPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new ReadFPROperation(m_thread.GetID(), buf, buf_size));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_arm64::GetWriteFPROperation(void *buf, size_t buf_size)
+{
+ return NativeProcessLinux::OperationUP(new WriteFPROperation(m_thread.GetID(), buf, buf_size));
+}
+
+#endif // defined (__arm64__) || defined (__aarch64__)
//
//===----------------------------------------------------------------------===//
+#if defined (__arm64__) || defined (__aarch64__)
#ifndef lldb_NativeRegisterContextLinux_arm64_h
#define lldb_NativeRegisterContextLinux_arm64_h
-#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h"
+#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
#include "Plugins/Process/Utility/lldb-arm64-register-enums.h"
namespace lldb_private {
class NativeProcessLinux;
- class NativeRegisterContextLinux_arm64 : public NativeRegisterContextRegisterInfo
+ class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux
{
public:
- NativeRegisterContextLinux_arm64 (NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx,
- RegisterInfoInterface *reg_info_interface_p);
+ NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
uint32_t
GetRegisterSetCount () const override;
lldb::addr_t
GetWatchpointAddress (uint32_t wp_index) override;
- bool
- HardwareSingleStep (bool enable) override;
-
uint32_t
GetWatchpointSize(uint32_t wp_index);
bool
WatchpointIsEnabled(uint32_t wp_index);
+ protected:
+ NativeProcessLinux::OperationUP
+ GetReadRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value) override;
+
+ NativeProcessLinux::OperationUP
+ GetWriteRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ const RegisterValue &value) override;
+
+ NativeProcessLinux::OperationUP
+ GetReadGPROperation(void *buf, size_t buf_size) override;
+
+ NativeProcessLinux::OperationUP
+ GetWriteGPROperation(void *buf, size_t buf_size) override;
+
+ NativeProcessLinux::OperationUP
+ GetReadFPROperation(void *buf, size_t buf_size) override;
+
+ NativeProcessLinux::OperationUP
+ GetWriteFPROperation(void *buf, size_t buf_size) override;
+
+ void*
+ GetGPRBuffer() override { return &m_gpr_arm64; }
+
+ void*
+ GetFPRBuffer() override { return &m_fpr; }
+
+ size_t
+ GetFPRSize() override { return sizeof(m_fpr); }
+
private:
struct RegInfo
{
IsGPR(unsigned reg) const;
bool
- ReadGPR ();
-
- bool
- WriteGPR ();
-
- bool
IsFPR(unsigned reg) const;
- bool
- ReadFPR ();
-
- bool
- WriteFPR ();
-
Error
- ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value);
+ ReadHardwareDebugInfo(unsigned int &watch_count , unsigned int &break_count);
Error
- WriteRegisterRaw (uint32_t reg_index, const RegisterValue ®_value);
-
- lldb::ByteOrder
- GetByteOrder() const;
-
- size_t
- GetGPRSize() const;
+ WriteHardwareDebugRegs(lldb::addr_t *addr_buf, uint32_t *cntrl_buf, int type, int count);
};
} // namespace process_linux
#endif // #ifndef lldb_NativeRegisterContextLinux_arm64_h
+#endif // defined (__arm64__) || defined (__aarch64__)
//
//===----------------------------------------------------------------------===//
+#if defined (__mips__)
+
#include "NativeRegisterContextLinux_mips64.h"
-#include "lldb/lldb-private-forward.h"
-#include "lldb/Core/DataBufferHeap.h"
+// C Includes
+// C++ Includes
+
+// Other libraries and framework includes
#include "lldb/Core/Error.h"
#include "lldb/Core/RegisterValue.h"
-#include "lldb/Host/common/NativeProcessProtocol.h"
-#include "lldb/Host/common/NativeThreadProtocol.h"
+
#include "Plugins/Process/Linux/NativeProcessLinux.h"
+#include "Plugins/Process/Linux/Procfs.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
using namespace lldb_private;
using namespace lldb_private::process_linux;
{
{ "General Purpose Registers", "gpr", k_num_gp_reg_mips64, g_gp_regnums_mips64 }
};
+
+ class ReadRegOperation : public NativeProcessLinux::Operation
+ {
+ public:
+ ReadRegOperation(lldb::tid_t tid, uint32_t offset, RegisterValue &value) :
+ m_tid(tid),
+ m_offset(static_cast<uintptr_t>(offset)),
+ m_value(value)
+ { }
+
+ void
+ Execute(NativeProcessLinux *monitor) override;
+
+ private:
+ lldb::tid_t m_tid;
+ uintptr_t m_offset;
+ RegisterValue &m_value;
+ };
+
+ class WriteRegOperation : public NativeProcessLinux::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;
+ };
+
+} // end of anonymous namespace
+
+void
+ReadRegOperation::Execute(NativeProcessLinux *monitor)
+{
+ elf_gregset_t regs;
+ NativeProcessLinux::PtraceWrapper(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");
+ }
+}
+
+void
+WriteRegOperation::Execute(NativeProcessLinux *monitor)
+{
+ elf_gregset_t regs;
+ NativeProcessLinux::PtraceWrapper(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);
+ NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_tid, NULL, ®s, sizeof regs, m_error);
+ }
+}
+
+NativeRegisterContextLinux*
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+{
+ return new NativeRegisterContextLinux_mips64(target_arch, native_thread, concrete_frame_idx);
}
// ----------------------------------------------------------------------------
// NativeRegisterContextLinux_mips64 members.
// ----------------------------------------------------------------------------
-NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p) :
- NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p)
+NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) :
+ NativeRegisterContextLinux (native_thread, concrete_frame_idx, new RegisterContextLinux_mips64 (target_arch))
{
}
}
lldb_private::Error
-NativeRegisterContextLinux_mips64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value)
-{
- Error error;
-
- const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index);
- if (!reg_info)
- {
- error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index);
- return error;
- }
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->ReadRegisterValue(m_thread.GetID(),
- reg_info->byte_offset,
- reg_info->name,
- reg_info->byte_size,
- reg_value);
-}
-
-lldb_private::Error
NativeRegisterContextLinux_mips64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value)
{
Error error;
}
lldb_private::Error
-NativeRegisterContextLinux_mips64::WriteRegister(const uint32_t reg,
- const RegisterValue &value)
-{
- Error error;
-
- uint32_t reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
- assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
- if (!register_to_write_info_p)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_mips64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->WriteRegisterValue(m_thread.GetID(),
- register_to_write_info_p->byte_offset,
- register_to_write_info_p->name,
- value_to_write);
-}
-
-
-
-lldb_private::Error
NativeRegisterContextLinux_mips64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value)
{
assert (reg_info && "reg_info is null");
if (reg_index == LLDB_INVALID_REGNUM)
return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
- return WriteRegister(reg_index, reg_value);
+ return WriteRegisterRaw(reg_index, reg_value);
}
Error
{
return 0;
}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_mips64::GetReadRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value)
+{
+ return NativeProcessLinux::OperationUP(new ReadRegOperation(m_thread.GetID(), offset, value));
+}
+
+NativeProcessLinux::OperationUP
+NativeRegisterContextLinux_mips64::GetWriteRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ const RegisterValue &value)
+{
+ return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value));
+}
+
+#endif // defined (__mips__)
//
//===----------------------------------------------------------------------===//
+#if defined (__mips__)
#ifndef lldb_NativeRegisterContextLinux_mips64_h
#define lldb_NativeRegisterContextLinux_mips64_h
-#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h"
+#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
#include "Plugins/Process/Utility/RegisterContext_mips64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
k_num_gp_reg_mips64,
};
- class NativeRegisterContextLinux_mips64 : public NativeRegisterContextRegisterInfo
+ class NativeRegisterContextLinux_mips64 : public NativeRegisterContextLinux
{
public:
- NativeRegisterContextLinux_mips64 (NativeThreadProtocol &native_thread,
- uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p);
+ NativeRegisterContextLinux_mips64 (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
uint32_t
GetRegisterSetCount () const override;
uint32_t
NumSupportedHardwareWatchpoints () override;
- private:
-
- lldb_private::Error
- WriteRegister(const uint32_t reg, const RegisterValue &value);
-
- lldb_private::Error
- ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value);
+ protected:
+ NativeProcessLinux::OperationUP
+ GetReadRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value) override;
+
+ NativeProcessLinux::OperationUP
+ GetWriteRegisterValueOperation(uint32_t offset,
+ const char* reg_name,
+ const RegisterValue &value) override;
};
} // namespace process_linux
#endif // #ifndef lldb_NativeRegisterContextLinux_mips64_h
+#endif // defined (__mips__)
//
//===----------------------------------------------------------------------===//
+#if defined(__i386__) || defined(__x86_64__)
+
#include "NativeRegisterContextLinux_x86_64.h"
#include "lldb/Core/Log.h"
-#include "lldb/lldb-private-forward.h"
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/RegisterValue.h"
-#include "lldb/Host/common/NativeProcessProtocol.h"
-#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "Plugins/Process/Linux/NativeProcessLinux.h"
+#include "lldb/Host/HostInfo.h"
+
+#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
using namespace lldb_private;
using namespace lldb_private::process_linux;
#define NT_X86_XSTATE 0x202
#endif
+NativeRegisterContextLinux*
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx)
+{
+ return new NativeRegisterContextLinux_x86_64(target_arch, native_thread, concrete_frame_idx);
+}
+
// ----------------------------------------------------------------------------
// NativeRegisterContextLinux_x86_64 members.
// ----------------------------------------------------------------------------
-NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p) :
- NativeRegisterContextRegisterInfo (native_thread, concrete_frame_idx, reg_info_interface_p),
+static RegisterInfoInterface*
+CreateRegisterInfoInterface(const ArchSpec& target_arch)
+{
+ if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
+ {
+ // 32-bit hosts run with a RegisterContextLinux_i386 context.
+ return new RegisterContextLinux_i386(target_arch);
+ }
+ else
+ {
+ assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+ "Register setting path assumes this is a 64-bit host");
+ // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
+ return new RegisterContextLinux_x86_64 (target_arch);
+ }
+}
+
+NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx) :
+ NativeRegisterContextLinux (native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)),
m_fpr_type (eFPRTypeNotValid),
m_fpr (),
m_iovec (),
m_gpr_x86_64 ()
{
// Set up data about ranges of valid registers.
- switch (reg_info_interface_p->GetTargetArchitecture ().GetMachine ())
+ switch (target_arch.GetMachine ())
{
case llvm::Triple::x86:
m_reg_info.num_registers = k_num_registers_i386;
}
Error
-NativeRegisterContextLinux_x86_64::ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value)
-{
- Error error;
- const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index);
- if (!reg_info)
- {
- error.SetErrorStringWithFormat ("register %" PRIu32 " not found", reg_index);
- return error;
- }
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->ReadRegisterValue(m_thread.GetID(),
- reg_info->byte_offset,
- reg_info->name,
- reg_info->byte_size,
- reg_value);
-}
-
-Error
NativeRegisterContextLinux_x86_64::ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value)
{
Error error;
if (IsFPR(reg, GetFPRType()))
{
- if (!ReadFPR())
- {
- error.SetErrorString ("failed to read floating point register");
+ error = ReadFPR();
+ if (error.Fail())
return error;
- }
}
else
{
}
Error
-NativeRegisterContextLinux_x86_64::WriteRegister(const uint32_t reg,
- const RegisterValue &value)
-{
- Error error;
-
- uint32_t reg_to_write = reg;
- RegisterValue value_to_write = value;
-
- // Check if this is a subregister of a full register.
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
- if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
- {
- RegisterValue full_value;
- uint32_t full_reg = reg_info->invalidate_regs[0];
- const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
-
- // Read the full register.
- error = ReadRegister(full_reg_info, full_value);
- if (error.Fail ())
- return error;
-
- lldb::ByteOrder byte_order = GetByteOrder();
- uint8_t dst[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the full register.
- const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
- dst,
- sizeof(dst),
- byte_order,
- error);
- if (error.Success() && dest_size)
- {
- uint8_t src[RegisterValue::kMaxRegisterByteSize];
-
- // Get the bytes for the source data.
- const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
- if (error.Success() && src_size && (src_size < dest_size))
- {
- // Copy the src bytes to the destination.
- memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
- // Set this full register as the value to write.
- value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
- value_to_write.SetType(full_reg_info);
- reg_to_write = full_reg;
- }
- }
- }
-
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- {
- error.SetErrorString ("NativeProcessProtocol is NULL");
- return error;
- }
-
- const RegisterInfo *const register_to_write_info_p = GetRegisterInfoAtIndex (reg_to_write);
- assert (register_to_write_info_p && "register to write does not have valid RegisterInfo");
- if (!register_to_write_info_p)
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s failed to get RegisterInfo for write register index %" PRIu32, __FUNCTION__, reg_to_write);
- return error;
- }
-
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
- return process_p->WriteRegisterValue(m_thread.GetID(),
- register_to_write_info_p->byte_offset,
- register_to_write_info_p->name,
- value_to_write);
-}
-
-Error
NativeRegisterContextLinux_x86_64::WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value)
{
assert (reg_info && "reg_info is null");
return Error ("no lldb regnum for %s", reg_info && reg_info->name ? reg_info->name : "<unknown register>");
if (IsGPR(reg_index))
- return WriteRegister(reg_index, reg_value);
+ return WriteRegisterRaw(reg_index, reg_value);
if (IsFPR(reg_index, GetFPRType()))
{
}
}
- if (WriteFPR())
+ Error error = WriteFPR();
+ if (error.Fail())
+ return error;
+
+ if (IsAVX(reg_index))
{
- if (IsAVX(reg_index))
- {
- if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
- return Error ("CopyYMMtoXSTATE() failed");
- }
- return Error ();
+ if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))
+ return Error ("CopyYMMtoXSTATE() failed");
}
+ return Error ();
}
return Error ("failed - register wasn't recognized to be a GPR or an FPR, write strategy unknown");
}
return error;
}
- if (!ReadGPR ())
- {
- error.SetErrorString ("ReadGPR() failed");
+ error = ReadGPR();
+ if (error.Fail())
return error;
- }
- if (!ReadFPR ())
- {
- error.SetErrorString ("ReadFPR() failed");
+ error = ReadFPR();
+ if (error.Fail())
return error;
- }
uint8_t *dst = data_sp->GetBytes ();
if (dst == nullptr)
}
::memcpy (&m_gpr_x86_64, src, GetRegisterInfoInterface ().GetGPRSize ());
- if (!WriteGPR ())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteGPR() failed", __FUNCTION__);
+ error = WriteGPR();
+ if (error.Fail())
return error;
- }
src += GetRegisterInfoInterface ().GetGPRSize ();
if (GetFPRType () == eFPRTypeFXSAVE)
else if (GetFPRType () == eFPRTypeXSAVE)
::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
- if (!WriteFPR ())
- {
- error.SetErrorStringWithFormat ("NativeRegisterContextLinux_x86_64::%s WriteFPR() failed", __FUNCTION__);
+ error = WriteFPR();
+ if (error.Fail())
return error;
- }
if (GetFPRType() == eFPRTypeXSAVE)
{
return (set_index < num_sets);
}
-lldb::ByteOrder
-NativeRegisterContextLinux_x86_64::GetByteOrder() const
-{
- // Get the target process whose privileged thread was used for the register read.
- lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
-
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return byte_order;
-
- if (!process_sp->GetByteOrder (byte_order))
- {
- // FIXME log here
- }
-
- return byte_order;
-}
-
bool
NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const
{
// Try and see if AVX register retrieval works.
m_fpr_type = eFPRTypeXSAVE;
- if (!const_cast<NativeRegisterContextLinux_x86_64*> (this)->ReadFPR ())
+ if (const_cast<NativeRegisterContextLinux_x86_64*>(this)->ReadFPR().Fail())
{
// Fall back to general floating point with no AVX support.
m_fpr_type = eFPRTypeFXSAVE;
return generic_fpr;
}
-bool
+Error
NativeRegisterContextLinux_x86_64::WriteFPR()
{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
- if (GetFPRType() == eFPRTypeFXSAVE)
- return process_p->WriteFPR (m_thread.GetID (), &m_fpr.xstate.fxsave, sizeof (m_fpr.xstate.fxsave)).Success();
-
- if (GetFPRType() == eFPRTypeXSAVE)
- return process_p->WriteRegisterSet (m_thread.GetID (), &m_iovec, sizeof (m_fpr.xstate.xsave), NT_X86_XSTATE).Success();
- return false;
+ const FPRType fpr_type = GetFPRType ();
+ switch (fpr_type)
+ {
+ case FPRType::eFPRTypeFXSAVE:
+ return NativeRegisterContextLinux::WriteFPR();
+ case FPRType::eFPRTypeXSAVE:
+ return WriteRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ default:
+ return Error("Unrecognized FPR type");
+ }
}
bool
return false; // unsupported or invalid byte order
}
-bool
-NativeRegisterContextLinux_x86_64::ReadFPR ()
+void*
+NativeRegisterContextLinux_x86_64::GetFPRBuffer()
{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
const FPRType fpr_type = GetFPRType ();
switch (fpr_type)
{
case FPRType::eFPRTypeFXSAVE:
- return process_p->ReadFPR (m_thread.GetID (), &m_fpr.xstate.fxsave, sizeof (m_fpr.xstate.fxsave)).Success();
-
+ return &m_fpr.xstate.fxsave;
case FPRType::eFPRTypeXSAVE:
- return process_p->ReadRegisterSet (m_thread.GetID (), &m_iovec, sizeof (m_fpr.xstate.xsave), NT_X86_XSTATE).Success();
-
+ return &m_iovec;
default:
- return false;
+ return nullptr;
}
}
-bool
-NativeRegisterContextLinux_x86_64::ReadGPR()
+size_t
+NativeRegisterContextLinux_x86_64::GetFPRSize()
{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
- return process_p->ReadGPR (m_thread.GetID (), &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ()).Success();
+ const FPRType fpr_type = GetFPRType ();
+ switch (fpr_type)
+ {
+ case FPRType::eFPRTypeFXSAVE:
+ return sizeof(m_fpr.xstate.fxsave);
+ case FPRType::eFPRTypeXSAVE:
+ return sizeof(m_iovec);
+ default:
+ return 0;
+ }
}
-bool
-NativeRegisterContextLinux_x86_64::WriteGPR()
+Error
+NativeRegisterContextLinux_x86_64::ReadFPR ()
{
- NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
- if (!process_sp)
- return false;
- NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
-
- return process_p->WriteGPR (m_thread.GetID (), &m_gpr_x86_64, GetRegisterInfoInterface ().GetGPRSize ()).Success();
+ const FPRType fpr_type = GetFPRType ();
+ switch (fpr_type)
+ {
+ case FPRType::eFPRTypeFXSAVE:
+ return NativeRegisterContextLinux::ReadFPR();
+ case FPRType::eFPRTypeXSAVE:
+ return ReadRegisterSet(&m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+ default:
+ return Error("Unrecognized FPR type");
+ }
}
Error
control_bits |= enable_bit | rw_bits | size_bits;
- error = WriteRegister(m_reg_info.first_dr + wp_index, RegisterValue(addr));
+ error = WriteRegisterRaw(m_reg_info.first_dr + wp_index, RegisterValue(addr));
if (error.Fail()) return error;
- error = WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits));
+ error = WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
if (error.Fail()) return error;
error.Clear();
if (error.Fail()) return false;
uint64_t bit_mask = 1 << wp_index;
uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegister(m_reg_info.first_dr + 6, RegisterValue(status_bits));
+ error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
if (error.Fail()) return false;
// for watchpoints 0, 1, 2, or 3, respectively,
if (error.Fail()) return false;
bit_mask = (0x3 << (2 * wp_index)) | (0xF << (16 + 4 * wp_index));
uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits)).Success();
+ return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits)).Success();
}
Error
if (error.Fail()) return error;
uint64_t bit_mask = 0xF;
uint64_t status_bits = reg_value.GetAsUInt64() & ~bit_mask;
- error = WriteRegister(m_reg_info.first_dr + 6, RegisterValue(status_bits));
+ error = WriteRegisterRaw(m_reg_info.first_dr + 6, RegisterValue(status_bits));
if (error.Fail()) return error;
// clear bits {0-7,16-31} of the debug control register (DR7)
if (error.Fail()) return error;
bit_mask = 0xFF | (0xFFFF << 16);
uint64_t control_bits = reg_value.GetAsUInt64() & ~bit_mask;
- return WriteRegister(m_reg_info.first_dr + 7, RegisterValue(control_bits));
+ return WriteRegisterRaw(m_reg_info.first_dr + 7, RegisterValue(control_bits));
}
uint32_t
// Available debug address registers: dr0, dr1, dr2, dr3
return 4;
}
+
+#endif // defined(__i386__) || defined(__x86_64__)
//
//===----------------------------------------------------------------------===//
+#if defined(__i386__) || defined(__x86_64__)
#ifndef lldb_NativeRegisterContextLinux_x86_64_h
#define lldb_NativeRegisterContextLinux_x86_64_h
-#include "lldb/Host/common/NativeRegisterContextRegisterInfo.h"
+#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
class NativeProcessLinux;
- class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextRegisterInfo
+ class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextLinux
{
public:
- NativeRegisterContextLinux_x86_64 (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p);
+ NativeRegisterContextLinux_x86_64 (const ArchSpec& target_arch,
+ NativeThreadProtocol &native_thread,
+ uint32_t concrete_frame_idx);
uint32_t
GetRegisterSetCount () const override;
uint32_t
NumSupportedHardwareWatchpoints() override;
+ protected:
+ void*
+ GetGPRBuffer() override { return &m_gpr_x86_64; }
+
+ void*
+ GetFPRBuffer() override;
+
+ size_t
+ GetFPRSize() override;
+
+ Error
+ ReadFPR() override;
+
+ Error
+ WriteFPR() override;
+
private:
// Private member types.
uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64];
// Private member methods.
- Error
- WriteRegister(const uint32_t reg, const RegisterValue &value);
-
bool IsRegisterSetAvailable (uint32_t set_index) const;
- lldb::ByteOrder
- GetByteOrder() const;
-
bool
IsGPR(uint32_t reg_index) const;
IsFPR(uint32_t reg_index) const;
bool
- WriteFPR();
-
- bool IsFPR(uint32_t reg_index, FPRType fpr_type) const;
+ IsFPR(uint32_t reg_index, FPRType fpr_type) const;
bool
CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order);
bool
IsAVX (uint32_t reg_index) const;
-
- bool
- ReadFPR ();
-
- Error
- ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value);
-
- bool
- ReadGPR();
-
- bool
- WriteGPR();
};
} // namespace process_linux
#endif // #ifndef lldb_NativeRegisterContextLinux_x86_64_h
+#endif // defined(__i386__) || defined(__x86_64__)
#include "lldb/Core/Log.h"
#include "lldb/Core/State.h"
-#include "lldb/Host/Host.h"
-#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostNativeThread.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/lldb-enumerations.h"
#include "Plugins/Process/POSIX/CrashReason.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
-#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
-#include "Plugins/Process/Utility/RegisterInfoInterface.h"
-
#include <sys/syscall.h>
// Try to define a macro to encapsulate the tgkill syscall
#define tgkill(pid, tid, sig) \
if (m_reg_context_sp)
return m_reg_context_sp;
- // First select the appropriate RegisterInfoInterface.
- RegisterInfoInterface *reg_interface = nullptr;
NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
if (!m_process_sp)
return NativeRegisterContextSP ();
if (!m_process_sp->GetArchitecture (target_arch))
return NativeRegisterContextSP ();
- switch (target_arch.GetTriple().getOS())
- {
- case llvm::Triple::Linux:
- switch (target_arch.GetMachine())
- {
- case llvm::Triple::aarch64:
- assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8) && "Register setting path assumes this is a 64-bit host");
- reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm64(target_arch));
- break;
- case llvm::Triple::arm:
- assert(HostInfo::GetArchitecture ().GetAddressByteSize() == 4);
- reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_arm(target_arch));
- break;
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- if (HostInfo::GetArchitecture().GetAddressByteSize() == 4)
- {
- // 32-bit hosts run with a RegisterContextLinux_i386 context.
- reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
- }
- else
- {
- assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
- "Register setting path assumes this is a 64-bit host");
- // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
- reg_interface = static_cast<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (target_arch));
- }
- break;
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- assert((HostInfo::GetArchitecture ().GetAddressByteSize() == 8)
- && "Register setting path assumes this is a 64-bit host");
- reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_mips64 (target_arch));
- break;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- assert(reg_interface && "OS or CPU not supported!");
- if (!reg_interface)
- return NativeRegisterContextSP ();
-
- // Now create the register context.
- switch (target_arch.GetMachine())
- {
-#if 0
- case llvm::Triple::mips64:
- {
- RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
- m_posix_thread = reg_ctx;
- m_reg_context_sp.reset(reg_ctx);
- break;
- }
-#endif
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- {
- const uint32_t concrete_frame_idx = 0;
- m_reg_context_sp.reset (new NativeRegisterContextLinux_mips64 (*this, concrete_frame_idx, reg_interface));
- break;
- }
- case llvm::Triple::aarch64:
- {
- const uint32_t concrete_frame_idx = 0;
- m_reg_context_sp.reset (new NativeRegisterContextLinux_arm64(*this, concrete_frame_idx, reg_interface));
- break;
- }
- case llvm::Triple::arm:
- {
- const uint32_t concrete_frame_idx = 0;
- m_reg_context_sp.reset (new NativeRegisterContextLinux_arm(*this, concrete_frame_idx, reg_interface));
- break;
- }
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- {
- const uint32_t concrete_frame_idx = 0;
- m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface));
- break;
- }
- default:
- break;
- }
+ const uint32_t concrete_frame_idx = 0;
+ m_reg_context_sp.reset (NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(target_arch,
+ *this,
+ concrete_frame_idx));
return m_reg_context_sp;
}
#ifndef NT_FPREGSET
#define NT_FPREGSET NT_PRFPREG
#endif // NT_FPREGSET
-#endif // defined (__arm64__) || defined (__aarch64__)
+#elif defined (__mips__)
+typedef unsigned long elf_greg_t;
+typedef elf_greg_t elf_gregset_t[(sizeof (struct user_regs_struct) / sizeof(elf_greg_t))];
+typedef struct user_fpsimd_state elf_fpregset_t;
+#ifndef NT_FPREGSET
+ #define NT_FPREGSET NT_PRFPREG
+#endif // NT_FPREGSET
+#endif
#else // __ANDROID__
#include <sys/procfs.h>
#endif // __ANDROID__
//
//===---------------------------------------------------------------------===//
+#if defined (__mips__)
+
#include <vector>
#include <stddef.h>
return m_register_info_count;
}
+#endif
//
//===----------------------------------------------------------------------===//
+#if defined (__mips__)
+
#ifndef liblldb_RegisterContextLinux_mips64_H_
#define liblldb_RegisterContextLinux_mips64_H_
};
#endif
+
+#endif