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
17namespace 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.
23class MemoryTagMap {
24public:
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
72private:
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