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