Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:53

0001 //===-- MemoryTagManager.h --------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_TARGET_MEMORYTAGMANAGER_H
0010 #define LLDB_TARGET_MEMORYTAGMANAGER_H
0011 
0012 #include "lldb/Target/MemoryRegionInfo.h"
0013 #include "lldb/Utility/RangeMap.h"
0014 #include "lldb/lldb-private.h"
0015 #include "llvm/Support/Error.h"
0016 
0017 namespace lldb_private {
0018 
0019 // This interface allows high level commands to handle memory tags
0020 // in a generic way.
0021 //
0022 // Definitions:
0023 //   logical tag    - the tag stored in a pointer
0024 //   allocation tag - the tag stored in hardware
0025 //                    (e.g. special memory, cache line bits)
0026 //   granule        - number of bytes of memory a single tag applies to
0027 
0028 class MemoryTagManager {
0029 public:
0030   typedef Range<lldb::addr_t, lldb::addr_t> TagRange;
0031 
0032   // Extract the logical tag from a pointer
0033   // The tag is returned as a plain value, with any shifts removed.
0034   // For example if your tags are stored in bits 56-60 then the logical tag
0035   // you get will have been shifted down 56 before being returned.
0036   virtual lldb::addr_t GetLogicalTag(lldb::addr_t addr) const = 0;
0037 
0038   // Remove tag bits from a pointer
0039   virtual lldb::addr_t RemoveTagBits(lldb::addr_t addr) const = 0;
0040 
0041   // Return the difference between two addresses, ignoring any logical tags they
0042   // have. If your tags are just part of a larger set of ignored bits, this
0043   // should ignore all those bits.
0044   virtual ptrdiff_t AddressDiff(lldb::addr_t addr1,
0045                                 lldb::addr_t addr2) const = 0;
0046 
0047   // Return the number of bytes a single tag covers
0048   virtual lldb::addr_t GetGranuleSize() const = 0;
0049 
0050   // Align an address range to granule boundaries.
0051   // So that reading memory tags for the new range returns
0052   // tags that will cover the original range.
0053   //
0054   // Say your granules are 16 bytes and you want
0055   // tags for 16 bytes of memory starting from address 8.
0056   // 1 granule isn't enough because it only covers addresses
0057   // 0-16, we want addresses 8-24. So the range must be
0058   // expanded to 2 granules.
0059   virtual TagRange ExpandToGranule(TagRange range) const = 0;
0060 
0061   // Given a range addr to end_addr, check that:
0062   // * end_addr >= addr (when memory tags are removed)
0063   // * the granule aligned range is completely covered by tagged memory
0064   //   (which may include one or more memory regions)
0065   //
0066   // If so, return a modified range which will have been expanded
0067   // to be granule aligned. Otherwise return an error.
0068   //
0069   // Tags in the input addresses are ignored and not present
0070   // in the returned range.
0071   virtual llvm::Expected<TagRange> MakeTaggedRange(
0072       lldb::addr_t addr, lldb::addr_t end_addr,
0073       const lldb_private::MemoryRegionInfos &memory_regions) const = 0;
0074 
0075   // Given a range addr to end_addr, check that end_addr >= addr.
0076   // If it is not, return an error saying so.
0077   // Otherwise, granule align it and return a set of ranges representing
0078   // subsections of the aligned range that have memory tagging enabled.
0079   //
0080   // Basically a sparse version of MakeTaggedRange. Use this when you
0081   // want to know which parts of a larger range have memory tagging.
0082   //
0083   // Regions in memory_regions should be sorted in ascending order and
0084   // not overlap. (use Process GetMemoryRegions)
0085   //
0086   // Tags in the input addresses are ignored and not present
0087   // in the returned ranges.
0088   virtual llvm::Expected<std::vector<TagRange>> MakeTaggedRanges(
0089       lldb::addr_t addr, lldb::addr_t end_addr,
0090       const lldb_private::MemoryRegionInfos &memory_regions) const = 0;
0091 
0092   // Return the type value to use in GDB protocol qMemTags packets to read
0093   // allocation tags. This is named "Allocation" specifically because the spec
0094   // allows for logical tags to be read the same way, though we do not use that.
0095   //
0096   // This value is unique within a given architecture. Meaning that different
0097   // tagging schemes within the same architecture should use unique values,
0098   // but other architectures can overlap those values.
0099   virtual int32_t GetAllocationTagType() const = 0;
0100 
0101   // Return the number of bytes a single tag will be packed into during
0102   // transport. For example an MTE tag is 4 bits but occupies 1 byte during
0103   // transport.
0104   virtual size_t GetTagSizeInBytes() const = 0;
0105 
0106   // Unpack tags from their stored format (e.g. gdb qMemTags data) into separate
0107   // tags.
0108   //
0109   // Checks that each tag is within the expected value range and if granules is
0110   // set to non-zero, that the number of tags found matches the number of
0111   // granules we expected to cover.
0112   virtual llvm::Expected<std::vector<lldb::addr_t>>
0113   UnpackTagsData(const std::vector<uint8_t> &tags,
0114                  size_t granules = 0) const = 0;
0115 
0116   // Unpack tags from a corefile segment containing compressed tags
0117   // (compression that may be different from the one used for GDB transport).
0118   //
0119   // This method asumes that:
0120   // * addr and len have been granule aligned by a tag manager
0121   // * addr >= tag_segment_virtual_address
0122   //
0123   // 'reader' will always be a wrapper around a CoreFile in real use
0124   // but allows testing without having to mock a CoreFile.
0125   typedef std::function<size_t(lldb::offset_t, size_t, void *)> CoreReaderFn;
0126   std::vector<lldb::addr_t> virtual UnpackTagsFromCoreFileSegment(
0127       CoreReaderFn reader, lldb::addr_t tag_segment_virtual_address,
0128       lldb::addr_t tag_segment_data_address, lldb::addr_t addr,
0129       size_t len) const = 0;
0130 
0131   // Pack uncompressed tags into their storage format (e.g. for gdb QMemTags).
0132   // Checks that each tag is within the expected value range.
0133   // We do not check the number of tags or range they apply to because
0134   // it is up to the remote to repeat them as needed.
0135   virtual llvm::Expected<std::vector<uint8_t>>
0136   PackTags(const std::vector<lldb::addr_t> &tags) const = 0;
0137 
0138   // Take a set of tags and repeat them as much as needed to cover the given
0139   // range. We assume that this range has been previously expanded/aligned to
0140   // granules. (this method is used by lldb-server to implement QMemTags
0141   // packet handling)
0142   //
0143   // If the range is empty, zero tags are returned.
0144   // If the range is not empty and...
0145   //   * there are no tags, an error is returned.
0146   //   * there are fewer tags than granules, the tags are repeated to fill the
0147   //     range.
0148   //   * there are more tags than granules, only the tags required to cover
0149   //     the range are returned.
0150   //
0151   // When repeating tags it will not always return a multiple of the original
0152   // list. For example if your range is 3 granules and your tags are 1 and 2.
0153   // You will get tags 1, 2 and 1 returned. Rather than getting 1, 2, 1, 2,
0154   // which would be one too many tags for the range.
0155   //
0156   // A single tag will just be repeated as you'd expected. Tag 1 over 3 granules
0157   // would return 1, 1, 1.
0158   virtual llvm::Expected<std::vector<lldb::addr_t>>
0159   RepeatTagsForRange(const std::vector<lldb::addr_t> &tags,
0160                      TagRange range) const = 0;
0161 
0162   virtual ~MemoryTagManager() = default;
0163 };
0164 
0165 } // namespace lldb_private
0166 
0167 #endif // LLDB_TARGET_MEMORYTAGMANAGER_H