1 //===-- MemoryTagMap.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 
9 #include "lldb/Target/MemoryTagMap.h"
10 #include <optional>
11 
12 using namespace lldb_private;
13 
14 MemoryTagMap::MemoryTagMap(const MemoryTagManager *manager)
15     : m_manager(manager) {
16   assert(m_manager && "valid tag manager required to construct a MemoryTagMap");
17 }
18 
19 void MemoryTagMap::InsertTags(lldb::addr_t addr,
20                               const std::vector<lldb::addr_t> tags) {
21   // We're assuming that addr has no non address bits and is granule aligned.
22   size_t granule_size = m_manager->GetGranuleSize();
23   for (auto tag : tags) {
24     m_addr_to_tag[addr] = tag;
25     addr += granule_size;
26   }
27 }
28 
29 bool MemoryTagMap::Empty() const { return m_addr_to_tag.empty(); }
30 
31 std::vector<std::optional<lldb::addr_t>>
32 MemoryTagMap::GetTags(lldb::addr_t addr, size_t len) const {
33   // Addr and len might be unaligned
34   addr = m_manager->RemoveTagBits(addr);
35   MemoryTagManager::TagRange range(addr, len);
36   range = m_manager->ExpandToGranule(range);
37 
38   std::vector<std::optional<lldb::addr_t>> tags;
39   lldb::addr_t end_addr = range.GetRangeEnd();
40   addr = range.GetRangeBase();
41   bool got_valid_tags = false;
42   size_t granule_size = m_manager->GetGranuleSize();
43 
44   for (; addr < end_addr; addr += granule_size) {
45     std::optional<lldb::addr_t> tag = GetTag(addr);
46     tags.push_back(tag);
47     if (tag)
48       got_valid_tags = true;
49   }
50 
51   // To save the caller checking if every item is std::nullopt,
52   // we return an empty vector if we got no tags at all.
53   if (got_valid_tags)
54     return tags;
55   return {};
56 }
57 
58 std::optional<lldb::addr_t> MemoryTagMap::GetTag(lldb::addr_t addr) const {
59   // Here we assume that addr is granule aligned, just like when the tags
60   // were inserted.
61   auto found = m_addr_to_tag.find(addr);
62   if (found == m_addr_to_tag.end())
63     return std::nullopt;
64   return found->second;
65 }
66