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