1 //==- MappedBlockStream.h - Discontiguous stream data in an MSF --*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H
10 #define LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H
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"
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
39 class MappedBlockStream
: public BinaryStream
{
40 friend class WritableMappedBlockStream
;
43 static std::unique_ptr
<MappedBlockStream
>
44 createStream(uint32_t BlockSize
, const MSFStreamLayout
&Layout
,
45 BinaryStreamRef MsfData
, BumpPtrAllocator
&Allocator
);
47 static std::unique_ptr
<MappedBlockStream
>
48 createIndexedStream(const MSFLayout
&Layout
, BinaryStreamRef MsfData
,
49 uint32_t StreamIndex
, BumpPtrAllocator
&Allocator
);
51 static std::unique_ptr
<MappedBlockStream
>
52 createFpmStream(const MSFLayout
&Layout
, BinaryStreamRef MsfData
,
53 BumpPtrAllocator
&Allocator
);
55 static std::unique_ptr
<MappedBlockStream
>
56 createDirectoryStream(const MSFLayout
&Layout
, BinaryStreamRef MsfData
,
57 BumpPtrAllocator
&Allocator
);
59 support::endianness
getEndian() const override
{
60 return support::little
;
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
;
68 uint32_t getLength() override
;
70 BumpPtrAllocator
&getAllocator() { return Allocator
; }
72 void invalidateCache();
74 uint32_t getBlockSize() const { return BlockSize
; }
75 uint32_t getNumBlocks() const { return StreamLayout
.Blocks
.size(); }
76 uint32_t getStreamLength() const { return StreamLayout
.Length
; }
79 MappedBlockStream(uint32_t BlockSize
, const MSFStreamLayout
&StreamLayout
,
80 BinaryStreamRef MsfData
, BumpPtrAllocator
&Allocator
);
83 const MSFStreamLayout
&getStreamLayout() const { return StreamLayout
; }
84 void fixCacheAfterWrite(uint32_t Offset
, ArrayRef
<uint8_t> Data
) const;
86 Error
readBytes(uint32_t Offset
, MutableArrayRef
<uint8_t> Buffer
);
87 bool tryReadContiguously(uint32_t Offset
, uint32_t Size
,
88 ArrayRef
<uint8_t> &Buffer
);
90 const uint32_t BlockSize
;
91 const MSFStreamLayout StreamLayout
;
92 BinaryStreamRef MsfData
;
94 using CacheEntry
= MutableArrayRef
<uint8_t>;
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
;
107 class WritableMappedBlockStream
: public WritableBinaryStream
{
109 static std::unique_ptr
<WritableMappedBlockStream
>
110 createStream(uint32_t BlockSize
, const MSFStreamLayout
&Layout
,
111 WritableBinaryStreamRef MsfData
, BumpPtrAllocator
&Allocator
);
113 static std::unique_ptr
<WritableMappedBlockStream
>
114 createIndexedStream(const MSFLayout
&Layout
, WritableBinaryStreamRef MsfData
,
115 uint32_t StreamIndex
, BumpPtrAllocator
&Allocator
);
117 static std::unique_ptr
<WritableMappedBlockStream
>
118 createDirectoryStream(const MSFLayout
&Layout
,
119 WritableBinaryStreamRef MsfData
,
120 BumpPtrAllocator
&Allocator
);
122 static std::unique_ptr
<WritableMappedBlockStream
>
123 createFpmStream(const MSFLayout
&Layout
, WritableBinaryStreamRef MsfData
,
124 BumpPtrAllocator
&Allocator
, bool AltFpm
= false);
126 support::endianness
getEndian() const override
{
127 return support::little
;
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
;
136 Error
writeBytes(uint32_t Offset
, ArrayRef
<uint8_t> Buffer
) override
;
138 Error
commit() override
;
140 const MSFStreamLayout
&getStreamLayout() const {
141 return ReadInterface
.getStreamLayout();
144 uint32_t getBlockSize() const { return ReadInterface
.getBlockSize(); }
145 uint32_t getNumBlocks() const { return ReadInterface
.getNumBlocks(); }
146 uint32_t getStreamLength() const { return ReadInterface
.getStreamLength(); }
149 WritableMappedBlockStream(uint32_t BlockSize
,
150 const MSFStreamLayout
&StreamLayout
,
151 WritableBinaryStreamRef MsfData
,
152 BumpPtrAllocator
&Allocator
);
155 MappedBlockStream ReadInterface
;
156 WritableBinaryStreamRef WriteInterface
;
159 } // end namespace pdb
160 } // end namespace llvm
162 #endif // LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H