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