/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Target/MemoryTagManager.h
Line | Count | Source |
1 | | //===-- MemoryTagManager.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_MEMORYTAGMANAGER_H |
10 | | #define LLDB_TARGET_MEMORYTAGMANAGER_H |
11 | | |
12 | | #include "lldb/Target/MemoryRegionInfo.h" |
13 | | #include "lldb/Utility/RangeMap.h" |
14 | | #include "lldb/lldb-private.h" |
15 | | #include "llvm/Support/Error.h" |
16 | | |
17 | | namespace lldb_private { |
18 | | |
19 | | // This interface allows high level commands to handle memory tags |
20 | | // in a generic way. |
21 | | // |
22 | | // Definitions: |
23 | | // logical tag - the tag stored in a pointer |
24 | | // allocation tag - the tag stored in hardware |
25 | | // (e.g. special memory, cache line bits) |
26 | | // granule - number of bytes of memory a single tag applies to |
27 | | |
28 | | class MemoryTagManager { |
29 | | public: |
30 | | typedef Range<lldb::addr_t, lldb::addr_t> TagRange; |
31 | | |
32 | | // Extract the logical tag from a pointer |
33 | | // The tag is returned as a plain value, with any shifts removed. |
34 | | // For example if your tags are stored in bits 56-60 then the logical tag |
35 | | // you get will have been shifted down 56 before being returned. |
36 | | virtual lldb::addr_t GetLogicalTag(lldb::addr_t addr) const = 0; |
37 | | |
38 | | // Remove tag bits from a pointer |
39 | | virtual lldb::addr_t RemoveTagBits(lldb::addr_t addr) const = 0; |
40 | | |
41 | | // Return the difference between two addresses, ignoring any logical tags they |
42 | | // have. If your tags are just part of a larger set of ignored bits, this |
43 | | // should ignore all those bits. |
44 | | virtual ptrdiff_t AddressDiff(lldb::addr_t addr1, |
45 | | lldb::addr_t addr2) const = 0; |
46 | | |
47 | | // Return the number of bytes a single tag covers |
48 | | virtual lldb::addr_t GetGranuleSize() const = 0; |
49 | | |
50 | | // Align an address range to granule boundaries. |
51 | | // So that reading memory tags for the new range returns |
52 | | // tags that will cover the original range. |
53 | | // |
54 | | // Say your granules are 16 bytes and you want |
55 | | // tags for 16 bytes of memory starting from address 8. |
56 | | // 1 granule isn't enough because it only covers addresses |
57 | | // 0-16, we want addresses 8-24. So the range must be |
58 | | // expanded to 2 granules. |
59 | | virtual TagRange ExpandToGranule(TagRange range) const = 0; |
60 | | |
61 | | // Given a range addr to end_addr, check that: |
62 | | // * end_addr >= addr (when memory tags are removed) |
63 | | // * the granule aligned range is completely covered by tagged memory |
64 | | // (which may include one or more memory regions) |
65 | | // |
66 | | // If so, return a modified range which will have been expanded |
67 | | // to be granule aligned. Otherwise return an error. |
68 | | // |
69 | | // Tags in the input addresses are ignored and not present |
70 | | // in the returned range. |
71 | | virtual llvm::Expected<TagRange> MakeTaggedRange( |
72 | | lldb::addr_t addr, lldb::addr_t end_addr, |
73 | | const lldb_private::MemoryRegionInfos &memory_regions) const = 0; |
74 | | |
75 | | // Given a range addr to end_addr, check that end_addr >= addr. |
76 | | // If it is not, return an error saying so. |
77 | | // Otherwise, granule align it and return a set of ranges representing |
78 | | // subsections of the aligned range that have memory tagging enabled. |
79 | | // |
80 | | // Basically a sparse version of MakeTaggedRange. Use this when you |
81 | | // want to know which parts of a larger range have memory tagging. |
82 | | // |
83 | | // Regions in memory_regions should be sorted in ascending order and |
84 | | // not overlap. (use Process GetMemoryRegions) |
85 | | // |
86 | | // Tags in the input addresses are ignored and not present |
87 | | // in the returned ranges. |
88 | | virtual llvm::Expected<std::vector<TagRange>> MakeTaggedRanges( |
89 | | lldb::addr_t addr, lldb::addr_t end_addr, |
90 | | const lldb_private::MemoryRegionInfos &memory_regions) const = 0; |
91 | | |
92 | | // Return the type value to use in GDB protocol qMemTags packets to read |
93 | | // allocation tags. This is named "Allocation" specifically because the spec |
94 | | // allows for logical tags to be read the same way, though we do not use that. |
95 | | // |
96 | | // This value is unique within a given architecture. Meaning that different |
97 | | // tagging schemes within the same architecture should use unique values, |
98 | | // but other architectures can overlap those values. |
99 | | virtual int32_t GetAllocationTagType() const = 0; |
100 | | |
101 | | // Return the number of bytes a single tag will be packed into during |
102 | | // transport. For example an MTE tag is 4 bits but occupies 1 byte during |
103 | | // transport. |
104 | | virtual size_t GetTagSizeInBytes() const = 0; |
105 | | |
106 | | // Unpack tags from their stored format (e.g. gdb qMemTags data) into seperate |
107 | | // tags. |
108 | | // |
109 | | // Checks that each tag is within the expected value range and if granules is |
110 | | // set to non-zero, that the number of tags found matches the number of |
111 | | // granules we expected to cover. |
112 | | virtual llvm::Expected<std::vector<lldb::addr_t>> |
113 | | UnpackTagsData(const std::vector<uint8_t> &tags, |
114 | | size_t granules = 0) const = 0; |
115 | | |
116 | | // Unpack tags from a corefile segment containing compressed tags |
117 | | // (compression that may be different from the one used for GDB transport). |
118 | | // |
119 | | // This method asumes that: |
120 | | // * addr and len have been granule aligned by a tag manager |
121 | | // * addr >= tag_segment_virtual_address |
122 | | // |
123 | | // 'reader' will always be a wrapper around a CoreFile in real use |
124 | | // but allows testing without having to mock a CoreFile. |
125 | | typedef std::function<size_t(lldb::offset_t, size_t, void *)> CoreReaderFn; |
126 | | std::vector<lldb::addr_t> virtual UnpackTagsFromCoreFileSegment( |
127 | | CoreReaderFn reader, lldb::addr_t tag_segment_virtual_address, |
128 | | lldb::addr_t tag_segment_data_address, lldb::addr_t addr, |
129 | | size_t len) const = 0; |
130 | | |
131 | | // Pack uncompressed tags into their storage format (e.g. for gdb QMemTags). |
132 | | // Checks that each tag is within the expected value range. |
133 | | // We do not check the number of tags or range they apply to because |
134 | | // it is up to the remote to repeat them as needed. |
135 | | virtual llvm::Expected<std::vector<uint8_t>> |
136 | | PackTags(const std::vector<lldb::addr_t> &tags) const = 0; |
137 | | |
138 | | // Take a set of tags and repeat them as much as needed to cover the given |
139 | | // range. We assume that this range has been previously expanded/aligned to |
140 | | // granules. (this method is used by lldb-server to implement QMemTags |
141 | | // packet handling) |
142 | | // |
143 | | // If the range is empty, zero tags are returned. |
144 | | // If the range is not empty and... |
145 | | // * there are no tags, an error is returned. |
146 | | // * there are fewer tags than granules, the tags are repeated to fill the |
147 | | // range. |
148 | | // * there are more tags than granules, only the tags required to cover |
149 | | // the range are returned. |
150 | | // |
151 | | // When repeating tags it will not always return a multiple of the original |
152 | | // list. For example if your range is 3 granules and your tags are 1 and 2. |
153 | | // You will get tags 1, 2 and 1 returned. Rather than getting 1, 2, 1, 2, |
154 | | // which would be one too many tags for the range. |
155 | | // |
156 | | // A single tag will just be repeated as you'd expected. Tag 1 over 3 granules |
157 | | // would return 1, 1, 1. |
158 | | virtual llvm::Expected<std::vector<lldb::addr_t>> |
159 | | RepeatTagsForRange(const std::vector<lldb::addr_t> &tags, |
160 | | TagRange range) const = 0; |
161 | | |
162 | 138 | virtual ~MemoryTagManager() = default; |
163 | | }; |
164 | | |
165 | | } // namespace lldb_private |
166 | | |
167 | | #endif // LLDB_TARGET_MEMORYTAGMANAGER_H |