Skip to content

Commit 38e0a9e

Browse files
[lldb][AArch64][Linux] Fix memory tagging tests (#192421)
The test program was relying on mmap calls to allocate pages that were next to each other, which is not guaranteed but I got away with it on our simulated systems for a time. Instead of taking this chance, allocate all the pages once and then split the allocation by changing the permissions of each page. That ordering we can rely on. The repeating tag options test is broken due to #192057 so I've xfailed it.
1 parent 10be669 commit 38e0a9e

2 files changed

Lines changed: 26 additions & 24 deletions

File tree

lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@ def test_mte_memory_read_tag_display(self):
590590
@skipUnlessArch("aarch64")
591591
@skipUnlessPlatform(["linux"])
592592
@skipUnlessAArch64MTELinuxCompiler
593+
# Repeating options currently does not work, see
594+
# https://github.com/llvm/llvm-project/issues/192057.
595+
@expectedFailureAll(oslist=["linux"])
593596
def test_mte_memory_read_tag_display_repeated(self):
594597
"""Test that the --show-tags option is kept when repeating the memory read command."""
595598
self.setup_mte_test()

lldb/test/API/linux/aarch64/mte_tag_access/main.c

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@
1111
// This file uses ACLE intrinsics as detailed in:
1212
// https://developer.arm.com/documentation/101028/0012/10--Memory-tagging-intrinsics?lang=en
1313

14-
char *checked_mmap(size_t page_size, int prot) {
15-
char *ptr = mmap(0, page_size, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
14+
char *checked_mmap(size_t size, int prot) {
15+
char *ptr = mmap(0, size, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1616
if (ptr == MAP_FAILED)
1717
exit(1);
1818
return ptr;
1919
}
2020

21+
char *checked_mprotect(char *addr, size_t size, int prot) {
22+
if (mprotect(addr, size, prot) != 0)
23+
exit(1);
24+
return addr;
25+
}
26+
2127
int main(int argc, char const *argv[]) {
2228
// We assume that the test runner has checked we're on an MTE system
2329

@@ -30,29 +36,22 @@ int main(int argc, char const *argv[]) {
3036
return 1;
3137
}
3238

33-
size_t page_size = sysconf(_SC_PAGESIZE);
34-
35-
// We're going to mmap pages in this order:
36-
// <high addres>
37-
// MTE read/write
38-
// MTE read/write executable
39-
// non MTE
40-
// MTE read only
41-
// <low address>
42-
//
43-
// This means that the first two MTE pages end up next
44-
// to each other. Since the second one is also executable
45-
// it will create a new entry in /proc/smaps.
46-
int mte_prot = PROT_READ | PROT_MTE;
47-
48-
char *mte_buf_2 = checked_mmap(page_size, mte_prot | PROT_WRITE);
49-
char *mte_buf = checked_mmap(page_size, mte_prot | PROT_WRITE | PROT_EXEC);
50-
// We expect the mappings to be next to each other
51-
if (mte_buf_2 - mte_buf != page_size)
52-
return 1;
39+
const size_t page_size = sysconf(_SC_PAGESIZE);
40+
// Each time we change the permissions of a page, it becomes its own unique
41+
// mapping.
42+
char *pages = checked_mmap(page_size * 4, 0);
5343

54-
char *non_mte_buf = checked_mmap(page_size, PROT_READ);
55-
char *mte_read_only = checked_mmap(page_size, mte_prot);
44+
// The order and layout of these mappings is important. They start with
45+
// the lowest address.
46+
char *mte_read_only =
47+
checked_mprotect(pages, page_size, PROT_MTE | PROT_READ);
48+
char *non_mte_buf =
49+
checked_mprotect(mte_read_only + page_size, page_size, PROT_READ);
50+
char *mte_buf =
51+
checked_mprotect(non_mte_buf + page_size, page_size,
52+
PROT_READ | PROT_MTE | PROT_WRITE | PROT_EXEC);
53+
char *mte_buf_2 = checked_mprotect(mte_buf + page_size, page_size,
54+
PROT_MTE | PROT_READ | PROT_WRITE);
5655

5756
// Target value for "memory find" testing.
5857
strncpy(mte_buf+128, "LLDB", 4);

0 commit comments

Comments
 (0)