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