[Lldb-commits] [lldb] [lldb][test] Strip the MTE tag in TestExpeditedRecentReads (PR #226272)

Yao Qi via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 24 12:01:11 PDT 2026


https://github.com/qiyao created https://github.com/llvm/llvm-project/pull/226272

When the inferior runs with MTE enabled, both heap cases in
`TestExpeditedRecentReads.py` fail at their first stop:

```
AssertionError: [] == [] : the first stop should read the heap buffer from the stub; reads: [0x104da8a00,0x104da8c00)
AssertionError: [] == [] : the first stop should read the heap buffer from the stub; reads: [0x1047acb30,0x1047acb38), [0x1047acb30,0x1047acb38), ...
```

lldb did read the heap buffer. `calloc` returns a pointer with an MTE
tag in its top byte, and lldb strips the tag before it reads memory:

```
(lldb) breakpoint set -p "break here" -f main.c
(lldb) process launch --memory-tagging
...
(lldb) frame variable heap
(Payload *) heap = 0x0b000001005b0b30
(lldb) script v = lldb.frame.FindVariable("heap"); print("GetValueAsUnsigned: 0x%x" % v.GetValueAsUnsigned(0)); print("GetValueAsAddress:  0x%x" % v.GetValueAsAddress())
GetValueAsUnsigned: 0xb000001005b0b30
GetValueAsAddress:  0x1005b0b30
```

Reading `heap->values[0]` then sends `x1005b0a00,200`, which reads the
untagged address. `heap_range` takes the address from
`GetValueAsUnsigned`, which keeps the tag, so `covering` never matches
a read. Use `GetValueAsAddress`, which returns the address with the
non-addressable bits cleared.

Assisted-by: claude


>From e7c7be755a096f92b364f4188f4b61413744abf6 Mon Sep 17 00:00:00 2001
From: Yao Qi <yao_qi at apple.com>
Date: Thu, 24 Sep 2026 16:47:55 +0100
Subject: [PATCH] [lldb][test] Strip the MTE tag in TestExpeditedRecentReads

When the inferior runs with MTE enabled, both heap cases in
`TestExpeditedRecentReads.py` fail at their first stop:

```
AssertionError: [] == [] : the first stop should read the heap buffer from the stub; reads: [0x104da8a00,0x104da8c00)
AssertionError: [] == [] : the first stop should read the heap buffer from the stub; reads: [0x1047acb30,0x1047acb38), [0x1047acb30,0x1047acb38), ...
```

lldb did read the heap buffer. `calloc` returns a pointer with an MTE
tag in its top byte, and lldb strips the tag before it reads memory:

```
(lldb) breakpoint set -p "break here" -f main.c
(lldb) process launch --memory-tagging
...
(lldb) frame variable heap
(Payload *) heap = 0x0b000001005b0b30
(lldb) script v = lldb.frame.FindVariable("heap"); print("GetValueAsUnsigned: 0x%x" % v.GetValueAsUnsigned(0)); print("GetValueAsAddress:  0x%x" % v.GetValueAsAddress())
GetValueAsUnsigned: 0xb000001005b0b30
GetValueAsAddress:  0x1005b0b30
```

Reading `heap->values[0]` then sends `x1005b0a00,200`, which reads the
untagged address. `heap_range` takes the address from
`GetValueAsUnsigned`, which keeps the tag, so `covering` never matches
a read. Use `GetValueAsAddress`, which returns the address with the
non-addressable bits cleared.

Assisted-by: claude
---
 .../macosx/expedited-recent-reads/TestExpeditedRecentReads.py   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/test/API/macosx/expedited-recent-reads/TestExpeditedRecentReads.py b/lldb/test/API/macosx/expedited-recent-reads/TestExpeditedRecentReads.py
index b0e64e6eb4fcb..cebe31fd52407 100644
--- a/lldb/test/API/macosx/expedited-recent-reads/TestExpeditedRecentReads.py
+++ b/lldb/test/API/macosx/expedited-recent-reads/TestExpeditedRecentReads.py
@@ -161,7 +161,7 @@ def check_heap_reads(self, disable_memory_cache):
     def heap_range(thread):
         """The (address, size) of the buffer the 'heap' local points at."""
         heap = thread.GetFrameAtIndex(0).FindVariable("heap")
-        return heap.GetValueAsUnsigned(0), heap.GetType().GetPointeeType().GetByteSize()
+        return heap.GetValueAsAddress(), heap.GetType().GetPointeeType().GetByteSize()
 
     def examine_heap(self, logfile, thread, marker):
         """Read every element of the heap buffer the way a variables view would,



More information about the lldb-commits mailing list