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 non address bits from a pointer 39 virtual lldb::addr_t RemoveNonAddressBits(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. 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 // Return the type value to use in GDB protocol qMemTags packets to read 76 // allocation tags. This is named "Allocation" specifically because the spec 77 // allows for logical tags to be read the same way, though we do not use that. 78 // 79 // This value is unique within a given architecture. Meaning that different 80 // tagging schemes within the same architecture should use unique values, 81 // but other architectures can overlap those values. 82 virtual int32_t GetAllocationTagType() const = 0; 83 84 // Return the number of bytes a single tag will be packed into during 85 // transport. For example an MTE tag is 4 bits but occupies 1 byte during 86 // transport. 87 virtual size_t GetTagSizeInBytes() const = 0; 88 89 // Unpack tags from their stored format (e.g. gdb qMemTags data) into seperate 90 // tags. 91 // 92 // Checks that each tag is within the expected value range and if granules is 93 // set to non-zero, that the number of tags found matches the number of 94 // granules we expected to cover. 95 virtual llvm::Expected<std::vector<lldb::addr_t>> 96 UnpackTagsData(const std::vector<uint8_t> &tags, 97 size_t granules = 0) const = 0; 98 99 // Pack uncompressed tags into their storage format (e.g. for gdb QMemTags). 100 // Checks that each tag is within the expected value range. 101 // We do not check the number of tags or range they apply to because 102 // it is up to the remote to repeat them as needed. 103 virtual llvm::Expected<std::vector<uint8_t>> 104 PackTags(const std::vector<lldb::addr_t> &tags) const = 0; 105 106 // Take a set of tags and repeat them as much as needed to cover the given 107 // range. We assume that this range has been previously expanded/aligned to 108 // granules. (this method is used by lldb-server to implement QMemTags 109 // packet handling) 110 // 111 // If the range is empty, zero tags are returned. 112 // If the range is not empty and... 113 // * there are no tags, an error is returned. 114 // * there are fewer tags than granules, the tags are repeated to fill the 115 // range. 116 // * there are more tags than granules, only the tags required to cover 117 // the range are returned. 118 // 119 // When repeating tags it will not always return a multiple of the original 120 // list. For example if your range is 3 granules and your tags are 1 and 2. 121 // You will get tags 1, 2 and 1 returned. Rather than getting 1, 2, 1, 2, 122 // which would be one too many tags for the range. 123 // 124 // A single tag will just be repeated as you'd expected. Tag 1 over 3 granules 125 // would return 1, 1, 1. 126 virtual llvm::Expected<std::vector<lldb::addr_t>> 127 RepeatTagsForRange(const std::vector<lldb::addr_t> &tags, 128 TagRange range) const = 0; 129 130 virtual ~MemoryTagManager() {} 131 }; 132 133 } // namespace lldb_private 134 135 #endif // LLDB_TARGET_MEMORYTAGMANAGER_H 136