diff --git a/lldb/source/Commands/CommandObjectMemoryTag.cpp b/lldb/source/Commands/CommandObjectMemoryTag.cpp --- a/lldb/source/Commands/CommandObjectMemoryTag.cpp +++ b/lldb/source/Commands/CommandObjectMemoryTag.cpp @@ -12,6 +12,7 @@ #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionValueString.h" +#include "lldb/Target/ABI.h" #include "lldb/Target/Process.h" using namespace lldb; @@ -85,6 +86,17 @@ // If this fails the list of regions is cleared, so we don't need to read // the return status here. process->GetMemoryRegions(memory_regions); + + lldb::addr_t logical_tag = tag_manager->GetLogicalTag(start_addr); + + // The tag manager only removes tag bits. These addresses may include other + // non-address bits that must also be ignored. + ABISP abi = process->GetABI(); + if (abi) { + start_addr = abi->FixDataAddress(start_addr); + end_addr = abi->FixDataAddress(end_addr); + } + llvm::Expected tagged_range = tag_manager->MakeTaggedRange(start_addr, end_addr, memory_regions); @@ -101,7 +113,6 @@ return false; } - lldb::addr_t logical_tag = tag_manager->GetLogicalTag(start_addr); result.AppendMessageWithFormatv("Logical tag: {0:x}", logical_tag); result.AppendMessage("Allocation tags:"); @@ -231,6 +242,12 @@ // the return status here. process->GetMemoryRegions(memory_regions); + // The tag manager only removes tag bits. These addresses may include other + // non-address bits that must also be ignored. + ABISP abi = process->GetABI(); + if (abi) + start_addr = abi->FixDataAddress(start_addr); + // We have to assume start_addr is not granule aligned. // So if we simply made a range: // (start_addr, start_addr + (N * granule_size)) @@ -254,6 +271,10 @@ end_addr = aligned_start_addr + (tags.size() * tag_manager->GetGranuleSize()); + // Remove non-address bits that aren't memory tags + if (abi) + end_addr = abi->FixDataAddress(end_addr); + // Now we've aligned the start address so if we ask for another range // using the number of tags N, we'll get back a range that is also N // granules in size. diff --git a/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py b/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py --- a/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py +++ b/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py @@ -20,6 +20,11 @@ if not self.isAArch64MTE(): self.skipTest('Target must support MTE.') + # Required to check that commands remove non-address bits + # other than the memory tags. + if not self.isAArch64PAuth(): + self.skipTest('Target must support pointer authentication') + self.build() self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) diff --git a/lldb/test/API/linux/aarch64/mte_tag_access/main.c b/lldb/test/API/linux/aarch64/mte_tag_access/main.c --- a/lldb/test/API/linux/aarch64/mte_tag_access/main.c +++ b/lldb/test/API/linux/aarch64/mte_tag_access/main.c @@ -71,8 +71,9 @@ // tag char *mte_buf_alt_tag = __arm_mte_create_random_tag(mte_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. + // The memory tag manager 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, value) \ (char *)((size_t)(ptr) | ((size_t)((value)&0xf) << 60)) // mte_buf_alt_tag's nibble > mte_buf to check that lldb isn't just removing @@ -82,6 +83,15 @@ mte_buf_2 = SET_TOP_NIBBLE(mte_buf_2, 0xC); mte_read_only = SET_TOP_NIBBLE(mte_read_only, 0xD); +// The top level commands should be removing all non-address bits, including +// pointer signatures. This signs ptr with PAC key A. That signature goes +// in some bits other than the top byte. +#define sign_ptr(ptr) __asm__ __volatile__("pacdza %0" : "=r"(ptr) : "r"(ptr)) + sign_ptr(mte_buf); + sign_ptr(mte_buf_alt_tag); + sign_ptr(mte_buf_2); + sign_ptr(mte_read_only); + // Breakpoint here return 0; }