1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
//===-- CommandObjectMemoryTag.cpp ----------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "CommandObjectMemoryTag.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Process.h"
using namespace lldb;
using namespace lldb_private;
#define LLDB_OPTIONS_memory_tag_read
#include "CommandOptions.inc"
class CommandObjectMemoryTagRead : public CommandObjectParsed {
public:
CommandObjectMemoryTagRead(CommandInterpreter &interpreter)
: CommandObjectParsed(interpreter, "tag",
"Read memory tags for the given range of memory.",
nullptr,
eCommandRequiresTarget | eCommandRequiresProcess |
eCommandProcessMustBePaused) {
// Address
m_arguments.push_back(
CommandArgumentEntry{CommandArgumentData(eArgTypeAddressOrExpression)});
// Optional end address
m_arguments.push_back(CommandArgumentEntry{
CommandArgumentData(eArgTypeAddressOrExpression, eArgRepeatOptional)});
}
~CommandObjectMemoryTagRead() override = default;
protected:
bool DoExecute(Args &command, CommandReturnObject &result) override {
if ((command.GetArgumentCount() < 1) || (command.GetArgumentCount() > 2)) {
result.AppendError(
"wrong number of arguments; expected at least <address-expression>, "
"at most <address-expression> <end-address-expression>");
return false;
}
Status error;
addr_t start_addr = OptionArgParser::ToAddress(
&m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
if (start_addr == LLDB_INVALID_ADDRESS) {
result.AppendErrorWithFormatv("Invalid address expression, {0}",
error.AsCString());
return false;
}
// Default 1 byte beyond start, rounds up to at most 1 granule later
addr_t end_addr = start_addr + 1;
if (command.GetArgumentCount() > 1) {
end_addr = OptionArgParser::ToAddress(&m_exe_ctx, command[1].ref(),
LLDB_INVALID_ADDRESS, &error);
if (end_addr == LLDB_INVALID_ADDRESS) {
result.AppendErrorWithFormatv("Invalid end address expression, {0}",
error.AsCString());
return false;
}
}
Process *process = m_exe_ctx.GetProcessPtr();
llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
process->GetMemoryTagManager();
if (!tag_manager_or_err) {
result.SetError(Status(tag_manager_or_err.takeError()));
return false;
}
const MemoryTagManager *tag_manager = *tag_manager_or_err;
MemoryRegionInfos memory_regions;
// If this fails the list of regions is cleared, so we don't need to read
// the return status here.
process->GetMemoryRegions(memory_regions);
llvm::Expected<MemoryTagManager::TagRange> tagged_range =
tag_manager->MakeTaggedRange(start_addr, end_addr, memory_regions);
if (!tagged_range) {
result.SetError(Status(tagged_range.takeError()));
return false;
}
llvm::Expected<std::vector<lldb::addr_t>> tags = process->ReadMemoryTags(
tagged_range->GetRangeBase(), tagged_range->GetByteSize());
if (!tags) {
result.SetError(Status(tags.takeError()));
return false;
}
result.AppendMessageWithFormatv("Logical tag: {0:x}",
tag_manager->GetLogicalTag(start_addr));
result.AppendMessage("Allocation tags:");
addr_t addr = tagged_range->GetRangeBase();
for (auto tag : *tags) {
addr_t next_addr = addr + tag_manager->GetGranuleSize();
// Showing tagged adresses here until we have non address bit handling
result.AppendMessageWithFormatv("[{0:x}, {1:x}): {2:x}", addr, next_addr,
tag);
addr = next_addr;
}
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
};
CommandObjectMemoryTag::CommandObjectMemoryTag(CommandInterpreter &interpreter)
: CommandObjectMultiword(
interpreter, "tag", "Commands for manipulating memory tags",
"memory tag <sub-command> [<sub-command-options>]") {
CommandObjectSP read_command_object(
new CommandObjectMemoryTagRead(interpreter));
read_command_object->SetCommandName("memory tag read");
LoadSubCommand("read", read_command_object);
}
CommandObjectMemoryTag::~CommandObjectMemoryTag() = default;
|