1 //===-- MemoryTagMap.h ------------------------------------------*- 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 
9 #ifndef LLDB_TARGET_MEMORYTAGMAP_H
10 #define LLDB_TARGET_MEMORYTAGMAP_H
11 
12 #include "lldb/Target/MemoryTagManager.h"
13 #include "lldb/lldb-private.h"
14 #include <map>
15 #include <optional>
16 
17 namespace lldb_private {
18 
19 /// MemoryTagMap provides a way to give a sparse read result
20 /// when reading memory tags for a range. This is useful when
21 /// you want to annotate some large memory dump that might include
22 /// tagged memory but you don't know that it is all tagged.
23 class MemoryTagMap {
24 public:
25   /// Init an empty tag map
26   ///
27   /// \param [in] manager
28   ///     Non-null pointer to a memory tag manager.
29   MemoryTagMap(const MemoryTagManager *manager);
30 
31   /// Insert tags into the map starting from addr.
32   ///
33   /// \param [in] addr
34   ///     Start address of the range to insert tags for.
35   ///     This address should be granule aligned and have had
36   ///     any non address bits removed.
37   ///     (ideally you would use the base of the range you used
38   ///     to read the tags in the first place)
39   ///
40   /// \param [in] tags
41   ///     Vector of tags to insert. The first tag will be inserted
42   ///     at addr, the next at addr+granule size and so on until
43   ///     all tags have been inserted.
44   void InsertTags(lldb::addr_t addr, const std::vector<lldb::addr_t> tags);
45 
46   bool Empty() const;
47 
48   /// Lookup memory tags for a range of memory from addr to addr+len.
49   ///
50   /// \param [in] addr
51   ///    The start of the range. This may include non address bits and
52   ///    does not have to be granule aligned.
53   ///
54   /// \param [in] len
55   ///    The length in bytes of the range to read tags for. This does
56   ///    not need to be multiple of the granule size.
57   ///
58   /// \return
59   ///    A vector containing the tags found for the granules in the
60   ///    range. (which is the result of granule aligning the given range)
61   ///
62   ///    Each item in the vector is an optional tag. Meaning that if
63   ///    it is valid then the granule had a tag and if not, it didn't.
64   ///
65   ///    If the range had no tags at all, the vector will be empty.
66   ///    If some of the range was tagged it will have items and some
67   ///    of them may be std::nullopt.
68   ///    (this saves the caller checking whether all items are std::nullopt)
69   std::vector<std::optional<lldb::addr_t>> GetTags(lldb::addr_t addr,
70                                                    size_t len) const;
71 
72 private:
73   /// Lookup the tag for address
74   ///
75   /// \param [in] address
76   ///     The address to lookup a tag for. This should be aligned
77   ///     to a granule boundary.
78   ///
79   /// \return
80   ///     The tag for the granule that address refers to, or std::nullopt
81   ///     if it has no memory tag.
82   std::optional<lldb::addr_t> GetTag(lldb::addr_t addr) const;
83 
84   // A map of granule aligned addresses to their memory tag
85   std::map<lldb::addr_t, lldb::addr_t> m_addr_to_tag;
86 
87   // Memory tag manager used to align addresses and get granule size.
88   // Ideally this would be a const& but only certain architectures will
89   // have a memory tag manager class to provide here. So for a method
90   // returning a MemoryTagMap, std::optional<MemoryTagMap> allows it to handle
91   // architectures without memory tagging. Optionals cannot hold references
92   // so we go with a pointer that we assume will be not be null.
93   const MemoryTagManager *m_manager;
94 };
95 
96 } // namespace lldb_private
97 
98 #endif // LLDB_TARGET_MEMORYTAGMAP_H
99