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