diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -22,6 +22,7 @@ #include "lldb/Interpreter/Options.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/Language.h" #include "lldb/Target/MemoryHistory.h" #include "lldb/Target/MemoryRegionInfo.h" @@ -589,9 +590,16 @@ return false; } + ABISP abi = m_exe_ctx.GetProcessPtr()->GetABI(); + if (abi) + addr = abi->FixDataAddress(addr); + if (argc == 2) { lldb::addr_t end_addr = OptionArgParser::ToAddress( &m_exe_ctx, command[1].ref(), LLDB_INVALID_ADDRESS, nullptr); + if (end_addr != LLDB_INVALID_ADDRESS && abi) + end_addr = abi->FixDataAddress(end_addr); + if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid end address expression."); result.AppendError(error.AsCString()); diff --git a/lldb/test/API/linux/aarch64/tagged_memory_read/Makefile b/lldb/test/API/linux/aarch64/tagged_memory_read/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/linux/aarch64/tagged_memory_read/Makefile @@ -0,0 +1,4 @@ +C_SOURCES := main.c +CFLAGS_EXTRAS := -march=armv8.3-a + +include Makefile.rules diff --git a/lldb/test/API/linux/aarch64/tagged_memory_read/TestAArch64LinuxTaggedMemoryRead.py b/lldb/test/API/linux/aarch64/tagged_memory_read/TestAArch64LinuxTaggedMemoryRead.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/linux/aarch64/tagged_memory_read/TestAArch64LinuxTaggedMemoryRead.py @@ -0,0 +1,55 @@ +""" +Test that "memory read" removes the top byte and pointer +authentication signature of addresses before using them. +""" + + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class AArch64LinuxTaggedMemoryReadTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @skipUnlessArch("aarch64") + @skipUnlessPlatform(["linux"]) + def test_mte_tagged_memory_read(self): + if not self.isAArch64PAuth(): + self.skipTest('Target must support pointer authentication.') + + 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', '// Set break point at this line.'), + 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']) + + # If we do not remove non address bits, this can fail in two ways. + # 1. We attempt to read much more than 16 bytes, probably more than + # the default 1024 byte read size. (which is an error) + # 2. We error because end address is < start address. Likely + # because end's tag is < the beginning's tag. + # + # Each time we check that the printed line addresses do not include + # either of the tags we set. + tagged_addr_pattern = "0x(34|46)[0-9A-Fa-f]{14}:.*" + self.expect("memory read ptr1 ptr2+16", patterns=[tagged_addr_pattern], matching=False) + # Check that the stored previous end address is stripped + self.expect("memory read", patterns=[tagged_addr_pattern], matching=False) + self.expect("memory read ptr2 ptr1+16", patterns=[tagged_addr_pattern], matching=False) + self.expect("memory read", patterns=[tagged_addr_pattern], matching=False) diff --git a/lldb/test/API/linux/aarch64/tagged_memory_read/main.c b/lldb/test/API/linux/aarch64/tagged_memory_read/main.c new file mode 100644 --- /dev/null +++ b/lldb/test/API/linux/aarch64/tagged_memory_read/main.c @@ -0,0 +1,18 @@ +#include + +static char *set_non_address_bits(char *ptr, size_t tag) { + // Set top byte tag + ptr = (char *)((size_t)ptr | (tag << 56)); + // Sign it + __asm__ __volatile__("pacdzb %0" : "=r"(ptr) : "r"(ptr)); + return ptr; +} + +int main(int argc, char const *argv[]) { + char buf[32]; + + char *ptr1 = set_non_address_bits(buf, 0x34); + char *ptr2 = set_non_address_bits(buf, 0x56); + + return 0; // Set break point at this line. +}