llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lldb Author: David Spickett (DavidSpickett) <details> <summary>Changes</summary> This change adds initial support for managing the Permission Overlay Extension (POE). This extension allows userspace programs to change memory permissions without making a sycall. This is used to implement Linux's memory protection keys (https://docs.kernel.org/core-api/protection-keys.html) on AArch64. Overview of POE: * Page table entries have a set of permissions. To change these, a program would have to use a syscall which adds overhead. * 3 bits of the page table entry are used for a protection key 0-7. * POE adds a new register "por" which stores 4-bit sets of permissions. * The protection key is an index into this por register. * Permissions in POR are applied on top of the page table permissions, but may only remove permissions. For example, if you overlay read/execute over read/write, the result is read. Since execute was not in the page table permissions. * This register can be modified without leaving userspace, making permission changes faster. To help debug this, I have made the following changes to LLDB: * Ability to read and write the por register. * Save and restore of por when running expressions. * Register field definitions to print the por permissions in a human readable form. * Recognition of memory protection key faults as a distinct type of SIGSEGV (this will apply to Linux on any architecture). There are a few more features to add around memory region information, that will be in follow up changes. --- Patch is 34.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/177145.diff 18 Files Affected: - (modified) lldb/packages/Python/lldbsuite/test/cpu_feature.py (+1) - (modified) lldb/packages/Python/lldbsuite/test/lldbtest.py (+3) - (modified) lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (+88-1) - (modified) lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h (+16) - (modified) lldb/source/Plugins/Process/Utility/LinuxSignals.cpp (+1) - (modified) lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp (+4) - (modified) lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h (+1) - (modified) lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp (+34) - (modified) lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h (+4-1) - (modified) lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp (+33) - (modified) lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h (+7) - (modified) lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp (+15) - (modified) lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h (+1) - (modified) lldb/source/Plugins/Process/elf-core/RegisterUtilities.h (+4) - (added) lldb/test/API/linux/aarch64/permission_overlay/Makefile (+3) - (added) lldb/test/API/linux/aarch64/permission_overlay/TestAArch64LinuxPOE.py (+129) - (added) lldb/test/API/linux/aarch64/permission_overlay/corefile () - (added) lldb/test/API/linux/aarch64/permission_overlay/main.c (+128) ``````````diff diff --git a/lldb/packages/Python/lldbsuite/test/cpu_feature.py b/lldb/packages/Python/lldbsuite/test/cpu_feature.py index d7668c1884e40..736d5e86399ae 100644 --- a/lldb/packages/Python/lldbsuite/test/cpu_feature.py +++ b/lldb/packages/Python/lldbsuite/test/cpu_feature.py @@ -61,6 +61,7 @@ def _is_supported_darwin(self, cmd_runner): class AArch64: FPMR = CPUFeature("fpmr") + POE = CPUFeature("poe") GCS = CPUFeature("gcs") MTE = CPUFeature("mte", "hw.optional.arm.FEAT_MTE4") MTE_STORE_ONLY = CPUFeature("mtestoreonly") diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 55b527e3a9ce6..616d7cea6b4e3 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -1405,6 +1405,9 @@ def isAArch64PAuth(self): def isAArch64FPMR(self): return self.isAArch64() and self.isSupported(cpu_feature.AArch64.FPMR) + def isAArch64POE(self): + return self.isAArch64() and self.isSupported(cpu_feature.AArch64.POE) + def isAArch64Windows(self): """Returns true if the architecture is AArch64 and platform windows.""" if self.getPlatform() == "windows": diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index 294a446686f22..41b094f1a383a 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -65,6 +65,10 @@ #define NT_ARM_FPMR 0x40e /* Floating point mode register */ #endif +#ifndef NT_ARM_POE +#define NT_ARM_POE 0x40f /* Permission Overlay registers */ +#endif + #ifndef NT_ARM_GCS #define NT_ARM_GCS 0x410 /* Guarded Control Stack control registers */ #endif @@ -77,6 +81,8 @@ #define HWCAP2_FPMR (1UL << 48) +#define HWCAP2_POE (1ULL << 63) + using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_linux; @@ -159,6 +165,8 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskFPMR); if (*auxv_at_hwcap & HWCAP_GCS) opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskGCS); + if (*auxv_at_hwcap2 & HWCAP2_POE) + opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPOE); } opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS); @@ -206,6 +214,7 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( ::memset(&m_tls_regs, 0, sizeof(m_tls_regs)); ::memset(&m_sme_pseudo_regs, 0, sizeof(m_sme_pseudo_regs)); ::memset(&m_gcs_regs, 0, sizeof(m_gcs_regs)); + ::memset(&m_poe_regs, 0, sizeof(m_poe_regs)); std::fill(m_zt_reg.begin(), m_zt_reg.end(), 0); m_mte_ctrl_reg = 0; @@ -227,6 +236,7 @@ NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64( m_zt_buffer_is_valid = false; m_fpmr_is_valid = false; m_gcs_is_valid = false; + m_poe_is_valid = false; // SME adds the tpidr2 register m_tls_size = GetRegisterInfo().IsSSVEPresent() ? sizeof(m_tls_regs) @@ -455,6 +465,14 @@ NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info, offset = reg_info->byte_offset - GetRegisterInfo().GetGCSOffset(); assert(offset < GetGCSBufferSize()); src = (uint8_t *)GetGCSBuffer() + offset; + } else if (IsPOE(reg)) { + error = ReadPOE(); + if (error.Fail()) + return error; + + offset = reg_info->byte_offset - GetRegisterInfo().GetPOEOffset(); + assert(offset < GetPOEBufferSize()); + src = (uint8_t *)GetPOEBuffer() + offset; } else return Status::FromErrorString( "failed - register wasn't recognized to be a GPR or an FPR, " @@ -690,6 +708,17 @@ Status NativeRegisterContextLinux_arm64::WriteRegister( ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); return WriteGCS(); + } else if (IsPOE(reg)) { + error = ReadPOE(); + if (error.Fail()) + return error; + + offset = reg_info->byte_offset - GetRegisterInfo().GetPOEOffset(); + assert(offset < GetPOEBufferSize()); + dst = (uint8_t *)GetPOEBuffer() + offset; + ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size); + + return WritePOE(); } return Status::FromErrorString("Failed to write register value"); @@ -706,6 +735,7 @@ enum RegisterSetType : uint32_t { SME2, // ZT only. FPMR, GCS, // Guarded Control Stack registers. + POE, // Permission Overlay registers. }; static uint8_t *AddRegisterSetType(uint8_t *dst, @@ -800,6 +830,13 @@ NativeRegisterContextLinux_arm64::CacheAllRegisters(uint32_t &cached_size) { return error; } + if (GetRegisterInfo().IsPOEPresent()) { + cached_size += sizeof(RegisterSetType) + GetPOEBufferSize(); + error = ReadPOE(); + if (error.Fail()) + return error; + } + // tpidr is always present but tpidr2 depends on SME. cached_size += sizeof(RegisterSetType) + GetTLSBufferSize(); error = ReadTLS(); @@ -913,6 +950,11 @@ Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues( GetGCSBufferSize()); } + if (GetRegisterInfo().IsPOEPresent()) { + dst = AddSavedRegisters(dst, RegisterSetType::POE, GetPOEBuffer(), + GetPOEBufferSize()); + } + dst = AddSavedRegisters(dst, RegisterSetType::TLS, GetTLSBuffer(), GetTLSBufferSize()); @@ -1066,7 +1108,7 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( GetFPMRBuffer(), &src, GetFPMRBufferSize(), m_fpmr_is_valid, std::bind(&NativeRegisterContextLinux_arm64::WriteFPMR, this)); break; - case RegisterSetType::GCS: + case RegisterSetType::GCS: { // It is not permitted to enable GCS via ptrace. We can disable it, but // to keep things simple we will not revert any change to the // PR_SHADOW_STACK_ENABLE bit. Instead patch in the current enable bit @@ -1090,6 +1132,12 @@ Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues( break; } + case RegisterSetType::POE: + error = RestoreRegisters( + GetPOEBuffer(), &src, GetPOEBufferSize(), m_poe_is_valid, + std::bind(&NativeRegisterContextLinux_arm64::WritePOE, this)); + break; + } if (error.Fail()) return error; @@ -1140,6 +1188,10 @@ bool NativeRegisterContextLinux_arm64::IsGCS(unsigned reg) const { return GetRegisterInfo().IsGCSReg(reg); } +bool NativeRegisterContextLinux_arm64::IsPOE(unsigned reg) const { + return GetRegisterInfo().IsPOEReg(reg); +} + llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() { if (!m_refresh_hwdebug_info) { return llvm::Error::success(); @@ -1244,6 +1296,7 @@ void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() { m_zt_buffer_is_valid = false; m_fpmr_is_valid = false; m_gcs_is_valid = false; + m_poe_is_valid = false; // Update SVE and ZA registers in case there is change in configuration. ConfigureRegisterContext(); @@ -1591,6 +1644,40 @@ Status NativeRegisterContextLinux_arm64::WriteFPMR() { return WriteRegisterSet(&ioVec, GetFPMRBufferSize(), NT_ARM_FPMR); } +Status NativeRegisterContextLinux_arm64::ReadPOE() { + Status error; + + if (m_poe_is_valid) + return error; + + struct iovec ioVec; + ioVec.iov_base = GetPOEBuffer(); + ioVec.iov_len = GetPOEBufferSize(); + + error = ReadRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE); + + if (error.Success()) + m_poe_is_valid = true; + + return error; +} + +Status NativeRegisterContextLinux_arm64::WritePOE() { + Status error; + + error = ReadPOE(); + if (error.Fail()) + return error; + + struct iovec ioVec; + ioVec.iov_base = GetPOEBuffer(); + ioVec.iov_len = GetPOEBufferSize(); + + m_poe_is_valid = false; + + return WriteRegisterSet(&ioVec, GetPOEBufferSize(), NT_ARM_POE); +} + void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() { // ConfigureRegisterContext gets called from InvalidateAllRegisters // on every stop and configures SVE vector length and whether we are in diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 7ed0da8503496..cc34ef4c8f246 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -93,6 +93,7 @@ class NativeRegisterContextLinux_arm64 bool m_tls_is_valid; size_t m_tls_size; bool m_gcs_is_valid; + bool m_poe_is_valid; struct user_pt_regs m_gpr_arm64; // 64-bit general purpose registers. @@ -137,6 +138,12 @@ class NativeRegisterContextLinux_arm64 uint64_t m_fpmr_reg; + struct poe_regs { + uint64_t por_reg; + }; + + struct poe_regs m_poe_regs; + struct gcs_regs { uint64_t features_enabled; uint64_t features_locked; @@ -192,6 +199,10 @@ class NativeRegisterContextLinux_arm64 Status WriteFPMR(); + Status ReadPOE(); + + Status WritePOE(); + bool IsSVE(unsigned reg) const; bool IsSME(unsigned reg) const; bool IsPAuth(unsigned reg) const; @@ -199,6 +210,7 @@ class NativeRegisterContextLinux_arm64 bool IsTLS(unsigned reg) const; bool IsFPMR(unsigned reg) const; bool IsGCS(unsigned reg) const; + bool IsPOE(unsigned reg) const; uint64_t GetSVERegVG() { return m_sve_header.vl / 8; } @@ -226,6 +238,8 @@ class NativeRegisterContextLinux_arm64 void *GetGCSBuffer() { return &m_gcs_regs; } + void *GetPOEBuffer() { return &m_poe_regs; } + size_t GetSVEHeaderSize() { return sizeof(m_sve_header); } size_t GetPACMaskSize() { return sizeof(m_pac_mask); } @@ -250,6 +264,8 @@ class NativeRegisterContextLinux_arm64 size_t GetGCSBufferSize() { return sizeof(m_gcs_regs); } + size_t GetPOEBufferSize() { return sizeof(m_poe_regs); } + llvm::Error ReadHardwareDebugInfo() override; llvm::Error WriteHardwareDebugRegs(DREGType hwbType) override; diff --git a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp index dbbfc6a352e02..3cda0c80259de 100644 --- a/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp +++ b/lldb/source/Plugins/Process/Utility/LinuxSignals.cpp @@ -137,6 +137,7 @@ void LinuxSignals::Reset() { ADD_SIGCODE(SIGSEGV, 11, SEGV_MAPERR, 1, "address not mapped to object", SignalCodePrintOption::Address); ADD_SIGCODE(SIGSEGV, 11, SEGV_ACCERR, 2, "invalid permissions for mapped object", SignalCodePrintOption::Address); ADD_SIGCODE(SIGSEGV, 11, SEGV_BNDERR, 3, "failed address bounds checks", SignalCodePrintOption::Bounds); + ADD_SIGCODE(SIGSEGV, 11, SEGV_PKUERR, 4, "failed protection key checks", SignalCodePrintOption::Address); ADD_SIGCODE(SIGSEGV, 11, SEGV_MTEAERR, 8, "async tag check fault"); ADD_SIGCODE(SIGSEGV, 11, SEGV_MTESERR, 9, "sync tag check fault", SignalCodePrintOption::Address); ADD_SIGCODE(SIGSEGV, 11, SEGV_CPERR, 10, "control protection fault"); diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp index 0233837f99d09..ecff3bfd6c898 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp @@ -67,6 +67,10 @@ bool RegisterContextPOSIX_arm64::IsGCS(unsigned reg) const { return m_register_info_up->IsGCSReg(reg); } +bool RegisterContextPOSIX_arm64::IsPOE(unsigned reg) const { + return m_register_info_up->IsPOEReg(reg); +} + RegisterContextPOSIX_arm64::RegisterContextPOSIX_arm64( lldb_private::Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info) diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h index de46c628d836d..eba02cdd13699 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h @@ -60,6 +60,7 @@ class RegisterContextPOSIX_arm64 : public lldb_private::RegisterContext { bool IsMTE(unsigned reg) const; bool IsFPMR(unsigned reg) const; bool IsGCS(unsigned reg) const; + bool IsPOE(unsigned reg) const; bool IsSVEZ(unsigned reg) const { return m_register_info_up->IsSVEZReg(reg); } bool IsSVEP(unsigned reg) const { return m_register_info_up->IsSVEPReg(reg); } diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp index 330a24af67c4e..038bc946d1441 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp @@ -25,11 +25,45 @@ #define HWCAP2_SME (1ULL << 23) #define HWCAP2_EBF16 (1ULL << 32) #define HWCAP2_FPMR (1ULL << 48) +#define HWCAP2_POE (1ULL << 63) #define HWCAP3_MTE_STORE_ONLY (1ULL << 1) using namespace lldb_private; +Arm64RegisterFlagsDetector::Fields +Arm64RegisterFlagsDetector::DetectPORFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3) { + (void)hwcap; + (void)hwcap3; + + if (!(hwcap2 & HWCAP2_POE)) + return {}; + + static const FieldEnum por_perm_enum("por_perm_enum", + { + {0b0000, "No Access"}, + {0b0001, "Read"}, + {0b0010, "Execute"}, + {0b0011, "Read, Execute"}, + {0b0100, "Write"}, + {0b0101, "Write, Read"}, + {0b0110, "Write, Execute"}, + {0b0111, "Read, Write, Execute"}, + }); + + return { + {"Perm15", 60, 63, &por_perm_enum}, {"Perm14", 56, 59, &por_perm_enum}, + {"Perm13", 52, 55, &por_perm_enum}, {"Perm12", 48, 51, &por_perm_enum}, + {"Perm11", 44, 47, &por_perm_enum}, {"Perm10", 40, 43, &por_perm_enum}, + {"Perm9", 36, 39, &por_perm_enum}, {"Perm8", 32, 35, &por_perm_enum}, + {"Perm7", 28, 31, &por_perm_enum}, {"Perm6", 24, 27, &por_perm_enum}, + {"Perm5", 20, 23, &por_perm_enum}, {"Perm4", 16, 19, &por_perm_enum}, + {"Perm3", 12, 15, &por_perm_enum}, {"Perm2", 8, 11, &por_perm_enum}, + {"Perm1", 4, 7, &por_perm_enum}, {"Perm0", 0, 3, &por_perm_enum}, + }; +} + Arm64RegisterFlagsDetector::Fields Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3) { diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h index aec2bf9f4886f..3bd3a44f1c30d 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h @@ -69,6 +69,8 @@ class Arm64RegisterFlagsDetector { uint64_t hwcap3); static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3); + static Fields DetectPORFields(uint64_t hwcap, uint64_t hwcap2, + uint64_t hwcap3); struct RegisterEntry { RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector) @@ -78,7 +80,7 @@ class Arm64RegisterFlagsDetector { llvm::StringRef m_name; RegisterFlags m_flags; DetectorFn m_detector; - } m_registers[8] = { + } m_registers[9] = { RegisterEntry("cpsr", 4, DetectCPSRFields), RegisterEntry("fpsr", 4, DetectFPSRFields), RegisterEntry("fpcr", 4, DetectFPCRFields), @@ -87,6 +89,7 @@ class Arm64RegisterFlagsDetector { RegisterEntry("fpmr", 8, DetectFPMRFields), RegisterEntry("gcs_features_enabled", 8, DetectGCSFeatureFields), RegisterEntry("gcs_features_locked", 8, DetectGCSFeatureFields), + RegisterEntry("por", 8, DetectPORFields), }; // Becomes true once field detection has been run for all registers. diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index 3b8d6a84c964c..df1940a15ec6e 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -101,6 +101,9 @@ static lldb_private::RegisterInfo g_register_infos_gcs[] = { DEFINE_EXTENSION_REG(gcs_features_enabled), DEFINE_EXTENSION_REG(gcs_features_locked), DEFINE_EXTENSION_REG(gcspr_el0)}; +static lldb_private::RegisterInfo g_register_infos_poe[] = { + DEFINE_EXTENSION_REG(por)}; + // Number of register sets provided by this context. enum { k_num_gpr_registers = gpr_w28 - gpr_x0 + 1, @@ -114,6 +117,7 @@ enum { k_num_sme_register = 3, k_num_fpmr_register = 1, k_num_gcs_register = 3, + k_num_poe_register = 1, k_num_register_sets_default = 2, k_num_register_sets = 3 }; @@ -229,6 +233,9 @@ static const lldb_private::RegisterSet g_reg_set_fpmr_arm64 = { static const lldb_private::RegisterSet g_reg_set_gcs_arm64 = { "Guarded Control Stack Registers", "gcs", k_num_gcs_register, nullptr}; +static const lldb_private::RegisterSet g_reg_set_poe_arm64 = { + "Permission Overlay Registers", "poe", k_num_poe_register, nullptr}; + RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets) : lldb_private::RegisterInfoAndSetInterface(target_arch), @@ -284,6 +291,9 @@ RegisterInfoPOSIX_arm64::RegisterInfoPOSIX_arm64( if (m_opt_regsets.AllSet(eRegsetMaskGCS)) AddRegSetGCS(); + if (m_opt_regsets.AllSet(eRegsetMaskPOE)) + AddRegSetPOE(); + m_register_info_count = m_dynamic_reg_infos.size(); m_register_info_p = m_dynamic_reg_infos.data(); m_register_set_p = m_dynamic_reg_sets.data(); @@ -462,6 +472,21 @@ void RegisterInfoPOSIX_arm64::AddRegSetGCS() { m_dynamic_reg_sets.back().registers = m_gcs_regnum_collection.data(); } +void RegisterInfoPOSIX_arm64::AddRegSetPOE() { + uint32_t poe_regnum = m_dynamic_reg_infos.size(); + m_poe_regnum_collection.push_back(poe_regnum); + m_dynamic_reg_infos.push_back(g_register_infos_poe[0]); + m_dynamic_reg_infos[poe_regnum].byte_offset = + m_dynamic_reg_infos[poe_regnum - 1].byte_offset + + m_dynamic_reg_infos[poe_regnum - 1].byte_size; + m_dynamic_reg_infos[poe_regnum].kinds[lldb::eRegisterKindLLDB] = poe_regnum; + + m_per_regset_regnum_range[m_register_set_count] = + std::make_pair(poe_regnum, poe_regnum + 1); + m_dynamic_reg_sets.push_back(g_reg_set_poe_arm64); + m_dynamic_reg_sets.back().registers = m_poe_regnum_collection.data(); +} + uint32_t RegisterInfoPOSIX_arm64::ConfigureVectorLengthSVE(uint32_t sve_vq) { // sve_vq contains SVE Quad vector length in context of AArch64 SVE. // SVE register infos if enabled cannot be disabled by selecting sve_vq = 0. @@ -593,6 +618,10 @@ bool RegisterInfoPOSIX_arm64::IsGCSReg(unsigned reg) const { return llvm::is_contained(m_gcs_regnum_collection, reg); } +bool RegisterInfoPOSIX_arm64::IsPOEReg(unsigned reg) const { + return llvm::is_contained(m_poe_regnum_collection, reg); +} + uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; } uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEFFR() const { return sve_ffr; } @@ -630,3 +659,7 @@ uint32_t RegisterInfoPOSIX_arm64::GetFPMROffset() const { uint32_t RegisterInfoPOSIX_arm64::GetGCSOffset() const { return m_register_info_p[m_gcs_regnum_collection[0]].byte_offset; } + +uint32_t RegisterInfoPOSIX_arm64::GetPOEOffset() const { + return m_register_info_p[m_poe_regnum_collection[0]].byte_offset; +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h index bca5bff24bff0..b40235a3655b8 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_ar... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/177145 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
