aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-04 19:20:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-08 19:02:26 +0000
commit81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch)
tree311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp
parent5fff09660e06a66bed6482da9c70df328e16bbb6 (diff)
parent145449b1e420787bb99721a429341fa6be3adfb6 (diff)
Diffstat (limited to 'contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Commands/CommandObjectMemory.cpp274
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 &current_command_args,
- uint32_t index) override {
- return m_cmd_name.c_str();
+ llvm::Optional<std::string> GetRepeatCommand(Args &current_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 &current_command_args,
- uint32_t index) override {
- return m_cmd_name.c_str();
+ llvm::Optional<std::string> GetRepeatCommand(Args &current_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 &current_command_args,
- uint32_t index) override {
+ llvm::Optional<std::string> GetRepeatCommand(Args &current_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