diff options
author | Muhammad Omair Javaid <omair.javaid@linaro.org> | 2021-03-30 15:39:32 +0500 |
---|---|---|
committer | Muhammad Omair Javaid <omair.javaid@linaro.org> | 2021-03-31 04:38:36 +0500 |
commit | d6d3d21cd1cb1567eaf7ff8c0867b07227a19d99 (patch) | |
tree | 6495687f4c3bf7683a06fca15aed243aed8115b3 /lldb/source/Plugins/Process/Linux | |
parent | 144ec1c38ef1d3a6d37dadf7240ef5f04c10daae (diff) | |
download | llvm-d6d3d21cd1cb1567eaf7ff8c0867b07227a19d99.zip llvm-d6d3d21cd1cb1567eaf7ff8c0867b07227a19d99.tar.gz llvm-d6d3d21cd1cb1567eaf7ff8c0867b07227a19d99.tar.bz2 |
[LLDB] Add support for Arm64/Linux dynamic register sets
This is patch adds support for adding dynamic register sets for
AArch64 dynamic features in LLDB. AArch64 has optional features like
SVE, Pointer Authentication and MTE which means LLDB needs to decide
at run time which registers it needs to pull in for the current
executable based on underlying support for a certain feature.
This patch makes necessary adjustments to make way for dynamic
register infos and dynamic register sets.
Reviewed By: labath
Differential Revision: https://reviews.llvm.org/D96458
Diffstat (limited to 'lldb/source/Plugins/Process/Linux')
-rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp | 60 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h | 5 |
2 files changed, 44 insertions, 21 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 5c025c0e..09cf72c 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -46,18 +46,37 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( case llvm::Triple::arm: return std::make_unique<NativeRegisterContextLinux_arm>(target_arch, native_thread); - case llvm::Triple::aarch64: - return std::make_unique<NativeRegisterContextLinux_arm64>(target_arch, - native_thread); + case llvm::Triple::aarch64: { + // Configure register sets supported by this AArch64 target. + // Read SVE header to check for SVE support. + struct user_sve_header sve_header; + struct iovec ioVec; + ioVec.iov_base = &sve_header; + ioVec.iov_len = sizeof(sve_header); + unsigned int regset = NT_ARM_SVE; + + Flags opt_regsets; + if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, + native_thread.GetID(), ®set, + &ioVec, sizeof(sve_header)) + .Success()) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE); + + auto register_info_up = + std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets); + return std::make_unique<NativeRegisterContextLinux_arm64>( + target_arch, native_thread, std::move(register_info_up)); + } default: llvm_unreachable("have no register context for architecture"); } } NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( - const ArchSpec &target_arch, NativeThreadProtocol &native_thread) - : NativeRegisterContextRegisterInfo( - native_thread, new RegisterInfoPOSIX_arm64(target_arch)) { + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up) + : NativeRegisterContextRegisterInfo(native_thread, + register_info_up.release()) { ::memset(&m_fpr, 0, sizeof(m_fpr)); ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64)); ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs)); @@ -75,8 +94,10 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( m_sve_buffer_is_valid = false; m_sve_header_is_valid = false; - // SVE is not enabled until we query user_sve_header - m_sve_state = SVEState::Unknown; + if (GetRegisterInfo().IsSVEEnabled()) + m_sve_state = SVEState::Unknown; + else + m_sve_state = SVEState::Disabled; } RegisterInfoPOSIX_arm64 & @@ -451,10 +472,7 @@ bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const { } bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const { - if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) == - RegisterInfoPOSIX_arm64::SVERegSet) - return true; - return false; + return GetRegisterInfo().IsSVEReg(reg); } llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { @@ -676,23 +694,27 @@ Status NativeRegisterContextLinux_arm64::WriteAllSVE() { } void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { - // Read SVE configuration data and configure register infos. + // ConfigureRegisterContext gets called from InvalidateAllRegisters + // on every stop and configures SVE vector length. + // If m_sve_state is set to SVEState::Disabled on first stop, code below will + // be deemed non operational for the lifetime of current process. if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) { Status error = ReadSVEHeader(); - if (!error.Success() && m_sve_state == SVEState::Unknown) { - m_sve_state = SVEState::Disabled; - GetRegisterInfo().ConfigureVectorRegisterInfos( - RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64); - } else { + if (error.Success()) { + // If SVE is enabled thread can switch between SVEState::FPSIMD and + // SVEState::Full on every stop. if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD) m_sve_state = SVEState::FPSIMD; else if ((m_sve_header.flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE) m_sve_state = SVEState::Full; + // On every stop we configure SVE vector length by calling + // ConfigureVectorLength regardless of current SVEState of this thread. uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE; if (sve_vl_valid(m_sve_header.vl)) vq = sve_vq_from_vl(m_sve_header.vl); - GetRegisterInfo().ConfigureVectorRegisterInfos(vq); + + GetRegisterInfo().ConfigureVectorLength(vq); m_sve_ptrace_payload.resize(SVE_PT_SIZE(vq, SVE_PT_REGS_SVE)); } } diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 47105a5..f0dd638 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -26,8 +26,9 @@ class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux, public NativeRegisterContextDBReg_arm64 { public: - NativeRegisterContextLinux_arm64(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread); + NativeRegisterContextLinux_arm64( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up); uint32_t GetRegisterSetCount() const override; |