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