https://github.com/JDevlieghere created 
https://github.com/llvm/llvm-project/pull/159117

Recognize an MTE tag fault Mach exception. A tag fault is an error reported by 
Arm's Memory Tagging Extension (MTE) when a memory access attempts to use a 
pointer with a tag that doesn't match the tag stored with the memory. LLDB will 
print the tag and address to make the issue easier to diagnose.

This was hand tested by debugging an MTE enabled binary on an iPhone 17 running 
iOS 26.

rdar://113575216

>From 03a63175357f3b941d120ec3bbab57bf2c3e5997 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <[email protected]>
Date: Tue, 16 Sep 2025 08:58:41 -0700
Subject: [PATCH] [lldb] Recognize MTE fault Mach exceptions

Recognize an MTE tag fault Mach exception. A tag fault is an error
reported by Arm's Memory Tagging Extension (MTE) when a memory access
attempts to use a pointer with a tag that doesn't match the tag stored
with the memory. LLDB will print the tag and address to make the issue
easier to diagnose.

This was tested by debugging an MTE enabled binary running on an iPhone
17 running iOS 26.
---
 .../Process/Utility/StopInfoMachException.cpp | 31 +++++++++++++++++++
 .../Process/Utility/StopInfoMachException.h   |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp 
b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 29a64a2a03bf0..6853121f3e01c 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -77,6 +77,35 @@ static void DescribeAddressBriefly(Stream &strm, const 
Address &addr,
   strm.Printf(".\n");
 }
 
+static constexpr uint8_t g_mte_tag_shift = 64 - 8;
+static constexpr uintptr_t g_mte_tag_mask = (uintptr_t)0x0f << g_mte_tag_shift;
+
+bool StopInfoMachException::DetermineTagMismatch(ExecutionContext &exe_ctx) {
+  const bool IsBadAccess = m_value == 1;            // EXC_BAD_ACCESS
+  const bool IsMTETagFault = (m_exc_code == 0x106); // EXC_ARM_MTE_TAG_FAULT
+  if (!IsBadAccess || !IsMTETagFault)
+    return false;
+
+  if (m_exc_data_count < 2)
+    return false;
+
+  const uint64_t bad_address = m_exc_subcode;
+
+  StreamString strm;
+  strm.Printf("EXC_ARM_MTE_TAG_FAULT (code=%" PRIu64 ", address=0x%" PRIx64
+              ")\n",
+              m_exc_code, bad_address);
+
+  const uint8_t tag = (bad_address & g_mte_tag_mask) >> g_mte_tag_shift;
+  const uint64_t canonical_addr = bad_address & ~g_mte_tag_mask;
+  strm.Printf(
+      "Note: MTE tag mismatch detected: pointer tag=%d, address=0x%" PRIx64,
+      tag, canonical_addr);
+  m_description = std::string(strm.GetString());
+
+  return true;
+}
+
 bool StopInfoMachException::DeterminePtrauthFailure(ExecutionContext &exe_ctx) 
{
   bool IsBreakpoint = m_value == 6; // EXC_BREAKPOINT
   bool IsBadAccess = m_value == 1;  // EXC_BAD_ACCESS
@@ -266,6 +295,8 @@ const char *StopInfoMachException::GetDescription() {
     case llvm::Triple::aarch64:
       if (DeterminePtrauthFailure(exe_ctx))
         return m_description.c_str();
+      if (DetermineTagMismatch(exe_ctx))
+        return m_description.c_str();
       break;
 
     default:
diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h 
b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
index c612ac400b4c4..c02389e5b3642 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -27,6 +27,8 @@ class StopInfoMachException : public StopInfo {
   /// is auth-related failure, and returns false otherwise.
   bool DeterminePtrauthFailure(ExecutionContext &exe_ctx);
 
+  bool DetermineTagMismatch(ExecutionContext &exe_ctx);
+
 public:
   // Constructors and Destructors
   StopInfoMachException(Thread &thread, uint32_t exc_type,

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to