diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp index 0f4324f83dd6..f7ba755b5bab 100644 --- a/lldb/source/Host/common/HostInfoBase.cpp +++ b/lldb/source/Host/common/HostInfoBase.cpp @@ -409,13 +409,13 @@ HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_6 arch_32.SetTriple(triple); break; + case llvm::Triple::aarch64: case llvm::Triple::ppc64: case llvm::Triple::x86_64: arch_64.SetTriple(triple); arch_32.SetTriple(triple.get32BitArchVariant()); break; - case llvm::Triple::aarch64: case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::sparcv9: diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp index 31752fed5b42..79653fc62686 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp +++ b/lldb/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 +#include + #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)); } @@ -956,12 +964,34 @@ NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info) 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 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. @@ -994,24 +1024,68 @@ NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset, 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 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/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h index 611b36ad4db1..349564970428 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h +++ b/lldb/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 @@ -90,11 +90,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; @@ -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/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index e4d26fc640f3..22cdbb40d15c 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/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,