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