1 //==- MappedBlockStream.h - Discontiguous stream data in an MSF --*- 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 LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H 10 #define LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H 11 12 #include "llvm/ADT/ArrayRef.h" 13 #include "llvm/ADT/DenseMap.h" 14 #include "llvm/DebugInfo/MSF/MSFCommon.h" 15 #include "llvm/Support/Allocator.h" 16 #include "llvm/Support/BinaryStream.h" 17 #include "llvm/Support/BinaryStreamRef.h" 18 #include "llvm/Support/Endian.h" 19 #include "llvm/Support/Error.h" 20 #include <cstdint> 21 #include <memory> 22 #include <vector> 23 24 namespace llvm { 25 namespace msf { 26 27 /// MappedBlockStream represents data stored in an MSF file into chunks of a 28 /// particular size (called the Block Size), and whose chunks may not be 29 /// necessarily contiguous. The arrangement of these chunks MSF the file 30 /// is described by some other metadata contained within the MSF file. In 31 /// the case of a standard MSF Stream, the layout of the stream's blocks 32 /// is described by the MSF "directory", but in the case of the directory 33 /// itself, the layout is described by an array at a fixed location within 34 /// the MSF. MappedBlockStream provides methods for reading from and writing 35 /// to one of these streams transparently, as if it were a contiguous sequence 36 /// of bytes. 37 class MappedBlockStream : public BinaryStream { 38 friend class WritableMappedBlockStream; 39 40 public: 41 static std::unique_ptr<MappedBlockStream> 42 createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, 43 BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); 44 45 static std::unique_ptr<MappedBlockStream> 46 createIndexedStream(const MSFLayout &Layout, BinaryStreamRef MsfData, 47 uint32_t StreamIndex, BumpPtrAllocator &Allocator); 48 49 static std::unique_ptr<MappedBlockStream> 50 createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData, 51 BumpPtrAllocator &Allocator); 52 53 static std::unique_ptr<MappedBlockStream> 54 createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData, 55 BumpPtrAllocator &Allocator); 56 57 llvm::endianness getEndian() const override { 58 return llvm::endianness::little; 59 } 60 61 Error readBytes(uint64_t Offset, uint64_t Size, 62 ArrayRef<uint8_t> &Buffer) override; 63 Error readLongestContiguousChunk(uint64_t Offset, 64 ArrayRef<uint8_t> &Buffer) override; 65 66 uint64_t getLength() override; 67 68 BumpPtrAllocator &getAllocator() { return Allocator; } 69 70 void invalidateCache(); 71 72 uint32_t getBlockSize() const { return BlockSize; } 73 uint32_t getNumBlocks() const { return StreamLayout.Blocks.size(); } 74 uint32_t getStreamLength() const { return StreamLayout.Length; } 75 76 protected: 77 MappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &StreamLayout, 78 BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); 79 80 private: 81 const MSFStreamLayout &getStreamLayout() const { return StreamLayout; } 82 void fixCacheAfterWrite(uint64_t Offset, ArrayRef<uint8_t> Data) const; 83 84 Error readBytes(uint64_t Offset, MutableArrayRef<uint8_t> Buffer); 85 bool tryReadContiguously(uint64_t Offset, uint64_t Size, 86 ArrayRef<uint8_t> &Buffer); 87 88 const uint32_t BlockSize; 89 const MSFStreamLayout StreamLayout; 90 BinaryStreamRef MsfData; 91 92 using CacheEntry = MutableArrayRef<uint8_t>; 93 94 // We just store the allocator by reference. We use this to allocate 95 // contiguous memory for things like arrays or strings that cross a block 96 // boundary, and this memory is expected to outlive the stream. For example, 97 // someone could create a stream, read some stuff, then close the stream, and 98 // we would like outstanding references to fields to remain valid since the 99 // entire file is mapped anyway. Because of that, the user must supply the 100 // allocator to allocate broken records from. 101 BumpPtrAllocator &Allocator; 102 DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; 103 }; 104 105 class WritableMappedBlockStream : public WritableBinaryStream { 106 public: 107 static std::unique_ptr<WritableMappedBlockStream> 108 createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, 109 WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator); 110 111 static std::unique_ptr<WritableMappedBlockStream> 112 createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, 113 uint32_t StreamIndex, BumpPtrAllocator &Allocator); 114 115 static std::unique_ptr<WritableMappedBlockStream> 116 createDirectoryStream(const MSFLayout &Layout, 117 WritableBinaryStreamRef MsfData, 118 BumpPtrAllocator &Allocator); 119 120 static std::unique_ptr<WritableMappedBlockStream> 121 createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, 122 BumpPtrAllocator &Allocator, bool AltFpm = false); 123 124 llvm::endianness getEndian() const override { 125 return llvm::endianness::little; 126 } 127 128 Error readBytes(uint64_t Offset, uint64_t Size, 129 ArrayRef<uint8_t> &Buffer) override; 130 Error readLongestContiguousChunk(uint64_t Offset, 131 ArrayRef<uint8_t> &Buffer) override; 132 uint64_t getLength() override; 133 134 Error writeBytes(uint64_t Offset, ArrayRef<uint8_t> Buffer) override; 135 136 Error commit() override; 137 138 const MSFStreamLayout &getStreamLayout() const { 139 return ReadInterface.getStreamLayout(); 140 } 141 142 uint32_t getBlockSize() const { return ReadInterface.getBlockSize(); } 143 uint32_t getNumBlocks() const { return ReadInterface.getNumBlocks(); } 144 uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); } 145 146 protected: 147 WritableMappedBlockStream(uint32_t BlockSize, 148 const MSFStreamLayout &StreamLayout, 149 WritableBinaryStreamRef MsfData, 150 BumpPtrAllocator &Allocator); 151 152 private: 153 MappedBlockStream ReadInterface; 154 WritableBinaryStreamRef WriteInterface; 155 }; 156 157 } // namespace msf 158 } // end namespace llvm 159 160 #endif // LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H 161