diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-04 19:20:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:02:26 +0000 |
commit | 81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch) | |
tree | 311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp | |
parent | 5fff09660e06a66bed6482da9c70df328e16bbb6 (diff) | |
parent | 145449b1e420787bb99721a429341fa6be3adfb6 (diff) |
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp | 274 |
1 files changed, 190 insertions, 84 deletions
diff --git a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp index 1033d13f9f26..98fa38f25635 100644 --- a/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp +++ b/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" +#include "lldb/Interpreter/OptionGroupMemoryTag.h" #include "lldb/Interpreter/OptionGroupOutputFile.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionValueLanguage.h" @@ -33,7 +34,6 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/DataBufferHeap.h" -#include "lldb/Utility/DataBufferLLVM.h" #include "lldb/Utility/StreamString.h" #include "llvm/Support/MathExtras.h" #include <cinttypes> @@ -91,10 +91,6 @@ public: error = m_offset.SetValueFromString(option_value); break; - case '\x01': - m_show_tags = true; - break; - default: llvm_unreachable("Unimplemented option"); } @@ -108,7 +104,6 @@ public: m_force = false; m_offset.Clear(); m_language_for_type.Clear(); - m_show_tags = false; } Status FinalizeSettings(Target *target, OptionGroupFormat &format_options) { @@ -282,7 +277,6 @@ public: bool m_force; OptionValueUInt64 m_offset; OptionValueLanguage m_language_for_type; - bool m_show_tags = false; }; // Read memory from the inferior process @@ -294,8 +288,7 @@ public: "Read from the memory of the current target process.", nullptr, eCommandRequiresTarget | eCommandProcessMustBePaused), m_format_options(eFormatBytesWithASCII, 1, 8), - - m_next_addr(LLDB_INVALID_ADDRESS), m_prev_byte_size(0), + m_memory_tag_options(/*note_binary=*/true), m_prev_format_options(eFormatBytesWithASCII, 1, 8) { CommandArgumentEntry arg1; CommandArgumentEntry arg2; @@ -338,6 +331,8 @@ public: m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); m_option_group.Append(&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3); + m_option_group.Append(&m_memory_tag_options, LLDB_OPT_SET_ALL, + LLDB_OPT_SET_ALL); m_option_group.Finalize(); } @@ -345,9 +340,9 @@ public: Options *GetOptions() override { return &m_option_group; } - const char *GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { - return m_cmd_name.c_str(); + llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + return m_cmd_name; } protected: @@ -557,11 +552,13 @@ protected: if (!m_format_options.AnyOptionWasSet() && !m_memory_options.AnyOptionWasSet() && !m_outfile_options.AnyOptionWasSet() && - !m_varobj_options.AnyOptionWasSet()) { + !m_varobj_options.AnyOptionWasSet() && + !m_memory_tag_options.AnyOptionWasSet()) { m_format_options = m_prev_format_options; m_memory_options = m_prev_memory_options; m_outfile_options = m_prev_outfile_options; m_varobj_options = m_prev_varobj_options; + m_memory_tag_options = m_prev_memory_tag_options; } } @@ -595,7 +592,10 @@ protected: return false; } - ABISP abi = m_exe_ctx.GetProcessPtr()->GetABI(); + ABISP abi; + if (Process *proc = m_exe_ctx.GetProcessPtr()) + abi = proc->GetABI(); + if (abi) addr = abi->FixDataAddress(addr); @@ -641,7 +641,7 @@ protected: return false; } - DataBufferSP data_sp; + WritableDataBufferSP data_sp; size_t bytes_read = 0; if (compiler_type.GetOpaqueQualType()) { // Make sure we don't display our type as ASCII bytes like the default @@ -755,6 +755,7 @@ protected: m_prev_memory_options = m_memory_options; m_prev_outfile_options = m_outfile_options; m_prev_varobj_options = m_varobj_options; + m_prev_memory_tag_options = m_memory_tag_options; m_prev_compiler_type = compiler_type; std::unique_ptr<Stream> output_stream_storage; @@ -866,7 +867,7 @@ protected: size_t bytes_dumped = DumpDataExtractor( data, output_stream_p, 0, format, item_byte_size, item_count, num_per_line / target->GetArchitecture().GetDataByteSize(), addr, 0, 0, - exe_scope, m_memory_options.m_show_tags); + exe_scope, m_memory_tag_options.GetShowTags().GetCurrentValue()); m_next_addr = addr + bytes_dumped; output_stream_p->EOL(); return true; @@ -877,12 +878,14 @@ protected: OptionGroupReadMemory m_memory_options; OptionGroupOutputFile m_outfile_options; OptionGroupValueObjectDisplay m_varobj_options; - lldb::addr_t m_next_addr; - lldb::addr_t m_prev_byte_size; + OptionGroupMemoryTag m_memory_tag_options; + lldb::addr_t m_next_addr = LLDB_INVALID_ADDRESS; + lldb::addr_t m_prev_byte_size = 0; OptionGroupFormat m_prev_format_options; OptionGroupReadMemory m_prev_memory_options; OptionGroupOutputFile m_prev_outfile_options; OptionGroupValueObjectDisplay m_prev_varobj_options; + OptionGroupMemoryTag m_prev_memory_tag_options; CompilerType m_prev_compiler_type; }; @@ -975,6 +978,8 @@ public: 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(); } @@ -986,7 +991,7 @@ protected: class ProcessMemoryIterator { public: ProcessMemoryIterator(ProcessSP process_sp, lldb::addr_t base) - : m_process_sp(process_sp), m_base_addr(base), m_is_valid(true) { + : m_process_sp(process_sp), m_base_addr(base) { lldbassert(process_sp.get() != nullptr); } @@ -1010,7 +1015,7 @@ protected: private: ProcessSP m_process_sp; lldb::addr_t m_base_addr; - bool m_is_valid; + bool m_is_valid = true; }; bool DoExecute(Args &command, CommandReturnObject &result) override { // No need to check "process" for validity as eCommandRequiresProcess @@ -1054,9 +1059,14 @@ protected: DataBufferHeap buffer; - if (m_memory_options.m_string.OptionWasSet()) - buffer.CopyData(m_memory_options.m_string.GetStringValue()); - else if (m_memory_options.m_expr.OptionWasSet()) { + if (m_memory_options.m_string.OptionWasSet()) { + llvm::StringRef str = m_memory_options.m_string.GetStringValue(); + if (str.empty()) { + result.AppendError("search string must have non-zero length."); + return false; + } + buffer.CopyData(str); + } else if (m_memory_options.m_expr.OptionWasSet()) { StackFrame *frame = m_exe_ctx.GetFramePtr(); ValueObjectSP result_sp; if ((eExpressionCompleted == @@ -1134,7 +1144,9 @@ protected: 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(); } @@ -1177,6 +1189,7 @@ protected: OptionGroupOptions m_option_group; OptionGroupFindMemory m_memory_options; + OptionGroupMemoryTag m_memory_tag_options; }; #define LLDB_OPTIONS_memory_write @@ -1187,7 +1200,7 @@ class CommandObjectMemoryWrite : public CommandObjectParsed { public: class OptionGroupWriteMemory : public OptionGroup { public: - OptionGroupWriteMemory() {} + OptionGroupWriteMemory() = default; ~OptionGroupWriteMemory() override = default; @@ -1586,9 +1599,9 @@ public: ~CommandObjectMemoryHistory() override = default; - const char *GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { - return m_cmd_name.c_str(); + llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { + return m_cmd_name; } protected: @@ -1638,20 +1651,112 @@ protected: // CommandObjectMemoryRegion #pragma mark CommandObjectMemoryRegion +#define LLDB_OPTIONS_memory_region +#include "CommandOptions.inc" + class CommandObjectMemoryRegion : public CommandObjectParsed { public: + class OptionGroupMemoryRegion : public OptionGroup { + public: + OptionGroupMemoryRegion() : OptionGroup(), m_all(false, false) {} + + ~OptionGroupMemoryRegion() override = default; + + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_memory_region_options); + } + + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, + ExecutionContext *execution_context) override { + Status status; + const int short_option = g_memory_region_options[option_idx].short_option; + + switch (short_option) { + case 'a': + m_all.SetCurrentValue(true); + m_all.SetOptionWasSet(); + break; + default: + llvm_unreachable("Unimplemented option"); + } + + return status; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_all.Clear(); + } + + OptionValueBoolean m_all; + }; + CommandObjectMemoryRegion(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "memory region", "Get information on the memory region containing " "an address in the current target process.", - "memory region ADDR", + "memory region <address-expression> (or --all)", eCommandRequiresProcess | eCommandTryTargetAPILock | - eCommandProcessMustBeLaunched), - m_prev_end_addr(LLDB_INVALID_ADDRESS) {} + eCommandProcessMustBeLaunched) { + // Address in option set 1. + m_arguments.push_back(CommandArgumentEntry{CommandArgumentData( + eArgTypeAddressOrExpression, eArgRepeatPlain, LLDB_OPT_SET_1)}); + // "--all" will go in option set 2. + m_option_group.Append(&m_memory_region_options); + m_option_group.Finalize(); + } ~CommandObjectMemoryRegion() override = default; + Options *GetOptions() override { return &m_option_group; } + protected: + void DumpRegion(CommandReturnObject &result, Target &target, + const MemoryRegionInfo &range_info, lldb::addr_t load_addr) { + lldb_private::Address addr; + ConstString section_name; + if (target.ResolveLoadAddress(load_addr, addr)) { + SectionSP section_sp(addr.GetSection()); + if (section_sp) { + // Got the top most section, not the deepest section + while (section_sp->GetParent()) + section_sp = section_sp->GetParent(); + section_name = section_sp->GetName(); + } + } + + ConstString name = range_info.GetName(); + result.AppendMessageWithFormatv( + "[{0:x16}-{1:x16}) {2:r}{3:w}{4:x}{5}{6}{7}{8}", + range_info.GetRange().GetRangeBase(), + range_info.GetRange().GetRangeEnd(), range_info.GetReadable(), + range_info.GetWritable(), range_info.GetExecutable(), name ? " " : "", + name, section_name ? " " : "", section_name); + MemoryRegionInfo::OptionalBool memory_tagged = range_info.GetMemoryTagged(); + if (memory_tagged == MemoryRegionInfo::OptionalBool::eYes) + result.AppendMessage("memory tagging: enabled"); + + const llvm::Optional<std::vector<addr_t>> &dirty_page_list = + range_info.GetDirtyPageList(); + if (dirty_page_list) { + const size_t page_count = dirty_page_list.getValue().size(); + result.AppendMessageWithFormat( + "Modified memory (dirty) page list provided, %zu entries.\n", + page_count); + if (page_count > 0) { + bool print_comma = false; + result.AppendMessageWithFormat("Dirty pages: "); + for (size_t i = 0; i < page_count; i++) { + if (print_comma) + result.AppendMessageWithFormat(", "); + else + print_comma = true; + result.AppendMessageWithFormat("0x%" PRIx64, (*dirty_page_list)[i]); + } + result.AppendMessageWithFormat(".\n"); + } + } + } + bool DoExecute(Args &command, CommandReturnObject &result) override { ProcessSP process_sp = m_exe_ctx.GetProcessSP(); if (!process_sp) { @@ -1668,6 +1773,13 @@ protected: const lldb::ABISP &abi = process_sp->GetABI(); if (argc == 1) { + if (m_memory_region_options.m_all) { + result.AppendError( + "The \"--all\" option cannot be used when an address " + "argument is given"); + return false; + } + auto load_addr_str = command[0].ref(); // Non-address bits in this will be handled later by GetMemoryRegion load_addr = OptionArgParser::ToAddress(&m_exe_ctx, load_addr_str, @@ -1681,67 +1793,58 @@ protected: // When we're repeating the command, the previous end address is // used for load_addr. If that was 0xF...F then we must have // reached the end of memory. - (argc == 0 && load_addr == LLDB_INVALID_ADDRESS) || + (argc == 0 && !m_memory_region_options.m_all && + load_addr == LLDB_INVALID_ADDRESS) || // If the target has non-address bits (tags, limited virtual // address size, etc.), the end of mappable memory will be lower // than that. So if we find any non-address bit set, we must be // at the end of the mappable range. - (abi && (abi->FixDataAddress(load_addr) != load_addr))) { - result.AppendErrorWithFormat("'%s' takes one argument:\nUsage: %s\n", - m_cmd_name.c_str(), m_cmd_syntax.c_str()); + (abi && (abi->FixAnyAddress(load_addr) != load_addr))) { + result.AppendErrorWithFormat( + "'%s' takes one argument or \"--all\" option:\nUsage: %s\n", + m_cmd_name.c_str(), m_cmd_syntax.c_str()); return false; } - lldb_private::MemoryRegionInfo range_info; - error = process_sp->GetMemoryRegionInfo(load_addr, range_info); - if (error.Success()) { - lldb_private::Address addr; - ConstString name = range_info.GetName(); - ConstString section_name; - if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) { - SectionSP section_sp(addr.GetSection()); - if (section_sp) { - // Got the top most section, not the deepest section - while (section_sp->GetParent()) - section_sp = section_sp->GetParent(); - section_name = section_sp->GetName(); + // Is is important that we track the address used to request the region as + // this will give the correct section name in the case that regions overlap. + // On Windows we get mutliple regions that start at the same place but are + // different sizes and refer to different sections. + std::vector<std::pair<lldb_private::MemoryRegionInfo, lldb::addr_t>> + region_list; + if (m_memory_region_options.m_all) { + // We don't use GetMemoryRegions here because it doesn't include unmapped + // areas like repeating the command would. So instead, emulate doing that. + lldb::addr_t addr = 0; + while (error.Success() && addr != LLDB_INVALID_ADDRESS && + // When there are non-address bits the last range will not extend + // to LLDB_INVALID_ADDRESS but to the max virtual address. + // This prevents us looping forever if that is the case. + (abi && (abi->FixAnyAddress(addr) == addr))) { + lldb_private::MemoryRegionInfo region_info; + error = process_sp->GetMemoryRegionInfo(addr, region_info); + + if (error.Success()) { + region_list.push_back({region_info, addr}); + addr = region_info.GetRange().GetRangeEnd(); } } - result.AppendMessageWithFormatv( - "[{0:x16}-{1:x16}) {2:r}{3:w}{4:x}{5}{6}{7}{8}", - range_info.GetRange().GetRangeBase(), - range_info.GetRange().GetRangeEnd(), range_info.GetReadable(), - range_info.GetWritable(), range_info.GetExecutable(), name ? " " : "", - name, section_name ? " " : "", section_name); - MemoryRegionInfo::OptionalBool memory_tagged = - range_info.GetMemoryTagged(); - if (memory_tagged == MemoryRegionInfo::OptionalBool::eYes) - result.AppendMessage("memory tagging: enabled"); - - const llvm::Optional<std::vector<addr_t>> &dirty_page_list = - range_info.GetDirtyPageList(); - if (dirty_page_list.hasValue()) { - const size_t page_count = dirty_page_list.getValue().size(); - result.AppendMessageWithFormat( - "Modified memory (dirty) page list provided, %zu entries.\n", - page_count); - if (page_count > 0) { - bool print_comma = false; - result.AppendMessageWithFormat("Dirty pages: "); - for (size_t i = 0; i < page_count; i++) { - if (print_comma) - result.AppendMessageWithFormat(", "); - else - print_comma = true; - result.AppendMessageWithFormat("0x%" PRIx64, - dirty_page_list.getValue()[i]); - } - result.AppendMessageWithFormat(".\n"); - } + // Even if we read nothing, don't error for --all + error.Clear(); + } else { + lldb_private::MemoryRegionInfo region_info; + error = process_sp->GetMemoryRegionInfo(load_addr, region_info); + if (error.Success()) + region_list.push_back({region_info, load_addr}); + } + + if (error.Success()) { + for (std::pair<MemoryRegionInfo, addr_t> &range : region_list) { + DumpRegion(result, process_sp->GetTarget(), range.first, range.second); + m_prev_end_addr = range.first.GetRange().GetRangeEnd(); } - m_prev_end_addr = range_info.GetRange().GetRangeEnd(); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -1750,14 +1853,17 @@ protected: return false; } - const char *GetRepeatCommand(Args ¤t_command_args, - uint32_t index) override { + llvm::Optional<std::string> GetRepeatCommand(Args ¤t_command_args, + uint32_t index) override { // If we repeat this command, repeat it without any arguments so we can // show the next memory range - return m_cmd_name.c_str(); + return m_cmd_name; } - lldb::addr_t m_prev_end_addr; + lldb::addr_t m_prev_end_addr = LLDB_INVALID_ADDRESS; + + OptionGroupOptions m_option_group; + OptionGroupMemoryRegion m_memory_region_options; }; // CommandObjectMemory |