blob: 593d781b990e1ba8b14f50bde15ce30febb80c8d [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//==- MappedBlockStream.h - Discontiguous stream data in an MSF --*- C++ -*-==//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
24namespace llvm {
25namespace msf {
26
27struct 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.
39class MappedBlockStream : public BinaryStream {
40 friend class WritableMappedBlockStream;
41
42public:
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
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
70 BumpPtrAllocator &getAllocator() { return Allocator; }
71
72 void invalidateCache();
73
74 uint32_t getBlockSize() const { return BlockSize; }
75 uint32_t getNumBlocks() const { return StreamLayout.Blocks.size(); }
76 uint32_t getStreamLength() const { return StreamLayout.Length; }
77
78protected:
79 MappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &StreamLayout,
80 BinaryStreamRef MsfData, BumpPtrAllocator &Allocator);
81
82private:
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
107class WritableMappedBlockStream : public WritableBinaryStream {
108public:
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
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
140 const MSFStreamLayout &getStreamLayout() const {
141 return ReadInterface.getStreamLayout();
142 }
143
144 uint32_t getBlockSize() const { return ReadInterface.getBlockSize(); }
145 uint32_t getNumBlocks() const { return ReadInterface.getNumBlocks(); }
146 uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); }
147
148protected:
149 WritableMappedBlockStream(uint32_t BlockSize,
150 const MSFStreamLayout &StreamLayout,
151 WritableBinaryStreamRef MsfData,
152 BumpPtrAllocator &Allocator);
153
154private:
155 MappedBlockStream ReadInterface;
156 WritableBinaryStreamRef WriteInterface;
157};
158
159} // end namespace pdb
160} // end namespace llvm
161
162#endif // LLVM_DEBUGINFO_MSF_MAPPEDBLOCKSTREAM_H