1321369Sdim//==- MappedBlockStream.h - Discontiguous stream data in an MSF --*- C++ -*-==// 2311116Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6311116Sdim// 7311116Sdim//===----------------------------------------------------------------------===// 8311116Sdim 9311116Sdim#ifndef LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H 10311116Sdim#define LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H 11311116Sdim 12311116Sdim#include "llvm/ADT/ArrayRef.h" 13311116Sdim#include "llvm/ADT/DenseMap.h" 14327952Sdim#include "llvm/DebugInfo/MSF/MSFCommon.h" 15311116Sdim#include "llvm/Support/Allocator.h" 16321369Sdim#include "llvm/Support/BinaryStream.h" 17321369Sdim#include "llvm/Support/BinaryStreamRef.h" 18311116Sdim#include "llvm/Support/Endian.h" 19311116Sdim#include "llvm/Support/Error.h" 20311116Sdim#include <cstdint> 21321369Sdim#include <memory> 22311116Sdim#include <vector> 23311116Sdim 24311116Sdimnamespace llvm { 25311116Sdimnamespace msf { 26311116Sdim 27311116Sdimstruct MSFLayout; 28311116Sdim 29311116Sdim/// MappedBlockStream represents data stored in an MSF file into chunks of a 30311116Sdim/// particular size (called the Block Size), and whose chunks may not be 31311116Sdim/// necessarily contiguous. The arrangement of these chunks MSF the file 32311116Sdim/// is described by some other metadata contained within the MSF file. In 33311116Sdim/// the case of a standard MSF Stream, the layout of the stream's blocks 34311116Sdim/// is described by the MSF "directory", but in the case of the directory 35311116Sdim/// itself, the layout is described by an array at a fixed location within 36311116Sdim/// the MSF. MappedBlockStream provides methods for reading from and writing 37311116Sdim/// to one of these streams transparently, as if it were a contiguous sequence 38311116Sdim/// of bytes. 39321369Sdimclass MappedBlockStream : public BinaryStream { 40311116Sdim friend class WritableMappedBlockStream; 41321369Sdim 42311116Sdimpublic: 43311116Sdim static std::unique_ptr<MappedBlockStream> 44321369Sdim createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, 45321369Sdim BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); 46311116Sdim 47311116Sdim static std::unique_ptr<MappedBlockStream> 48321369Sdim createIndexedStream(const MSFLayout &Layout, BinaryStreamRef MsfData, 49321369Sdim uint32_t StreamIndex, BumpPtrAllocator &Allocator); 50311116Sdim 51311116Sdim static std::unique_ptr<MappedBlockStream> 52321369Sdim createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData, 53321369Sdim BumpPtrAllocator &Allocator); 54311116Sdim 55311116Sdim static std::unique_ptr<MappedBlockStream> 56321369Sdim createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData, 57321369Sdim BumpPtrAllocator &Allocator); 58311116Sdim 59321369Sdim support::endianness getEndian() const override { 60321369Sdim return support::little; 61321369Sdim } 62321369Sdim 63311116Sdim Error readBytes(uint32_t Offset, uint32_t Size, 64321369Sdim ArrayRef<uint8_t> &Buffer) override; 65311116Sdim Error readLongestContiguousChunk(uint32_t Offset, 66321369Sdim ArrayRef<uint8_t> &Buffer) override; 67311116Sdim 68321369Sdim uint32_t getLength() override; 69311116Sdim 70321369Sdim BumpPtrAllocator &getAllocator() { return Allocator; } 71311116Sdim 72311116Sdim void invalidateCache(); 73311116Sdim 74311116Sdim uint32_t getBlockSize() const { return BlockSize; } 75321369Sdim uint32_t getNumBlocks() const { return StreamLayout.Blocks.size(); } 76311116Sdim uint32_t getStreamLength() const { return StreamLayout.Length; } 77311116Sdim 78311116Sdimprotected: 79321369Sdim MappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &StreamLayout, 80321369Sdim BinaryStreamRef MsfData, BumpPtrAllocator &Allocator); 81311116Sdim 82311116Sdimprivate: 83311116Sdim const MSFStreamLayout &getStreamLayout() const { return StreamLayout; } 84311116Sdim void fixCacheAfterWrite(uint32_t Offset, ArrayRef<uint8_t> Data) const; 85311116Sdim 86321369Sdim Error readBytes(uint32_t Offset, MutableArrayRef<uint8_t> Buffer); 87311116Sdim bool tryReadContiguously(uint32_t Offset, uint32_t Size, 88321369Sdim ArrayRef<uint8_t> &Buffer); 89311116Sdim 90311116Sdim const uint32_t BlockSize; 91311116Sdim const MSFStreamLayout StreamLayout; 92321369Sdim BinaryStreamRef MsfData; 93311116Sdim 94321369Sdim using CacheEntry = MutableArrayRef<uint8_t>; 95321369Sdim 96321369Sdim // We just store the allocator by reference. We use this to allocate 97321369Sdim // contiguous memory for things like arrays or strings that cross a block 98321369Sdim // boundary, and this memory is expected to outlive the stream. For example, 99321369Sdim // someone could create a stream, read some stuff, then close the stream, and 100321369Sdim // we would like outstanding references to fields to remain valid since the 101321369Sdim // entire file is mapped anyway. Because of that, the user must supply the 102321369Sdim // allocator to allocate broken records from. 103321369Sdim BumpPtrAllocator &Allocator; 104321369Sdim DenseMap<uint32_t, std::vector<CacheEntry>> CacheMap; 105311116Sdim}; 106311116Sdim 107321369Sdimclass WritableMappedBlockStream : public WritableBinaryStream { 108311116Sdimpublic: 109311116Sdim static std::unique_ptr<WritableMappedBlockStream> 110321369Sdim createStream(uint32_t BlockSize, const MSFStreamLayout &Layout, 111321369Sdim WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator); 112311116Sdim 113311116Sdim static std::unique_ptr<WritableMappedBlockStream> 114321369Sdim createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, 115321369Sdim uint32_t StreamIndex, BumpPtrAllocator &Allocator); 116311116Sdim 117311116Sdim static std::unique_ptr<WritableMappedBlockStream> 118321369Sdim createDirectoryStream(const MSFLayout &Layout, 119321369Sdim WritableBinaryStreamRef MsfData, 120321369Sdim BumpPtrAllocator &Allocator); 121311116Sdim 122311116Sdim static std::unique_ptr<WritableMappedBlockStream> 123321369Sdim createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, 124327952Sdim BumpPtrAllocator &Allocator, bool AltFpm = false); 125311116Sdim 126321369Sdim support::endianness getEndian() const override { 127321369Sdim return support::little; 128321369Sdim } 129321369Sdim 130311116Sdim Error readBytes(uint32_t Offset, uint32_t Size, 131321369Sdim ArrayRef<uint8_t> &Buffer) override; 132311116Sdim Error readLongestContiguousChunk(uint32_t Offset, 133321369Sdim ArrayRef<uint8_t> &Buffer) override; 134321369Sdim uint32_t getLength() override; 135311116Sdim 136321369Sdim Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) override; 137311116Sdim 138321369Sdim Error commit() override; 139311116Sdim 140311116Sdim const MSFStreamLayout &getStreamLayout() const { 141311116Sdim return ReadInterface.getStreamLayout(); 142311116Sdim } 143321369Sdim 144311116Sdim uint32_t getBlockSize() const { return ReadInterface.getBlockSize(); } 145311116Sdim uint32_t getNumBlocks() const { return ReadInterface.getNumBlocks(); } 146311116Sdim uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); } 147311116Sdim 148311116Sdimprotected: 149321369Sdim WritableMappedBlockStream(uint32_t BlockSize, 150311116Sdim const MSFStreamLayout &StreamLayout, 151321369Sdim WritableBinaryStreamRef MsfData, 152321369Sdim BumpPtrAllocator &Allocator); 153311116Sdim 154311116Sdimprivate: 155311116Sdim MappedBlockStream ReadInterface; 156321369Sdim WritableBinaryStreamRef WriteInterface; 157311116Sdim}; 158311116Sdim 159311116Sdim} // end namespace pdb 160311116Sdim} // end namespace llvm 161311116Sdim 162311116Sdim#endif // LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H 163