Skip to content

Commit def2020

Browse files
authored
[lldb] Recognize MTE fault Mach exceptions (#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
1 parent f549bb2 commit def2020

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

lldb/source/Plugins/Process/Utility/StopInfoMachException.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,35 @@ static void DescribeAddressBriefly(Stream &strm, const Address &addr,
7777
strm.Printf(".\n");
7878
}
7979

80+
static constexpr uint8_t g_mte_tag_shift = 64 - 8;
81+
static constexpr uintptr_t g_mte_tag_mask = (uintptr_t)0x0f << g_mte_tag_shift;
82+
83+
bool StopInfoMachException::DetermineTagMismatch(ExecutionContext &exe_ctx) {
84+
const bool IsBadAccess = m_value == 1; // EXC_BAD_ACCESS
85+
const bool IsMTETagFault = (m_exc_code == 0x106); // EXC_ARM_MTE_TAG_FAULT
86+
if (!IsBadAccess || !IsMTETagFault)
87+
return false;
88+
89+
if (m_exc_data_count < 2)
90+
return false;
91+
92+
const uint64_t bad_address = m_exc_subcode;
93+
94+
StreamString strm;
95+
strm.Printf("EXC_ARM_MTE_TAG_FAULT (code=%" PRIu64 ", address=0x%" PRIx64
96+
")\n",
97+
m_exc_code, bad_address);
98+
99+
const uint8_t tag = (bad_address & g_mte_tag_mask) >> g_mte_tag_shift;
100+
const uint64_t canonical_addr = bad_address & ~g_mte_tag_mask;
101+
strm.Printf(
102+
"Note: MTE tag mismatch detected: pointer tag=%d, address=0x%" PRIx64,
103+
tag, canonical_addr);
104+
m_description = std::string(strm.GetString());
105+
106+
return true;
107+
}
108+
80109
bool StopInfoMachException::DeterminePtrauthFailure(ExecutionContext &exe_ctx) {
81110
bool IsBreakpoint = m_value == 6; // EXC_BREAKPOINT
82111
bool IsBadAccess = m_value == 1; // EXC_BAD_ACCESS
@@ -266,6 +295,8 @@ const char *StopInfoMachException::GetDescription() {
266295
case llvm::Triple::aarch64:
267296
if (DeterminePtrauthFailure(exe_ctx))
268297
return m_description.c_str();
298+
if (DetermineTagMismatch(exe_ctx))
299+
return m_description.c_str();
269300
break;
270301

271302
default:

lldb/source/Plugins/Process/Utility/StopInfoMachException.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class StopInfoMachException : public StopInfo {
2727
/// is auth-related failure, and returns false otherwise.
2828
bool DeterminePtrauthFailure(ExecutionContext &exe_ctx);
2929

30+
bool DetermineTagMismatch(ExecutionContext &exe_ctx);
31+
3032
public:
3133
// Constructors and Destructors
3234
StopInfoMachException(Thread &thread, uint32_t exc_type,

0 commit comments

Comments
 (0)