Skip to content

Conversation

@yln
Copy link
Collaborator

@yln yln commented Dec 17, 2025

5a5a315 [lldb][NFC] Extract StopInfoMachException::GetTagFaultAddress() helper function

9a91ded [lldb] Recognize MTE faults with EXC_GUARD exception type
Recognize the new EXC_GUARD mach exception type
for MTE faults. We also keep supporting the old
EXC_BAD_ACCESS exception type for backward
compatibility (newer LLDB on older OS).

rdar://166415268

@yln yln self-assigned this Dec 17, 2025
@yln yln added the lldb label Dec 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 17, 2025

@llvm/pr-subscribers-lldb

Author: Julian Lettner (yln)

Changes

5a5a315 [lldb][NFC] Extract StopInfoMachException::GetTagFaultAddress() helper function

9a91ded [lldb] Recognize MTE faults with EXC_GUARD exception type
Recognize the new EXC_GUARD mach exception type
for MTE faults. We also keep supporting the old
EXC_BAD_ACCESS exception type for backward
compatibility (newer LLDB on older OS).

rdar://166415268


Full diff: https://github.com/llvm/llvm-project/pull/172579.diff

2 Files Affected:

  • (modified) lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp (+20-10)
  • (modified) lldb/source/Plugins/Process/Utility/StopInfoMachException.h (+4-1)
diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 601cfdcb4e9f7..826807e47ce96 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -77,19 +77,27 @@ static void DescribeAddressBriefly(Stream &strm, const Address &addr,
   strm.Printf(".\n");
 }
 
+std::optional<addr_t> StopInfoMachException::GetTagFaultAddress() const {
+  bool bad_access =
+      (m_value == 1 || m_value == 12);           // EXC_BAD_ACCESS or EXC_GUARD
+  bool tag_fault = (m_exc_code == 0x106);        // EXC_ARM_MTE_TAG_FAULT
+  bool has_fault_addr = (m_exc_data_count >= 2); // m_exc_subcode -> fault addr
+
+  if (bad_access && tag_fault && has_fault_addr)
+    return m_exc_subcode; // Fault address
+
+  return std::nullopt;
+}
+
 static constexpr uint8_t g_mte_tag_shift = 64 - 8;
 static constexpr addr_t g_mte_tag_mask = (addr_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;
+bool StopInfoMachException::DetermineTagMismatch() {
+  auto fault_address = GetTagFaultAddress();
+  if (!fault_address)
+      return false;
 
-  const uint64_t bad_address = m_exc_subcode;
+  const uint64_t bad_address = *fault_address;
 
   StreamString strm;
   strm.Printf("EXC_ARM_MTE_TAG_FAULT (code=%" PRIu64 ", address=0x%" PRIx64
@@ -295,7 +303,7 @@ const char *StopInfoMachException::GetDescription() {
     case llvm::Triple::aarch64:
       if (DeterminePtrauthFailure(exe_ctx))
         return m_description.c_str();
-      if (DetermineTagMismatch(exe_ctx))
+      if (DetermineTagMismatch())
         return m_description.c_str();
       break;
 
@@ -490,6 +498,8 @@ const char *StopInfoMachException::GetDescription() {
 #endif
     break;
   case 12:
+    if (DetermineTagMismatch())
+      return m_description.c_str();
     exc_desc = "EXC_GUARD";
     break;
   }
diff --git a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
index c02389e5b3642..26f93e0bb348f 100644
--- a/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
+++ b/lldb/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -27,7 +27,7 @@ class StopInfoMachException : public StopInfo {
   /// is auth-related failure, and returns false otherwise.
   bool DeterminePtrauthFailure(ExecutionContext &exe_ctx);
 
-  bool DetermineTagMismatch(ExecutionContext &exe_ctx);
+  bool DetermineTagMismatch();
 
 public:
   // Constructors and Destructors
@@ -48,6 +48,9 @@ class StopInfoMachException : public StopInfo {
 
   const char *GetDescription() override;
 
+  // Returns the fault address, iff this is a EXC_ARM_MTE_TAG_FAULT.
+  std::optional<lldb::addr_t> GetTagFaultAddress() const;
+
 #if defined(__APPLE__)
   struct MachException {
     static const char *Name(exception_type_t exc_type);

@github-actions

This comment was marked as resolved.

yln added 2 commits December 16, 2025 16:27
Recognize the new `EXC_GUARD` mach exception type
for MTE faults.  We also keep supporting the old
`EXC_BAD_ACCESS` exception type for backward
compatibility (newer LLDB on older OS).

rdar://166415268
@yln yln force-pushed the users/yln/lldb-mte-fault-EXC_GUARD branch from 9a91ded to 1f7ddff Compare December 17, 2025 00:28
Comment on lines +81 to +84
bool bad_access =
(m_value == 1 || m_value == 12); // EXC_BAD_ACCESS or EXC_GUARD
bool tag_fault = (m_exc_code == 0x106); // EXC_ARM_MTE_TAG_FAULT
bool has_fault_addr = (m_exc_data_count >= 2); // m_exc_subcode -> fault addr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool bad_access =
(m_value == 1 || m_value == 12); // EXC_BAD_ACCESS or EXC_GUARD
bool tag_fault = (m_exc_code == 0x106); // EXC_ARM_MTE_TAG_FAULT
bool has_fault_addr = (m_exc_data_count >= 2); // m_exc_subcode -> fault addr
const bool bad_access =
(m_value == 1 || m_value == 12); // EXC_BAD_ACCESS or EXC_GUARD
const bool tag_fault = (m_exc_code == 0x106); // EXC_ARM_MTE_TAG_FAULT
// Whether the subcode (m_exc_subcode) holds the fault address.
const bool has_fault_addr = (m_exc_data_count >= 2);

Comment on lines +86 to +87
if (bad_access && tag_fault && has_fault_addr)
return m_exc_subcode; // Fault address
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments should be english prose with capitalization and periods.

Suggested change
if (bad_access && tag_fault && has_fault_addr)
return m_exc_subcode; // Fault address
if (bad_access && tag_fault && has_fault_addr)
return m_exc_subcode; // The subcode is the fault address.


if (m_exc_data_count < 2)
bool StopInfoMachException::DetermineTagMismatch() {
auto fault_address = GetTagFaultAddress();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type isn't obvious from the RHS.

Suggested change
auto fault_address = GetTagFaultAddress();
std::optional<addr_t> fault_address = GetTagFaultAddress();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants