summaryrefslogtreecommitdiff
path: root/source/Plugins/Process/Linux
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process/Linux')
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp88
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h16
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp16
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp10
4 files changed, 119 insertions, 11 deletions
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index 31752fed5b42..79653fc62686 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__arm__)
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
#include "NativeRegisterContextLinux_arm.h"
@@ -16,8 +16,12 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
+#include "Plugins/Process/Linux/Procfs.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
+#include <elf.h>
+#include <sys/socket.h>
+
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
#ifndef PTRACE_GETVFPREGS
@@ -169,6 +173,8 @@ g_reg_sets_arm[k_num_register_sets] =
{ "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
};
+#if defined(__arm__)
+
NativeRegisterContextLinux*
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
NativeThreadProtocol &native_thread,
@@ -177,6 +183,8 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec&
return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
}
+#endif // defined(__arm__)
+
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
NativeThreadProtocol &native_thread,
uint32_t concrete_frame_idx) :
@@ -919,14 +927,14 @@ NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_inde
ctrl_buf = &m_hwp_regs[hwb_index].control;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 1),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) -((hwb_index << 1) + 1),
addr_buf, sizeof(unsigned int));
if (error.Fail())
return error;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 2),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) -((hwb_index << 1) + 2),
ctrl_buf, sizeof(unsigned int));
}
else
@@ -935,14 +943,14 @@ NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_inde
ctrl_buf = &m_hwp_regs[hwb_index].control;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 1),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 1),
addr_buf, sizeof(unsigned int));
if (error.Fail())
return error;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 2),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 2),
ctrl_buf, sizeof(unsigned int));
}
@@ -957,11 +965,33 @@ NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info)
}
Error
+NativeRegisterContextLinux_arm::DoReadRegisterValue(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value)
+{
+ // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android devices (always return
+ // "Bad address"). To avoid using PTRACE_PEEKUSER we read out the full GPR register set instead.
+ // This approach is about 4 times slower but the performance overhead is negligible in
+ // comparision to processing time in lldb-server.
+ assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
+ if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
+ return Error("Register isn't fit into the size of the GPR area");
+
+ Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
+ if (error.Fail())
+ return error;
+
+ value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]);
+ return Error();
+}
+
+Error
NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
const char* reg_name,
const RegisterValue &value)
{
- // PTRACE_POKEUSER don't work in the aarch64 liux kernel used on android devices (always return
+ // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android devices (always return
// "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR register set, modify
// the requested register and write it back. This approach is about 4 times slower but the
// performance overhead is negligible in comparision to processing time in lldb-server.
@@ -995,23 +1025,67 @@ NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
}
Error
+NativeRegisterContextLinux_arm::DoReadGPR(void *buf, size_t buf_size)
+{
+#ifdef __arm__
+ return NativeRegisterContextLinux::DoReadGPR(buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return ReadRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
+#endif // __arm__
+}
+
+Error
+NativeRegisterContextLinux_arm::DoWriteGPR(void *buf, size_t buf_size)
+{
+#ifdef __arm__
+ return NativeRegisterContextLinux::DoWriteGPR(buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return WriteRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
+#endif // __arm__
+}
+
+Error
NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size)
{
+#ifdef __arm__
return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS,
m_thread.GetID(),
nullptr,
buf,
buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return ReadRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
+#endif // __arm__
}
Error
NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size)
{
+#ifdef __arm__
return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS,
m_thread.GetID(),
nullptr,
buf,
buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return WriteRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
+#endif // __arm__
}
-#endif // defined(__arm__)
+#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 611b36ad4db1..349564970428 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__arm__) // arm register context only needed on arm devices
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
#ifndef lldb_NativeRegisterContextLinux_arm_h
#define lldb_NativeRegisterContextLinux_arm_h
@@ -91,11 +91,23 @@ namespace process_linux {
protected:
Error
+ DoReadRegisterValue(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value) override;
+
+ Error
DoWriteRegisterValue(uint32_t offset,
const char* reg_name,
const RegisterValue &value) override;
Error
+ DoReadGPR(void *buf, size_t buf_size) override;
+
+ Error
+ DoWriteGPR(void *buf, size_t buf_size) override;
+
+ Error
DoReadFPR(void *buf, size_t buf_size) override;
Error
@@ -182,4 +194,4 @@ namespace process_linux {
#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h
-#endif // defined(__arm__)
+#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index e4d26fc640f3..22cdbb40d15c 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -9,6 +9,7 @@
#if defined (__arm64__) || defined (__aarch64__)
+#include "NativeRegisterContextLinux_arm.h"
#include "NativeRegisterContextLinux_arm64.h"
// C Includes
@@ -23,6 +24,7 @@
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "Plugins/Process/Linux/Procfs.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
// System includes - They have to be included after framework includes because they define some
@@ -142,7 +144,19 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec&
NativeThreadProtocol &native_thread,
uint32_t concrete_frame_idx)
{
- return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx);
+ Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS);
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::arm:
+ return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
+ case llvm::Triple::aarch64:
+ return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx);
+ default:
+ if (log)
+ log->Printf("NativeRegisterContextLinux::%s() have no register context for architecture: %s\n", __FUNCTION__,
+ target_arch.GetTriple().getArchName().str().c_str());
+ return nullptr;
+ }
}
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
index 3cfeaf5546bc..54d6f721c9d8 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
@@ -1388,7 +1388,15 @@ NativeRegisterContextLinux_mips64::DoReadRegisterValue(uint32_t offset,
{
lldb_private::ArchSpec arch;
if (m_thread.GetProcess()->GetArchitecture(arch))
- value.SetBytes((void *)(((unsigned char *)&regs) + offset + 4 * (arch.GetMachine() == llvm::Triple::mips)), arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8, arch.GetByteOrder());
+ {
+ void* target_address = ((uint8_t*)&regs) + offset + 4 * (arch.GetMachine() == llvm::Triple::mips);
+ uint32_t target_size;
+ if ((::strcmp(reg_name, "sr") == 0) || (::strcmp(reg_name, "cause") == 0) || (::strcmp(reg_name, "config5") == 0))
+ target_size = 4;
+ else
+ target_size = arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8;
+ value.SetBytes(target_address, target_size, arch.GetByteOrder());
+ }
else
error.SetErrorString("failed to get architecture");
}