[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG31f9960c3852: [lldb][AArch64] Add memory tag read command (authored by DavidSpickett). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 352741. DavidSpickett added a comment. Rebase. Remove `result.SetStatus(eReturnStatusFailed)` which is now implicitly done when you add an error. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list",
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 351432. DavidSpickett added a comment. Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +#
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 347909. DavidSpickett added a comment. Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +#
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 345117. DavidSpickett added a comment. Rebase onto earlier patches. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason =
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 341450. DavidSpickett added a comment. Rebase Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +#
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 340780. DavidSpickett added a comment. Rebase onto main. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) +
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 337468. DavidSpickett added a comment. - Rebase onto main Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint'])
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 330998. DavidSpickett added a comment. Expand test to check that we can read tags for a range that spans two mappings. This covers updated code in GetMemoryTagManager. Refactor the test file a bit to account for the extra mmap. I've tested the mmap sequence on my x86 box which has ASLR enabled and on Qemu. I always get the ordering we want for the test. I can't cite anything to say it should always work but I didn't find any feature that goes out of its way to change the ordering of mmap allocations. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + // We ask for two pages. One is read only so that we get + // 2 mappings in /proc/.../smaps so we can check reading + // a range across mappings. + // The first allocation will start at the highest address, + // so we allocate buf2 first to get: + // | buf | buf2 | + int prot = PROT_READ | PROT_MTE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + char *buf2 = mmap(0, page_size, prot, flags, -1, 0); + if (buf2 == MAP_FAILED) +return 1; + + // Writeable so we can set tags on it later + char *buf = mmap(0, page_size, prot | PROT_WRITE, flags, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // We expect the mappings to be next to each other + if (buf2 - buf != page_size) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, flags, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the first page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. +#define SET_TOP_NIBBLE(ptr) (char *)((size_t)(ptr) | (0xA << 60)) + buf = SET_TOP_NIBBLE(buf); + buf_alt_tag = SET_TOP_NIBBLE(buf_alt_tag); + buf2 = SET_TOP_NIBBLE(buf2); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,126 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett added a comment. I still have one known (though rare) limitation to this command. That is, if you try to read across two neighbouring MTE regions it will fail because it thinks that the whole range isn't tagged. When it is, it's just split over two regions. This would require you to manage to mmap them next to each other. So I'm looking for a way to do deliberately so it could be tested. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 330686. DavidSpickett added a comment. - Update after changing earlier revisions - Read page size only once in the test file Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + char *buf = mmap(0, page_size, PROT_READ | PROT_WRITE | PROT_MTE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. + size_t nibble = 0xA; + buf = (char *)((size_t)buf | (nibble << 60)); + buf_alt_tag = (char *)((size_t)buf_alt_tag | (nibble << 60)); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,116 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +# Argument validation +self.expect("memory tag read", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +error=True) +self.expect("memory tag read buf buf+16 32", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +error=True) +self.expect("memory tag read
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 329031. DavidSpickett added a comment. - RemoveNonAddressBits over RemoveLogicalTag - Set bits 63-60 of test file pointers to check we remove the top byte now. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + char *buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE | PROT_MTE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // lldb should be removing the whole top byte, not just the tags. + // So fill 63-60 with something non zero so we'll fail if we only remove tags. + size_t nibble = 0xA; + buf = (char *)((size_t)buf | (nibble << 60)); + buf_alt_tag = (char *)((size_t)buf_alt_tag | (nibble << 60)); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,116 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +# Argument validation +self.expect("memory tag read", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +error=True) +self.expect("memory tag read buf buf+16 32", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 327062. DavidSpickett added a comment. Update after changing previous patch. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + char *buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE | PROT_MTE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,116 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +# Argument validation +self.expect("memory tag read", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +error=True) +self.expect("memory tag read buf buf+16 32", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +error=True) +self.expect("memory tag read not_a_symbol", +substrs=["error: Invalid address expression, address expression \"not_a_symbol\" " + "evaluation failed"], +error=True) +self.expect("memory tag read buf not_a_symbol", +substrs=["error: Invalid end address expression, address
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett updated this revision to Diff 325775. DavidSpickett added a comment. - Add some comments to explain the intrinsics used. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + char *buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE | PROT_MTE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the page + char *tagged_ptr = buf; + // This ignores tag bits when subtracting the addresses + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +// Set the allocation tag for this location +__arm_mte_set_tag(tagged_ptr); +// + 16 for 16 byte granules +// Earlier we allowed all tag values, so this will give us an +// incrementing pattern 0-0xF wrapping back to 0. +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,116 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +# Argument validation +self.expect("memory tag read", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +error=True) +self.expect("memory tag read buf buf+16 32", +substrs=["error: wrong number of arguments; expected at least , " + "at most "], +error=True) +self.expect("memory tag read not_a_symbol", +substrs=["error: Invalid address expression, address expression \"not_a_symbol\" " + "evaluation failed"], +error=True) +self.expect("memory tag read buf not_a_symbol", +substrs=["error: Invalid end address
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett added inline comments. Comment at: lldb/test/API/linux/aarch64/mte_tag_read/main.c:46 + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + https://developer.arm.com/documentation/101028/0012/10--Memory-tagging-intrinsics for descriptions of these functions. I probably need to add some more comments here for the unfamiliar. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett added reviewers: omjavaid, labath. DavidSpickett added a comment. This command is described in the RFC under the name "mtag showatag" (https://lists.llvm.org/pipermail/lldb-dev/2020-August/016402.html). The change of naming was suggested in feedback and I think it does fit better with the other commands so I went with it. The output is very basic and could certainly be compacted but this is just the initial implementation. There is also the option to have this command highlight matches/mismatches. This would reduce (maybe remove) the need for a "memory tag check" command. I think that would be better done as a follow up if so. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D97285/new/ https://reviews.llvm.org/D97285 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D97285: [lldb][AArch64] Add "memory tag read" command
DavidSpickett created this revision. Herald added subscribers: danielkiss, kristof.beyls, mgorny. DavidSpickett requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits. This new command looks much like "memory read" and mirrors its basic behaviour. (lldb) memory tag read new_buf_ptr new_buf_ptr+32 Logical tag: 0x9 Allocation tags: [0x900f7ffa000, 0x900f7ffa010): 0x9 [0x900f7ffa010, 0x900f7ffa020): 0x0 Important proprties: - The end address is optional and defaults to reading 1 tag if ommitted - It is an error to try to read tags if the architecture or process doesn't support it, or if the range asked for is not tagged. - It is an error to read an inverted range (end < begin) (logical tags are removed for this check so you can pass tagged addresses here) - The range will be expanded to fit the tagging granule, so you can get more tags than simply (end-begin)/granule size. Whatever you get back will always cover the original range. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D97285 Files: lldb/source/Commands/CMakeLists.txt lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Commands/CommandObjectMemoryTag.cpp lldb/source/Commands/CommandObjectMemoryTag.h lldb/test/API/functionalities/memory/tag/Makefile lldb/test/API/functionalities/memory/tag/TestMemoryTag.py lldb/test/API/functionalities/memory/tag/main.cpp lldb/test/API/linux/aarch64/mte_tag_read/Makefile lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py lldb/test/API/linux/aarch64/mte_tag_read/main.c Index: lldb/test/API/linux/aarch64/mte_tag_read/main.c === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/main.c @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char const *argv[]) { + // We assume that the test runner has checked we're on an MTE system + + if (prctl(PR_SET_TAGGED_ADDR_CTRL, +PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_SYNC | +// Allow all tags to be generated by the addg +// instruction __arm_mte_increment_tag produces. +(0x << PR_MTE_TAG_SHIFT), +0, 0, 0)) { +return 1; + } + + size_t page_size = sysconf(_SC_PAGESIZE); + + // Allocate memory with MTE + char *buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE | PROT_MTE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf == MAP_FAILED) +return 1; + + // And without MTE + char *non_mte_buf = mmap(0, sysconf(_SC_PAGESIZE), PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (non_mte_buf == MAP_FAILED) +return 1; + + // Set incrementing tags until end of the page + char *tagged_ptr = buf; + while (__arm_mte_ptrdiff(tagged_ptr, buf) < page_size) { +__arm_mte_set_tag(tagged_ptr); +// 16 byte granules, tags will wrap at 0xF +tagged_ptr = __arm_mte_increment_tag(tagged_ptr + 16, 1); + } + + // Tag the original pointer with 9 + buf = __arm_mte_create_random_tag(buf, ~(1 << 9)); + // A different tag so that buf_alt_tag > buf if you don't handle the tag + char *buf_alt_tag = __arm_mte_create_random_tag(buf, ~(1 << 10)); + + // Breakpoint here + return 0; +} Index: lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py === --- /dev/null +++ lldb/test/API/linux/aarch64/mte_tag_read/TestAArch64LinuxMTEMemoryTagRead.py @@ -0,0 +1,116 @@ +""" +Test "memory tag read" command on AArch64 Linux with MTE. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxMTEMemoryTagReadTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +NO_DEBUG_INFO_TESTCASE = True + +@skipUnlessArch("aarch64") +@skipUnlessPlatform(["linux"]) +@skipUnlessAArch64MTELinuxCompiler +def test_mte_tag_read(self): +if not self.isAArch64MTE(): +self.skipTest('Target must support MTE.') + +self.build() +self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + +lldbutil.run_break_set_by_file_and_line(self, "main.c", +line_number('main.c', '// Breakpoint here'), +num_expected_locations=1) + +self.runCmd("run", RUN_SUCCEEDED) + +if self.process().GetState() == lldb.eStateExited: +self.fail("Test program failed to run.") + +self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT, +substrs=['stopped', + 'stop reason = breakpoint']) + +# Argument validation +self.expect("memory tag read", +substrs=["error: wrong number of arguments; expected at least , " +