forked from OSchip/llvm-project
Make the aarch64 lldb-server capable of debugging arm32 applications
Differential revision: http://reviews.llvm.org/D15533 llvm-svn: 257322
This commit is contained in:
parent
625e51d7a5
commit
e85e6021f0
|
@ -409,13 +409,13 @@ HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_6
|
||||||
arch_32.SetTriple(triple);
|
arch_32.SetTriple(triple);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case llvm::Triple::aarch64:
|
||||||
case llvm::Triple::ppc64:
|
case llvm::Triple::ppc64:
|
||||||
case llvm::Triple::x86_64:
|
case llvm::Triple::x86_64:
|
||||||
arch_64.SetTriple(triple);
|
arch_64.SetTriple(triple);
|
||||||
arch_32.SetTriple(triple.get32BitArchVariant());
|
arch_32.SetTriple(triple.get32BitArchVariant());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case llvm::Triple::aarch64:
|
|
||||||
case llvm::Triple::mips64:
|
case llvm::Triple::mips64:
|
||||||
case llvm::Triple::mips64el:
|
case llvm::Triple::mips64el:
|
||||||
case llvm::Triple::sparcv9:
|
case llvm::Triple::sparcv9:
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#if defined(__arm__)
|
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
|
||||||
|
|
||||||
#include "NativeRegisterContextLinux_arm.h"
|
#include "NativeRegisterContextLinux_arm.h"
|
||||||
|
|
||||||
|
@ -16,8 +16,12 @@
|
||||||
#include "lldb/Core/Log.h"
|
#include "lldb/Core/Log.h"
|
||||||
#include "lldb/Core/RegisterValue.h"
|
#include "lldb/Core/RegisterValue.h"
|
||||||
|
|
||||||
|
#include "Plugins/Process/Linux/Procfs.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
|
||||||
|
|
||||||
|
#include <elf.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
|
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
|
||||||
|
|
||||||
#ifndef PTRACE_GETVFPREGS
|
#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 }
|
{ "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(__arm__)
|
||||||
|
|
||||||
NativeRegisterContextLinux*
|
NativeRegisterContextLinux*
|
||||||
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
|
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
|
||||||
NativeThreadProtocol &native_thread,
|
NativeThreadProtocol &native_thread,
|
||||||
|
@ -177,6 +183,8 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec&
|
||||||
return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
|
return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // defined(__arm__)
|
||||||
|
|
||||||
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
|
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
|
||||||
NativeThreadProtocol &native_thread,
|
NativeThreadProtocol &native_thread,
|
||||||
uint32_t concrete_frame_idx) :
|
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;
|
ctrl_buf = &m_hwp_regs[hwb_index].control;
|
||||||
|
|
||||||
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
|
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));
|
addr_buf, sizeof(unsigned int));
|
||||||
|
|
||||||
if (error.Fail())
|
if (error.Fail())
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
|
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));
|
ctrl_buf, sizeof(unsigned int));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -935,14 +943,14 @@ NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_inde
|
||||||
ctrl_buf = &m_hwp_regs[hwb_index].control;
|
ctrl_buf = &m_hwp_regs[hwb_index].control;
|
||||||
|
|
||||||
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
|
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));
|
addr_buf, sizeof(unsigned int));
|
||||||
|
|
||||||
if (error.Fail())
|
if (error.Fail())
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
|
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));
|
ctrl_buf, sizeof(unsigned int));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -956,12 +964,34 @@ NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info)
|
||||||
return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
|
return reg_info->byte_offset - GetRegisterInfoAtIndex(m_reg_info.first_fpr)->byte_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
Error
|
||||||
NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
|
NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
|
||||||
const char* reg_name,
|
const char* reg_name,
|
||||||
const RegisterValue &value)
|
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
|
// "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
|
// 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.
|
// performance overhead is negligible in comparision to processing time in lldb-server.
|
||||||
|
@ -994,24 +1024,68 @@ NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
|
||||||
return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm));
|
return DoWriteGPR(m_gpr_arm, sizeof(m_gpr_arm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
Error
|
||||||
NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size)
|
NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
|
#ifdef __arm__
|
||||||
return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS,
|
return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS,
|
||||||
m_thread.GetID(),
|
m_thread.GetID(),
|
||||||
nullptr,
|
nullptr,
|
||||||
buf,
|
buf,
|
||||||
buf_size);
|
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
|
Error
|
||||||
NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size)
|
NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
|
#ifdef __arm__
|
||||||
return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS,
|
return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS,
|
||||||
m_thread.GetID(),
|
m_thread.GetID(),
|
||||||
nullptr,
|
nullptr,
|
||||||
buf,
|
buf,
|
||||||
buf_size);
|
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__)
|
||||||
|
|
|
@ -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
|
#ifndef lldb_NativeRegisterContextLinux_arm_h
|
||||||
#define lldb_NativeRegisterContextLinux_arm_h
|
#define lldb_NativeRegisterContextLinux_arm_h
|
||||||
|
@ -90,11 +90,23 @@ namespace process_linux {
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Error
|
||||||
|
DoReadRegisterValue(uint32_t offset,
|
||||||
|
const char* reg_name,
|
||||||
|
uint32_t size,
|
||||||
|
RegisterValue &value) override;
|
||||||
|
|
||||||
Error
|
Error
|
||||||
DoWriteRegisterValue(uint32_t offset,
|
DoWriteRegisterValue(uint32_t offset,
|
||||||
const char* reg_name,
|
const char* reg_name,
|
||||||
const RegisterValue &value) override;
|
const RegisterValue &value) override;
|
||||||
|
|
||||||
|
Error
|
||||||
|
DoReadGPR(void *buf, size_t buf_size) override;
|
||||||
|
|
||||||
|
Error
|
||||||
|
DoWriteGPR(void *buf, size_t buf_size) override;
|
||||||
|
|
||||||
Error
|
Error
|
||||||
DoReadFPR(void *buf, size_t buf_size) override;
|
DoReadFPR(void *buf, size_t buf_size) override;
|
||||||
|
|
||||||
|
@ -182,4 +194,4 @@ namespace process_linux {
|
||||||
|
|
||||||
#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h
|
#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h
|
||||||
|
|
||||||
#endif // defined(__arm__)
|
#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#if defined (__arm64__) || defined (__aarch64__)
|
#if defined (__arm64__) || defined (__aarch64__)
|
||||||
|
|
||||||
|
#include "NativeRegisterContextLinux_arm.h"
|
||||||
#include "NativeRegisterContextLinux_arm64.h"
|
#include "NativeRegisterContextLinux_arm64.h"
|
||||||
|
|
||||||
// C Includes
|
// C Includes
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
|
|
||||||
#include "Plugins/Process/Linux/NativeProcessLinux.h"
|
#include "Plugins/Process/Linux/NativeProcessLinux.h"
|
||||||
#include "Plugins/Process/Linux/Procfs.h"
|
#include "Plugins/Process/Linux/Procfs.h"
|
||||||
|
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
|
||||||
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
|
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
|
||||||
|
|
||||||
// System includes - They have to be included after framework includes because they define some
|
// 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,
|
NativeThreadProtocol &native_thread,
|
||||||
uint32_t concrete_frame_idx)
|
uint32_t 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);
|
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,
|
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
|
||||||
|
|
Loading…
Reference in New Issue