[llvm] [lldb][AArch64] Read mte_ctrl register from core files (PR #69689)

David Spickett via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 20 01:08:29 PDT 2023


https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/69689

This register reports the configuration of the AArch64 Linux tagged address ABI, part of which is the memory tagging (MTE) settings.

It will always be present in core files because even without MTE, there are parts of the tagged address ABI that can be configured (these parts use the Top Byte Ignore feature).

I missed adding this when I previously worked on MTE support. Until now you could read memory tags from a core file but not this register.

>From 355e7950a6d07e0c8c44bc2652072148b977d8d1 Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Mon, 9 Oct 2023 09:58:56 +0100
Subject: [PATCH] [lldb][AArch64] Read mte_ctrl register from core files

This register reports the configuration of the AArch64 Linux
tagged address ABI, part of which is the memory tagging (MTE)
settings.

It will always be present in core files because even without
MTE, there are parts of the tagged address ABI that can be
configured (these parts use the Top Byte Ignore feature).

I missed adding this when I previously worked on MTE support.
Until now you could read memory tags from a core file but
not this register.
---
 .../Utility/RegisterContextPOSIX_arm64.cpp       |  4 ++++
 .../Process/Utility/RegisterContextPOSIX_arm64.h |  1 +
 .../elf-core/RegisterContextPOSIXCore_arm64.cpp  | 12 ++++++++++++
 .../elf-core/RegisterContextPOSIXCore_arm64.h    |  1 +
 .../Plugins/Process/elf-core/RegisterUtilities.h |  5 +++++
 .../TestAArch64LinuxMTEMemoryTagCoreFile.py      | 16 ++++++++++++++++
 llvm/docs/ReleaseNotes.rst                       |  1 +
 7 files changed, 40 insertions(+)

diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index b57538e185f71fa..50e25568f2ae012 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -55,6 +55,10 @@ bool RegisterContextPOSIX_arm64::IsTLS(unsigned reg) const {
   return m_register_info_up->IsTLSReg(reg);
 }
 
+bool RegisterContextPOSIX_arm64::IsMTE(unsigned reg) const {
+  return m_register_info_up->IsMTEReg(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 aad95f33735f178..b1226b25b4be107 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -57,6 +57,7 @@ class RegisterContextPOSIX_arm64 : public lldb_private::RegisterContext {
   bool IsPAuth(unsigned reg) const;
   bool IsTLS(unsigned reg) const;
   bool IsSME(unsigned reg) const;
+  bool IsMTE(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/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 6f6c6d073939a61..790511eea14a586 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -50,6 +50,10 @@ RegisterContextCorePOSIX_arm64::Create(Thread &thread, const ArchSpec &arch,
   if (za_data.GetByteSize() >= sizeof(sve::user_za_header))
     opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskZA);
 
+  DataExtractor mte_data = getRegset(notes, arch.GetTriple(), AARCH64_MTE_Desc);
+  if (mte_data.GetByteSize() >= sizeof(uint64_t))
+    opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
+
   auto register_info_up =
       std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
   return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
@@ -91,6 +95,9 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
   if (m_register_info_up->IsZAEnabled())
     m_za_data = getRegset(notes, target_triple, AARCH64_ZA_Desc);
 
+  if (m_register_info_up->IsMTEEnabled())
+    m_mte_data = getRegset(notes, target_triple, AARCH64_MTE_Desc);
+
   ConfigureRegisterContext();
 }
 
@@ -282,6 +289,11 @@ bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
     assert(offset < m_tls_data.GetByteSize());
     value.SetFromMemoryData(*reg_info, m_tls_data.GetDataStart() + offset,
                             reg_info->byte_size, lldb::eByteOrderLittle, error);
+  } else if (IsMTE(reg)) {
+    offset = reg_info->byte_offset - m_register_info_up->GetMTEOffset();
+    assert(offset < m_mte_data.GetByteSize());
+    value.SetFromMemoryData(*reg_info, m_mte_data.GetDataStart() + offset,
+                            reg_info->byte_size, lldb::eByteOrderLittle, error);
   } else if (IsSME(reg)) {
     // If you had SME in the process, active or otherwise, there will at least
     // be a ZA header. No header, no SME at all.
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
index 73b65a4174290c1..86bdeb426ab3fe0 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.h
@@ -59,6 +59,7 @@ class RegisterContextCorePOSIX_arm64 : public RegisterContextPOSIX_arm64 {
   lldb_private::DataExtractor m_pac_data;
   lldb_private::DataExtractor m_tls_data;
   lldb_private::DataExtractor m_za_data;
+  lldb_private::DataExtractor m_mte_data;
 
   SVEState m_sve_state = SVEState::Unknown;
   uint16_t m_sve_vector_length = 0;
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
index f1b1194f886d5f6..4b01a56979bb1c4 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
+++ b/lldb/source/Plugins/Process/elf-core/RegisterUtilities.h
@@ -135,6 +135,11 @@ constexpr RegsetDesc AARCH64_TLS_Desc[] = {
     {llvm::Triple::Linux, llvm::Triple::aarch64, llvm::ELF::NT_ARM_TLS},
 };
 
+constexpr RegsetDesc AARCH64_MTE_Desc[] = {
+    {llvm::Triple::Linux, llvm::Triple::aarch64,
+     llvm::ELF::NT_ARM_TAGGED_ADDR_CTRL},
+};
+
 constexpr RegsetDesc PPC_VMX_Desc[] = {
     {llvm::Triple::FreeBSD, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
     {llvm::Triple::Linux, llvm::Triple::UnknownArch, llvm::ELF::NT_PPC_VMX},
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
index 1f8a5f9326b2b85..4389d3d761d79c2 100644
--- a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
+++ b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
@@ -220,3 +220,19 @@ def test_mte_tag_fault_reason(self):
                 "sync tag check fault"
             ],
         )
+
+    @skipIfLLVMTargetMissing("AArch64")
+    def test_mte_ctrl_register(self):
+        """Test that we correctly report the mte_ctrl register"."""
+        # The register is present even if MTE is not used in the current process
+        # and also on targets without MTE, because it controls parts of the
+        # overall tagged address ABI as well.
+        self.runCmd("target create --core core.nomte")
+        self.expect("register read mte_ctrl", substrs=["mte_ctrl = 0x0000000000000000"])
+
+        self.runCmd("target create --core core.mte")
+        # The expected value is:
+        # * Allowed tags value of 0xFFFF, shifted up by 3 resulting in 0x7fff8.
+        # * Bit 1 set to enable synchronous tag faults.
+        # * Bit 0 set to enable the tagged address ABI.
+        self.expect("register read mte_ctrl", substrs=["mte_ctrl = 0x000000000007fffb"])
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 6830285483e28d9..f02357f91c971ef 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -208,6 +208,7 @@ Changes to LLDB
 * ``lldb-vscode`` was renamed to ``lldb-dap`` and and its installation
   instructions have been updated to reflect this. The underlying functionality
   remains unchanged.
+* The ``mte_ctrl`` register can now be read from AArch64 Linux core files.
 
 Changes to Sanitizers
 ---------------------



More information about the llvm-commits mailing list