LLDB  mainline
CommandObjectMemoryTag.cpp
Go to the documentation of this file.
1 //===-- CommandObjectMemoryTag.cpp ----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "lldb/Host/OptionParser.h"
15 #include "lldb/Target/Process.h"
16 
17 using namespace lldb;
18 using namespace lldb_private;
19 
20 #define LLDB_OPTIONS_memory_tag_read
21 #include "CommandOptions.inc"
22 
24 public:
26  : CommandObjectParsed(interpreter, "tag",
27  "Read memory tags for the given range of memory."
28  " Mismatched tags will be marked.",
29  nullptr,
30  eCommandRequiresTarget | eCommandRequiresProcess |
31  eCommandProcessMustBePaused) {
32  // Address
33  m_arguments.push_back(
35  // Optional end address
36  m_arguments.push_back(CommandArgumentEntry{
38  }
39 
40  ~CommandObjectMemoryTagRead() override = default;
41 
42 protected:
43  bool DoExecute(Args &command, CommandReturnObject &result) override {
44  if ((command.GetArgumentCount() < 1) || (command.GetArgumentCount() > 2)) {
45  result.AppendError(
46  "wrong number of arguments; expected at least <address-expression>, "
47  "at most <address-expression> <end-address-expression>");
48  return false;
49  }
50 
51  Status error;
52  addr_t start_addr = OptionArgParser::ToAddress(
53  &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
54  if (start_addr == LLDB_INVALID_ADDRESS) {
55  result.AppendErrorWithFormatv("Invalid address expression, {0}",
56  error.AsCString());
57  return false;
58  }
59 
60  // Default 1 byte beyond start, rounds up to at most 1 granule later
61  addr_t end_addr = start_addr + 1;
62 
63  if (command.GetArgumentCount() > 1) {
64  end_addr = OptionArgParser::ToAddress(&m_exe_ctx, command[1].ref(),
66  if (end_addr == LLDB_INVALID_ADDRESS) {
67  result.AppendErrorWithFormatv("Invalid end address expression, {0}",
68  error.AsCString());
69  return false;
70  }
71  }
72 
73  Process *process = m_exe_ctx.GetProcessPtr();
74  llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
75  process->GetMemoryTagManager();
76 
77  if (!tag_manager_or_err) {
78  result.SetError(Status(tag_manager_or_err.takeError()));
79  return false;
80  }
81 
82  const MemoryTagManager *tag_manager = *tag_manager_or_err;
83 
84  MemoryRegionInfos memory_regions;
85  // If this fails the list of regions is cleared, so we don't need to read
86  // the return status here.
87  process->GetMemoryRegions(memory_regions);
88  llvm::Expected<MemoryTagManager::TagRange> tagged_range =
89  tag_manager->MakeTaggedRange(start_addr, end_addr, memory_regions);
90 
91  if (!tagged_range) {
92  result.SetError(Status(tagged_range.takeError()));
93  return false;
94  }
95 
96  llvm::Expected<std::vector<lldb::addr_t>> tags = process->ReadMemoryTags(
97  tagged_range->GetRangeBase(), tagged_range->GetByteSize());
98 
99  if (!tags) {
100  result.SetError(Status(tags.takeError()));
101  return false;
102  }
103 
104  lldb::addr_t logical_tag = tag_manager->GetLogicalTag(start_addr);
105  result.AppendMessageWithFormatv("Logical tag: {0:x}", logical_tag);
106  result.AppendMessage("Allocation tags:");
107 
108  addr_t addr = tagged_range->GetRangeBase();
109  for (auto tag : *tags) {
110  addr_t next_addr = addr + tag_manager->GetGranuleSize();
111  // Showing tagged adresses here until we have non address bit handling
112  result.AppendMessageWithFormatv("[{0:x}, {1:x}): {2:x}{3}", addr,
113  next_addr, tag,
114  logical_tag == tag ? "" : " (mismatch)");
115  addr = next_addr;
116  }
117 
119  return true;
120  }
121 };
122 
123 #define LLDB_OPTIONS_memory_tag_write
124 #include "CommandOptions.inc"
125 
127 public:
129  public:
131 
132  ~OptionGroupTagWrite() override = default;
133 
134  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
135  return llvm::makeArrayRef(g_memory_tag_write_options);
136  }
137 
138  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
139  ExecutionContext *execution_context) override {
140  Status status;
141  const int short_option =
142  g_memory_tag_write_options[option_idx].short_option;
143 
144  switch (short_option) {
145  case 'e':
146  m_end_addr = OptionArgParser::ToAddress(execution_context, option_value,
147  LLDB_INVALID_ADDRESS, &status);
148  break;
149  default:
150  llvm_unreachable("Unimplemented option");
151  }
152 
153  return status;
154  }
155 
156  void OptionParsingStarting(ExecutionContext *execution_context) override {
157  m_end_addr = LLDB_INVALID_ADDRESS;
158  }
159 
161  };
162 
164  : CommandObjectParsed(interpreter, "tag",
165  "Write memory tags starting from the granule that "
166  "contains the given address.",
167  nullptr,
168  eCommandRequiresTarget | eCommandRequiresProcess |
169  eCommandProcessMustBePaused),
170  m_option_group(), m_tag_write_options() {
171  // Address
172  m_arguments.push_back(
174  // One or more tag values
175  m_arguments.push_back(CommandArgumentEntry{
177 
178  m_option_group.Append(&m_tag_write_options);
179  m_option_group.Finalize();
180  }
181 
182  ~CommandObjectMemoryTagWrite() override = default;
183 
184  Options *GetOptions() override { return &m_option_group; }
185 
186 protected:
187  bool DoExecute(Args &command, CommandReturnObject &result) override {
188  if (command.GetArgumentCount() < 2) {
189  result.AppendError("wrong number of arguments; expected "
190  "<address-expression> <tag> [<tag> [...]]");
191  return false;
192  }
193 
194  Status error;
195  addr_t start_addr = OptionArgParser::ToAddress(
196  &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error);
197  if (start_addr == LLDB_INVALID_ADDRESS) {
198  result.AppendErrorWithFormatv("Invalid address expression, {0}",
199  error.AsCString());
200  return false;
201  }
202 
203  command.Shift(); // shift off start address
204 
205  std::vector<lldb::addr_t> tags;
206  for (auto &entry : command) {
207  lldb::addr_t tag_value;
208  // getAsInteger returns true on failure
209  if (entry.ref().getAsInteger(0, tag_value)) {
210  result.AppendErrorWithFormat(
211  "'%s' is not a valid unsigned decimal string value.\n",
212  entry.c_str());
213  return false;
214  }
215  tags.push_back(tag_value);
216  }
217 
218  Process *process = m_exe_ctx.GetProcessPtr();
219  llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
220  process->GetMemoryTagManager();
221 
222  if (!tag_manager_or_err) {
223  result.SetError(Status(tag_manager_or_err.takeError()));
224  return false;
225  }
226 
227  const MemoryTagManager *tag_manager = *tag_manager_or_err;
228 
229  MemoryRegionInfos memory_regions;
230  // If this fails the list of regions is cleared, so we don't need to read
231  // the return status here.
232  process->GetMemoryRegions(memory_regions);
233 
234  // We have to assume start_addr is not granule aligned.
235  // So if we simply made a range:
236  // (start_addr, start_addr + (N * granule_size))
237  // We would end up with a range that isn't N granules but N+1
238  // granules. To avoid this we'll align the start first using the method that
239  // doesn't check memory attributes. (if the final range is untagged we'll
240  // handle that error later)
241  lldb::addr_t aligned_start_addr =
242  tag_manager->ExpandToGranule(MemoryTagManager::TagRange(start_addr, 1))
243  .GetRangeBase();
244 
245  lldb::addr_t end_addr = 0;
246  // When you have an end address you want to align the range like tag read
247  // does. Meaning, align the start down (which we've done) and align the end
248  // up.
249  if (m_tag_write_options.m_end_addr != LLDB_INVALID_ADDRESS)
250  end_addr = m_tag_write_options.m_end_addr;
251  else
252  // Without an end address assume number of tags matches number of granules
253  // to write to
254  end_addr =
255  aligned_start_addr + (tags.size() * tag_manager->GetGranuleSize());
256 
257  // Now we've aligned the start address so if we ask for another range
258  // using the number of tags N, we'll get back a range that is also N
259  // granules in size.
260  llvm::Expected<MemoryTagManager::TagRange> tagged_range =
261  tag_manager->MakeTaggedRange(aligned_start_addr, end_addr,
262  memory_regions);
263 
264  if (!tagged_range) {
265  result.SetError(Status(tagged_range.takeError()));
266  return false;
267  }
268 
269  Status status = process->WriteMemoryTags(tagged_range->GetRangeBase(),
270  tagged_range->GetByteSize(), tags);
271 
272  if (status.Fail()) {
273  result.SetError(status);
274  return false;
275  }
276 
278  return true;
279  }
280 
283 };
284 
285 CommandObjectMemoryTag::CommandObjectMemoryTag(CommandInterpreter &interpreter)
287  interpreter, "tag", "Commands for manipulating memory tags",
288  "memory tag <sub-command> [<sub-command-options>]") {
289  CommandObjectSP read_command_object(
290  new CommandObjectMemoryTagRead(interpreter));
291  read_command_object->SetCommandName("memory tag read");
292  LoadSubCommand("read", read_command_object);
293 
294  CommandObjectSP write_command_object(
295  new CommandObjectMemoryTagWrite(interpreter));
296  write_command_object->SetCommandName("memory tag write");
297  LoadSubCommand("write", write_command_object);
298 }
299 
CommandObjectMemoryTagWrite::m_option_group
OptionGroupOptions m_option_group
Definition: CommandObjectMemoryTag.cpp:281
lldb_private::eArgRepeatOptional
@ eArgRepeatOptional
Definition: lldb-private-enumerations.h:96
lldb_private::CommandObjectParsed
Definition: CommandObject.h:394
lldb_private::Range::GetRangeBase
BaseType GetRangeBase() const
Definition: RangeMap.h:46
lldb_private::ExecutionContext
Definition: ExecutionContext.h:292
OptionGroupFormat.h
lldb_private::CommandReturnObject::SetError
void SetError(const Status &error, const char *fallback_error_cstr=nullptr)
Definition: CommandReturnObject.cpp:107
CommandObjectMemoryTagWrite::DoExecute
bool DoExecute(Args &command, CommandReturnObject &result) override
Definition: CommandObjectMemoryTag.cpp:187
lldb_private::Args::Shift
void Shift()
Shifts the first argument C string value of the array off the argument array.
Definition: Args.cpp:281
lldb_private::Process
Definition: Process.h:340
lldb_private::OptionGroupOptions
Definition: Options.h:255
lldb_private::CommandObject::CommandArgumentData
Definition: CommandObject.h:89
lldb_private::Process::GetMemoryRegions
virtual Status GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list)
Obtain all the mapped memory regions within this process.
Definition: Process.cpp:5886
lldb_private::OptionGroup
Definition: Options.h:233
lldb::eArgTypeAddressOrExpression
@ eArgTypeAddressOrExpression
Definition: lldb-enumerations.h:517
OptionArgParser.h
lldb_private::MemoryTagManager::MakeTaggedRange
virtual llvm::Expected< TagRange > MakeTaggedRange(lldb::addr_t addr, lldb::addr_t end_addr, const lldb_private::MemoryRegionInfos &memory_regions) const =0
lldb::eArgTypeValue
@ eArgTypeValue
Definition: lldb-enumerations.h:593
lldb_private::Args
Definition: Args.h:33
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::eArgRepeatPlus
@ eArgRepeatPlus
Definition: lldb-private-enumerations.h:97
CommandReturnObject.h
lldb_private::CommandReturnObject::AppendErrorWithFormatv
void AppendErrorWithFormatv(const char *format, Args &&... args)
Definition: CommandReturnObject.h:129
lldb_private::MemoryTagManager::GetLogicalTag
virtual lldb::addr_t GetLogicalTag(lldb::addr_t addr) const =0
Process.h
lldb_private::MemoryTagManager
Definition: MemoryTagManager.h:28
lldb_private::CommandObjectMultiword
Definition: CommandObjectMultiword.h:19
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::Options
Definition: Options.h:57
lldb_private::CommandObjectMultiword::LoadSubCommand
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
Definition: CommandObjectMultiword.cpp:80
lldb_private::CommandReturnObject::SetStatus
void SetStatus(lldb::ReturnStatus status)
Definition: CommandReturnObject.cpp:121
lldb_private::Status::Fail
bool Fail() const
Test for error condition.
Definition: Status.cpp:182
CommandObjectMemoryTagWrite::OptionGroupTagWrite
Definition: CommandObjectMemoryTag.cpp:128
lldb_private::MemoryRegionInfos
Definition: MemoryRegionInfo.h:164
CommandObjectMemoryTagWrite::OptionGroupTagWrite::OptionParsingStarting
void OptionParsingStarting(ExecutionContext *execution_context) override
Definition: CommandObjectMemoryTag.cpp:156
CommandObjectMemoryTagWrite
Definition: CommandObjectMemoryTag.cpp:126
CommandObjectMemoryTagWrite::OptionGroupTagWrite::m_end_addr
lldb::addr_t m_end_addr
Definition: CommandObjectMemoryTag.cpp:160
lldb_private::Range< lldb::addr_t, lldb::addr_t >
lldb_private::CommandInterpreter
Definition: CommandInterpreter.h:214
lldb_private::Process::GetMemoryTagManager
llvm::Expected< const MemoryTagManager * > GetMemoryTagManager()
If this architecture and process supports memory tagging, return a tag manager that can be used to ma...
Definition: Process.cpp:6102
CommandObjectMemoryTagRead::CommandObjectMemoryTagRead
CommandObjectMemoryTagRead(CommandInterpreter &interpreter)
Definition: CommandObjectMemoryTag.cpp:25
CommandObjectMemoryTagRead
Definition: CommandObjectMemoryTag.cpp:23
OptionValueString.h
CommandObjectMemoryTag.h
lldb_private::Status
Definition: Status.h:44
CommandObjectMemoryTagWrite::m_tag_write_options
OptionGroupTagWrite m_tag_write_options
Definition: CommandObjectMemoryTag.cpp:282
lldb_private::CommandReturnObject
Definition: CommandReturnObject.h:25
uint32_t
lldb::eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishResult
Definition: lldb-enumerations.h:261
lldb_private::CommandObjectMemoryTag::~CommandObjectMemoryTag
~CommandObjectMemoryTag() override
CommandObjectMemoryTagWrite::OptionGroupTagWrite::GetDefinitions
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Definition: CommandObjectMemoryTag.cpp:134
CommandObjectMemoryTagWrite::CommandObjectMemoryTagWrite
CommandObjectMemoryTagWrite(CommandInterpreter &interpreter)
Definition: CommandObjectMemoryTag.cpp:163
lldb_private::MemoryTagManager::GetGranuleSize
virtual lldb::addr_t GetGranuleSize() const =0
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:86
CommandObjectMemoryTagRead::DoExecute
bool DoExecute(Args &command, CommandReturnObject &result) override
Definition: CommandObjectMemoryTag.cpp:43
lldb_private::CommandReturnObject::AppendErrorWithFormat
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
Definition: CommandReturnObject.cpp:46
lldb_private::Process::ReadMemoryTags
llvm::Expected< std::vector< lldb::addr_t > > ReadMemoryTags(lldb::addr_t addr, size_t len)
Read memory tags for the range addr to addr+len.
Definition: Process.cpp:6121
OptionParser.h
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
CommandObjectMemoryTagWrite::GetOptions
Options * GetOptions() override
Definition: CommandObjectMemoryTag.cpp:184
lldb_private::CommandObject::CommandArgumentEntry
std::vector< CommandArgumentData > CommandArgumentEntry
Definition: CommandObject.h:105
CommandObjectMemoryTagWrite::OptionGroupTagWrite::OptionGroupTagWrite
OptionGroupTagWrite()
Definition: CommandObjectMemoryTag.cpp:130
lldb_private::CommandReturnObject::AppendError
void void AppendError(llvm::StringRef in_string)
Definition: CommandReturnObject.cpp:100
lldb_private::Args::GetArgumentCount
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:118
lldb
Definition: SBAddress.h:15
lldb_private::CommandReturnObject::AppendMessage
void AppendMessage(llvm::StringRef in_string)
Definition: CommandReturnObject.cpp:88
lldb_private::CommandReturnObject::AppendMessageWithFormatv
void void AppendMessageWithFormatv(const char *format, Args &&... args)
Definition: CommandReturnObject.h:119
lldb_private::Process::WriteMemoryTags
Status WriteMemoryTags(lldb::addr_t addr, size_t len, const std::vector< lldb::addr_t > &tags)
Write memory tags for a range of memory.
Definition: Process.cpp:6137
CommandObjectMemoryTagWrite::OptionGroupTagWrite::SetOptionValue
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override
Definition: CommandObjectMemoryTag.cpp:138
lldb_private::MemoryTagManager::ExpandToGranule
virtual TagRange ExpandToGranule(TagRange range) const =0