Coverage Report

Created: 2023-11-11 10:31

/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
141
  virtual ~MemoryTagManager() = default;
163
};
164
165
} // namespace lldb_private
166
167
#endif // LLDB_TARGET_MEMORYTAGMANAGER_H