LLDB  mainline
MemoryTagManagerAArch64MTE.cpp
Go to the documentation of this file.
1 //===-- MemoryTagManagerAArch64MTE.cpp --------------------------*- C++ -*-===//
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 
11 using namespace lldb_private;
12 
13 static const unsigned MTE_START_BIT = 56;
14 static const unsigned MTE_TAG_MAX = 0xf;
15 static const unsigned MTE_GRANULE_SIZE = 16;
16 
19  return (addr >> MTE_START_BIT) & MTE_TAG_MAX;
20 }
21 
24  // Here we're ignoring the whole top byte. If you've got MTE
25  // you must also have TBI (top byte ignore).
26  // The other 4 bits could contain other extension bits or
27  // user metadata.
28  return addr & ~((lldb::addr_t)0xFF << MTE_START_BIT);
29 }
30 
32  lldb::addr_t addr2) const {
33  return RemoveNonAddressBits(addr1) - RemoveNonAddressBits(addr2);
34 }
35 
37  return MTE_GRANULE_SIZE;
38 }
39 
41  return eMTE_allocation;
42 }
43 
45 
48  // Ignore reading a length of 0
49  if (!range.IsValid())
50  return range;
51 
52  const size_t granule = GetGranuleSize();
53 
54  // Align start down to granule start
55  lldb::addr_t new_start = range.GetRangeBase();
56  lldb::addr_t align_down_amount = new_start % granule;
57  new_start -= align_down_amount;
58 
59  // Account for the distance we moved the start above
60  size_t new_len = range.GetByteSize() + align_down_amount;
61  // Then align up to the end of the granule
62  size_t align_up_amount = granule - (new_len % granule);
63  if (align_up_amount != granule)
64  new_len += align_up_amount;
65 
66  return TagRange(new_start, new_len);
67 }
68 
69 llvm::Expected<MemoryTagManager::TagRange>
71  lldb::addr_t addr, lldb::addr_t end_addr,
72  const lldb_private::MemoryRegionInfos &memory_regions) const {
73  // First check that the range is not inverted.
74  // We must remove tags here otherwise an address with a higher
75  // tag value will always be > the other.
76  ptrdiff_t len = AddressDiff(end_addr, addr);
77  if (len <= 0) {
78  return llvm::createStringError(
79  llvm::inconvertibleErrorCode(),
80  "End address (0x%" PRIx64
81  ") must be greater than the start address (0x%" PRIx64 ")",
82  end_addr, addr);
83  }
84 
85  // Region addresses will not have memory tags. So when searching
86  // we must use an untagged address.
88  tag_range = ExpandToGranule(tag_range);
89 
90  // Make a copy so we can use the original for errors and the final return.
91  MemoryRegionInfo::RangeType remaining_range(tag_range);
92 
93  // While there are parts of the range that don't have a matching tagged memory
94  // region
95  while (remaining_range.IsValid()) {
96  // Search for a region that contains the start of the range
97  MemoryRegionInfos::const_iterator region = std::find_if(
98  memory_regions.cbegin(), memory_regions.cend(),
99  [&remaining_range](const MemoryRegionInfo &region) {
100  return region.GetRange().Contains(remaining_range.GetRangeBase());
101  });
102 
103  if (region == memory_regions.cend() ||
105  // Some part of this range is untagged (or unmapped) so error
106  return llvm::createStringError(llvm::inconvertibleErrorCode(),
107  "Address range 0x%" PRIx64 ":0x%" PRIx64
108  " is not in a memory tagged region",
109  tag_range.GetRangeBase(),
110  tag_range.GetRangeEnd());
111  }
112 
113  // We've found some part of the range so remove that part and continue
114  // searching for the rest. Moving the base "slides" the range so we need to
115  // save/restore the original end. If old_end is less than the new base, the
116  // range will be set to have 0 size and we'll exit the while.
117  lldb::addr_t old_end = remaining_range.GetRangeEnd();
118  remaining_range.SetRangeBase(region->GetRange().GetRangeEnd());
119  remaining_range.SetRangeEnd(old_end);
120  }
121 
122  // Every part of the range is contained within a tagged memory region.
123  return tag_range;
124 }
125 
126 llvm::Expected<std::vector<lldb::addr_t>>
127 MemoryTagManagerAArch64MTE::UnpackTagsData(const std::vector<uint8_t> &tags,
128  size_t granules /*=0*/) const {
129  // 0 means don't check the number of tags before unpacking
130  if (granules) {
131  size_t num_tags = tags.size() / GetTagSizeInBytes();
132  if (num_tags != granules) {
133  return llvm::createStringError(
134  llvm::inconvertibleErrorCode(),
135  "Packed tag data size does not match expected number of tags. "
136  "Expected %zu tag(s) for %zu granule(s), got %zu tag(s).",
137  granules, granules, num_tags);
138  }
139  }
140 
141  // (if bytes per tag was not 1, we would reconstruct them here)
142 
143  std::vector<lldb::addr_t> unpacked;
144  unpacked.reserve(tags.size());
145  for (auto it = tags.begin(); it != tags.end(); ++it) {
146  // Check all tags are in range
147  if (*it > MTE_TAG_MAX) {
148  return llvm::createStringError(
149  llvm::inconvertibleErrorCode(),
150  "Found tag 0x%x which is > max MTE tag value of 0x%x.", *it,
151  MTE_TAG_MAX);
152  }
153  unpacked.push_back(*it);
154  }
155 
156  return unpacked;
157 }
158 
159 llvm::Expected<std::vector<uint8_t>> MemoryTagManagerAArch64MTE::PackTags(
160  const std::vector<lldb::addr_t> &tags) const {
161  std::vector<uint8_t> packed;
162  packed.reserve(tags.size() * GetTagSizeInBytes());
163 
164  for (auto tag : tags) {
165  if (tag > MTE_TAG_MAX) {
166  return llvm::createStringError(llvm::inconvertibleErrorCode(),
167  "Found tag 0x%" PRIx64
168  " which is > max MTE tag value of 0x%x.",
169  tag, MTE_TAG_MAX);
170  }
171  packed.push_back(static_cast<uint8_t>(tag));
172  }
173 
174  return packed;
175 }
176 
177 llvm::Expected<std::vector<lldb::addr_t>>
179  const std::vector<lldb::addr_t> &tags, TagRange range) const {
180  std::vector<lldb::addr_t> new_tags;
181 
182  // If the range is not empty
183  if (range.IsValid()) {
184  if (tags.empty()) {
185  return llvm::createStringError(
186  llvm::inconvertibleErrorCode(),
187  "Expected some tags to cover given range, got zero.");
188  }
189 
190  // We assume that this range has already been expanded/aligned to granules
191  size_t granules = range.GetByteSize() / GetGranuleSize();
192  new_tags.reserve(granules);
193  for (size_t to_copy = 0; granules > 0; granules -= to_copy) {
194  to_copy = granules > tags.size() ? tags.size() : granules;
195  new_tags.insert(new_tags.end(), tags.begin(), tags.begin() + to_copy);
196  }
197  }
198 
199  return new_tags;
200 }
lldb_private::Range::GetRangeBase
BaseType GetRangeBase() const
Definition: RangeMap.h:46
lldb_private::MemoryTagManagerAArch64MTE::PackTags
llvm::Expected< std::vector< uint8_t > > PackTags(const std::vector< lldb::addr_t > &tags) const override
Definition: MemoryTagManagerAArch64MTE.cpp:159
MTE_START_BIT
static const unsigned MTE_START_BIT
Definition: MemoryTagManagerAArch64MTE.cpp:13
lldb_private::MemoryTagManagerAArch64MTE::UnpackTagsData
llvm::Expected< std::vector< lldb::addr_t > > UnpackTagsData(const std::vector< uint8_t > &tags, size_t granules=0) const override
Definition: MemoryTagManagerAArch64MTE.cpp:127
lldb_private::MemoryRegionInfo
Definition: MemoryRegionInfo.h:21
lldb_private::MemoryTagManagerAArch64MTE::GetLogicalTag
lldb::addr_t GetLogicalTag(lldb::addr_t addr) const override
Definition: MemoryTagManagerAArch64MTE.cpp:18
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::MemoryRegionInfo::GetMemoryTagged
OptionalBool GetMemoryTagged() const
Definition: MemoryRegionInfo.h:52
lldb_private::MemoryTagManagerAArch64MTE::ExpandToGranule
TagRange ExpandToGranule(TagRange range) const override
Definition: MemoryTagManagerAArch64MTE.cpp:47
lldb_private::Range::SetRangeEnd
void SetRangeEnd(BaseType end)
Definition: RangeMap.h:64
lldb_private::Range::IsValid
bool IsValid() const
Definition: RangeMap.h:75
lldb_private::MemoryRegionInfo::eYes
@ eYes
Definition: MemoryRegionInfo.h:25
lldb_private::MemoryRegionInfos
Definition: MemoryRegionInfo.h:164
lldb_private::MemoryTagManagerAArch64MTE::GetAllocationTagType
int32_t GetAllocationTagType() const override
Definition: MemoryTagManagerAArch64MTE.cpp:40
lldb_private::Range< lldb::addr_t, lldb::addr_t >
MemoryTagManagerAArch64MTE.h
lldb_private::MemoryTagManagerAArch64MTE::MakeTaggedRange
llvm::Expected< TagRange > MakeTaggedRange(lldb::addr_t addr, lldb::addr_t end_addr, const lldb_private::MemoryRegionInfos &memory_regions) const override
Definition: MemoryTagManagerAArch64MTE.cpp:70
lldb_private::MemoryTagManagerAArch64MTE::RemoveNonAddressBits
lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const override
Definition: MemoryTagManagerAArch64MTE.cpp:23
lldb_private::MemoryTagManagerAArch64MTE::AddressDiff
ptrdiff_t AddressDiff(lldb::addr_t addr1, lldb::addr_t addr2) const override
Definition: MemoryTagManagerAArch64MTE.cpp:31
lldb_private::MemoryTagManagerAArch64MTE::RepeatTagsForRange
llvm::Expected< std::vector< lldb::addr_t > > RepeatTagsForRange(const std::vector< lldb::addr_t > &tags, TagRange range) const override
Definition: MemoryTagManagerAArch64MTE.cpp:178
lldb_private::Range::SetRangeBase
void SetRangeBase(BaseType b)
Definition: RangeMap.h:48
lldb_private::Range::GetByteSize
SizeType GetByteSize() const
Definition: RangeMap.h:71
MTE_GRANULE_SIZE
static const unsigned MTE_GRANULE_SIZE
Definition: MemoryTagManagerAArch64MTE.cpp:15
lldb_private::MemoryTagManagerAArch64MTE::eMTE_allocation
@ eMTE_allocation
Definition: MemoryTagManagerAArch64MTE.h:22
lldb_private::MemoryRegionInfo::GetRange
RangeType & GetRange()
Definition: MemoryRegionInfo.h:36
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::MemoryTagManagerAArch64MTE::GetTagSizeInBytes
size_t GetTagSizeInBytes() const override
Definition: MemoryTagManagerAArch64MTE.cpp:44
lldb_private::MemoryTagManagerAArch64MTE::GetGranuleSize
lldb::addr_t GetGranuleSize() const override
Definition: MemoryTagManagerAArch64MTE.cpp:36
MTE_TAG_MAX
static const unsigned MTE_TAG_MAX
Definition: MemoryTagManagerAArch64MTE.cpp:14
lldb_private::MemoryTagManager::TagRange
Range< lldb::addr_t, lldb::addr_t > TagRange
Definition: MemoryTagManager.h:30
lldb_private::Range::GetRangeEnd
BaseType GetRangeEnd() const
Definition: RangeMap.h:62