aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Core/DumpDataExtractor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core/DumpDataExtractor.cpp')
-rw-r--r--lldb/source/Core/DumpDataExtractor.cpp129
1 files changed, 121 insertions, 8 deletions
diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index 175ffef04a81..211e16a2e033 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -17,6 +17,9 @@
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/MemoryTagManager.h"
+#include "lldb/Target/MemoryTagMap.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
@@ -253,6 +256,85 @@ void DumpFloatingPoint(std::ostringstream &ss, FloatT f) {
ss << f;
}
+static llvm::Optional<MemoryTagMap>
+GetMemoryTags(lldb::addr_t addr, size_t length,
+ ExecutionContextScope *exe_scope) {
+ assert(addr != LLDB_INVALID_ADDRESS);
+
+ if (!exe_scope)
+ return llvm::None;
+
+ TargetSP target_sp = exe_scope->CalculateTarget();
+ if (!target_sp)
+ return llvm::None;
+
+ ProcessSP process_sp = target_sp->CalculateProcess();
+ if (!process_sp)
+ return llvm::None;
+
+ llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
+ process_sp->GetMemoryTagManager();
+ if (!tag_manager_or_err) {
+ llvm::consumeError(tag_manager_or_err.takeError());
+ return llvm::None;
+ }
+
+ MemoryRegionInfos memory_regions;
+ // Don't check return status, list will be just empty if an error happened.
+ process_sp->GetMemoryRegions(memory_regions);
+
+ llvm::Expected<std::vector<MemoryTagManager::TagRange>> tagged_ranges_or_err =
+ (*tag_manager_or_err)
+ ->MakeTaggedRanges(addr, addr + length, memory_regions);
+ // Here we know that our range will not be inverted but we must still check
+ // for an error.
+ if (!tagged_ranges_or_err) {
+ llvm::consumeError(tagged_ranges_or_err.takeError());
+ return llvm::None;
+ }
+ if (tagged_ranges_or_err->empty())
+ return llvm::None;
+
+ MemoryTagMap memory_tag_map(*tag_manager_or_err);
+ for (const MemoryTagManager::TagRange &range : *tagged_ranges_or_err) {
+ llvm::Expected<std::vector<lldb::addr_t>> tags_or_err =
+ process_sp->ReadMemoryTags(range.GetRangeBase(), range.GetByteSize());
+
+ if (tags_or_err)
+ memory_tag_map.InsertTags(range.GetRangeBase(), *tags_or_err);
+ else
+ llvm::consumeError(tags_or_err.takeError());
+ }
+
+ if (memory_tag_map.Empty())
+ return llvm::None;
+
+ return memory_tag_map;
+}
+
+static void
+printMemoryTags(const DataExtractor &DE, Stream *s, lldb::addr_t addr,
+ size_t len,
+ const llvm::Optional<MemoryTagMap> &memory_tag_map) {
+ std::vector<llvm::Optional<lldb::addr_t>> tags =
+ memory_tag_map->GetTags(addr, len);
+
+ // Only print if there is at least one tag for this line
+ if (tags.empty())
+ return;
+
+ s->Printf(" (tag%s:", tags.size() > 1 ? "s" : "");
+ // Some granules may not be tagged but print something for them
+ // so that the ordering remains intact.
+ for (auto tag : tags) {
+ if (tag)
+ s->Printf(" 0x%" PRIx64, *tag);
+ else
+ s->PutCString(" <no tag>");
+ }
+ s->PutCString(")");
+}
+
lldb::offset_t lldb_private::DumpDataExtractor(
const DataExtractor &DE, Stream *s, offset_t start_offset,
lldb::Format item_format, size_t item_byte_size, size_t item_count,
@@ -261,7 +343,7 @@ lldb::offset_t lldb_private::DumpDataExtractor(
// non-zero, the value is a bitfield
uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the
// shift amount to apply to a bitfield
- ExecutionContextScope *exe_scope) {
+ ExecutionContextScope *exe_scope, bool show_memory_tags) {
if (s == nullptr)
return start_offset;
@@ -272,6 +354,11 @@ lldb::offset_t lldb_private::DumpDataExtractor(
offset_t offset = start_offset;
+ llvm::Optional<MemoryTagMap> memory_tag_map = llvm::None;
+ if (show_memory_tags && base_addr != LLDB_INVALID_ADDRESS)
+ memory_tag_map =
+ GetMemoryTags(base_addr, DE.GetByteSize() - offset, exe_scope);
+
if (item_format == eFormatInstruction)
return DumpInstructions(DE, s, exe_scope, start_offset, base_addr,
item_count);
@@ -283,7 +370,10 @@ lldb::offset_t lldb_private::DumpDataExtractor(
lldb::offset_t line_start_offset = start_offset;
for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count;
++count) {
+ // If we are at the beginning or end of a line
+ // Note that the last line is handled outside this for loop.
if ((count % num_per_line) == 0) {
+ // If we are at the end of a line
if (count > 0) {
if (item_format == eFormatBytesWithASCII &&
offset > line_start_offset) {
@@ -295,6 +385,15 @@ lldb::offset_t lldb_private::DumpDataExtractor(
offset - line_start_offset, SIZE_MAX,
LLDB_INVALID_ADDRESS, 0, 0);
}
+
+ if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {
+ size_t line_len = offset - line_start_offset;
+ lldb::addr_t line_base =
+ base_addr +
+ (offset - start_offset - line_len) / DE.getTargetByteSize();
+ printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
+ }
+
s->EOL();
}
if (base_addr != LLDB_INVALID_ADDRESS)
@@ -796,14 +895,28 @@ lldb::offset_t lldb_private::DumpDataExtractor(
}
}
- if (item_format == eFormatBytesWithASCII && offset > line_start_offset) {
- s->Printf("%*s", static_cast<int>(
- (num_per_line - (offset - line_start_offset)) * 3 + 2),
- "");
- DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
- offset - line_start_offset, SIZE_MAX,
- LLDB_INVALID_ADDRESS, 0, 0);
+ // If anything was printed we want to catch the end of the last line.
+ // Since we will exit the for loop above before we get a chance to append to
+ // it normally.
+ if (offset > line_start_offset) {
+ if (item_format == eFormatBytesWithASCII) {
+ s->Printf("%*s",
+ static_cast<int>(
+ (num_per_line - (offset - line_start_offset)) * 3 + 2),
+ "");
+ DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1,
+ offset - line_start_offset, SIZE_MAX,
+ LLDB_INVALID_ADDRESS, 0, 0);
+ }
+
+ if (base_addr != LLDB_INVALID_ADDRESS && memory_tag_map) {
+ size_t line_len = offset - line_start_offset;
+ lldb::addr_t line_base = base_addr + (offset - start_offset - line_len) /
+ DE.getTargetByteSize();
+ printMemoryTags(DE, s, line_base, line_len, memory_tag_map);
+ }
}
+
return offset; // Return the offset at which we ended up
}