Author: David Spickett Date: 2022-05-19T14:40:01+01:00 New Revision: 068f14f1e4ec69d218df544487f9420f2b3ab29b
URL: https://github.com/llvm/llvm-project/commit/068f14f1e4ec69d218df544487f9420f2b3ab29b DIFF: https://github.com/llvm/llvm-project/commit/068f14f1e4ec69d218df544487f9420f2b3ab29b.diff LOG: [lldb] Add --show-tags option to "memory find" This is off by default. If you get a result and that memory has memory tags, when --show-tags is given you'll see the tags inline with the memory content. ``` (lldb) memory read mte_buf mte_buf+64 --show-tags <...> 0xfffff7ff8020: 00 00 00 00 00 00 00 00 0d f0 fe ca 00 00 00 00 ................ (tag: 0x2) <...> (lldb) memory find -e 0xcafef00d mte_buf mte_buf+64 --show-tags data found at location: 0xfffff7ff8028 0xfffff7ff8028: 0d f0 fe ca 00 00 00 00 00 00 00 00 00 00 00 00 ................ (tags: 0x2 0x3) 0xfffff7ff8038: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ (tags: 0x3 0x4) ``` The logic for handling alignments is the same as for memory read so in the above example because the line starts misaligned to the granule it covers 2 granules. Depends on D125089 Reviewed By: omjavaid Differential Revision: https://reviews.llvm.org/D125090 Added: Modified: lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h lldb/source/Commands/CommandObjectMemory.cpp lldb/source/Interpreter/OptionGroupMemoryTag.cpp lldb/test/API/commands/help/TestHelp.py lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py lldb/test/API/linux/aarch64/mte_tag_access/main.c llvm/docs/ReleaseNotes.rst Removed: ################################################################################ diff --git a/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h b/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h index 956ec3f07a9b..918ea3ad96df 100644 --- a/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h +++ b/lldb/include/lldb/Interpreter/OptionGroupMemoryTag.h @@ -16,7 +16,10 @@ namespace lldb_private { class OptionGroupMemoryTag : public OptionGroup { public: - OptionGroupMemoryTag(); + OptionGroupMemoryTag( + // Whether to note that --show-tags does not apply to binary output. + // "memory read" wants this but "memory find" does not. + bool note_binary = false); ~OptionGroupMemoryTag() override = default; @@ -33,6 +36,7 @@ class OptionGroupMemoryTag : public OptionGroup { protected: OptionValueBoolean m_show_tags; + OptionDefinition m_option_definition; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 7005db308806..b7678add5399 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -288,7 +288,7 @@ class CommandObjectMemoryRead : public CommandObjectParsed { "Read from the memory of the current target process.", nullptr, eCommandRequiresTarget | eCommandProcessMustBePaused), m_format_options(eFormatBytesWithASCII, 1, 8), - + m_memory_tag_options(/*note_binary=*/true), m_prev_format_options(eFormatBytesWithASCII, 1, 8) { CommandArgumentEntry arg1; CommandArgumentEntry arg2; @@ -975,6 +975,8 @@ class CommandObjectMemoryFind : public CommandObjectParsed { m_arguments.push_back(arg2); m_option_group.Append(&m_memory_options); + m_option_group.Append(&m_memory_tag_options, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_ALL); m_option_group.Finalize(); } @@ -1139,7 +1141,9 @@ class CommandObjectMemoryFind : public CommandObjectParsed { DumpDataExtractor( data, &result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, - found_location + m_memory_options.m_offset.GetCurrentValue(), 0, 0); + found_location + m_memory_options.m_offset.GetCurrentValue(), 0, 0, + m_exe_ctx.GetBestExecutionContextScope(), + m_memory_tag_options.GetShowTags().GetCurrentValue()); result.GetOutputStream().EOL(); } @@ -1182,6 +1186,7 @@ class CommandObjectMemoryFind : public CommandObjectParsed { OptionGroupOptions m_option_group; OptionGroupFindMemory m_memory_options; + OptionGroupMemoryTag m_memory_tag_options; }; #define LLDB_OPTIONS_memory_write diff --git a/lldb/source/Interpreter/OptionGroupMemoryTag.cpp b/lldb/source/Interpreter/OptionGroupMemoryTag.cpp index f63dfd6bcac6..6752b6c8acf2 100644 --- a/lldb/source/Interpreter/OptionGroupMemoryTag.cpp +++ b/lldb/source/Interpreter/OptionGroupMemoryTag.cpp @@ -13,25 +13,26 @@ using namespace lldb; using namespace lldb_private; -OptionGroupMemoryTag::OptionGroupMemoryTag() : m_show_tags(false, false) {} - static const uint32_t SHORT_OPTION_SHOW_TAGS = 0x54414753; // 'tags' -static constexpr OptionDefinition g_option_table[] = { - {LLDB_OPT_SET_1, - false, - "show-tags", - SHORT_OPTION_SHOW_TAGS, - OptionParser::eNoArgument, - nullptr, - {}, - 0, - eArgTypeNone, - "Include memory tags in output (does not apply to binary output)."}, -}; +OptionGroupMemoryTag::OptionGroupMemoryTag(bool note_binary /*=false*/) + : m_show_tags(false, false), m_option_definition{ + LLDB_OPT_SET_1, + false, + "show-tags", + SHORT_OPTION_SHOW_TAGS, + OptionParser::eNoArgument, + nullptr, + {}, + 0, + eArgTypeNone, + note_binary + ? "Include memory tags in output " + "(does not apply to binary output)." + : "Include memory tags in output."} {} llvm::ArrayRef<OptionDefinition> OptionGroupMemoryTag::GetDefinitions() { - return llvm::makeArrayRef(g_option_table); + return llvm::makeArrayRef(m_option_definition); } Status @@ -40,7 +41,7 @@ OptionGroupMemoryTag::SetOptionValue(uint32_t option_idx, ExecutionContext *execution_context) { assert(option_idx == 0 && "Only one option in memory tag group!"); - switch (g_option_table[0].short_option) { + switch (m_option_definition.short_option) { case SHORT_OPTION_SHOW_TAGS: m_show_tags.SetCurrentValue(true); m_show_tags.SetOptionWasSet(); diff --git a/lldb/test/API/commands/help/TestHelp.py b/lldb/test/API/commands/help/TestHelp.py index 14f4472741bd..e3363e870e5d 100644 --- a/lldb/test/API/commands/help/TestHelp.py +++ b/lldb/test/API/commands/help/TestHelp.py @@ -303,3 +303,13 @@ def test_help_detailed_information_ordering(self): self.assertEqual(sorted(short_options), short_options, "Short option help displayed in an incorrect order!") + + @no_debug_info_test + def test_help_show_tags(self): + """ Check that memory find and memory read have the --show-tags option + but only memory read mentions binary output. """ + self.expect("help memory read", patterns=[ + "--show-tags\n\s+Include memory tags in output " + "\(does not apply to binary output\)."]) + self.expect("help memory find", patterns=[ + "--show-tags\n\s+Include memory tags in output."]) diff --git a/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py b/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py index 8ca5db4a659b..ec5d110461aa 100644 --- a/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py +++ b/lldb/test/API/linux/aarch64/mte_tag_access/TestAArch64LinuxMTEMemoryTagAccess.py @@ -441,3 +441,34 @@ def test_mte_memory_read_tag_display_repeated(self): # A fresh command reverts to the default of tags being off. self.expect("memory read mte_buf mte_buf+16 -f \"x\"", patterns=["0x[0-9A-fa-f]+00: 0x0+ 0x0+ 0x0+ 0x0+"]) + + @skipUnlessArch("aarch64") + @skipUnlessPlatform(["linux"]) + @skipUnlessAArch64MTELinuxCompiler + def test_mte_memory_find(self): + """Test the --show-tags option with memory find.""" + self.setup_mte_test() + + # No result, nothing changes. + self.expect("memory find -s \"foo\" mte_buf mte_buf+32 --show-tags", + substrs=["data not found within the range."]) + + cmd = "memory find -s \"LLDB\" mte_buf+64 mte_buf+512" + found_pattern = "data found at location: 0x[0-9A-Fa-f]+80" + results_patterns = [ + "0x[0-9A-Fa-f]+80: 4c 4c 44 42 (00 )+ LLDB\.+", + "0x[0-9A-Fa-f]+90: 00 00 00 00 (00 )+ \.+" + ] + + # Default is not to show tags + self.expect(cmd, patterns=[found_pattern, *results_patterns]) + self.expect(cmd + " --show-tags", patterns=[found_pattern, + results_patterns[0] + " \(tag: 0x8\)", + results_patterns[1] + " \(tag: 0x9\)"]) + + # Uses the same logic as memory read to handle misalignment. + self.expect("memory find -s \"DB\" mte_buf+64 mte_buf+512 --show-tags", + patterns=[ + "data found at location: 0x[0-9A-Fa-f]+82\n" + "0x[0-9A-Fa-f]+82: 44 42 (00 )+ DB\.+ \(tags: 0x8 0x9\)\n", + "0x[0-9A-Fa-f]+92: 00 00 (00 )+ ..\.+ \(tags: 0x9 0xa\)"]) diff --git a/lldb/test/API/linux/aarch64/mte_tag_access/main.c b/lldb/test/API/linux/aarch64/mte_tag_access/main.c index 5a466b166009..934cce8c3fa6 100644 --- a/lldb/test/API/linux/aarch64/mte_tag_access/main.c +++ b/lldb/test/API/linux/aarch64/mte_tag_access/main.c @@ -2,6 +2,7 @@ #include <asm/hwcap.h> #include <asm/mman.h> #include <stdlib.h> +#include <string.h> #include <sys/auxv.h> #include <sys/mman.h> #include <sys/prctl.h> @@ -53,6 +54,9 @@ int main(int argc, char const *argv[]) { char *non_mte_buf = checked_mmap(page_size, PROT_READ); char *mte_read_only = checked_mmap(page_size, mte_prot); + // Target value for "memory find" testing. + strncpy(mte_buf+128, "LLDB", 4); + // Set incrementing tags until end of the first page char *tagged_ptr = mte_buf; // This ignores tag bits when subtracting the addresses diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 101cec511792..340c30d17776 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -176,6 +176,9 @@ Changes to LLDB memory regions (including unmapped ranges). This is the equivalent of using address 0 then repeating the command until all regions have been listed. +* Added "--show-tags" option to the "memory find" command. This is off by default. + When enabled, if the target value is found in tagged memory, the tags for that + memory will be shown inline with the memory contents. Changes to Sanitizers --------------------- _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits