Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- MSFBuilder.h - MSF Directory & Metadata Builder ----------*- 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_MSFBUILDER_H
10
#define LLVM_DEBUGINFO_MSF_MSFBUILDER_H
11
 
12
#include "llvm/ADT/ArrayRef.h"
13
#include "llvm/ADT/BitVector.h"
14
#include "llvm/ADT/StringRef.h"
15
#include "llvm/Support/Allocator.h"
16
#include "llvm/Support/Error.h"
17
#include <cstdint>
18
#include <utility>
19
#include <vector>
20
 
21
namespace llvm {
22
class FileBufferByteStream;
23
namespace msf {
24
 
25
struct MSFLayout;
26
 
27
class MSFBuilder {
28
public:
29
  /// Create a new `MSFBuilder`.
30
  ///
31
  /// \param BlockSize The internal block size used by the PDB file.  See
32
  /// isValidBlockSize() for a list of valid block sizes.
33
  ///
34
  /// \param MinBlockCount Causes the builder to reserve up front space for
35
  /// at least `MinBlockCount` blocks.  This is useful when using `MSFBuilder`
36
  /// to read an existing MSF that you want to write back out later.  The
37
  /// original MSF file's SuperBlock contains the exact number of blocks used
38
  /// by the file, so is a good hint as to how many blocks the new MSF file
39
  /// will contain.  Furthermore, it is actually necessary in this case.  To
40
  /// preserve stability of the file's layout, it is helpful to try to keep
41
  /// all streams mapped to their original block numbers.  To ensure that this
42
  /// is possible, space for all blocks must be allocated beforehand so that
43
  /// streams can be assigned to them.
44
  ///
45
  /// \param CanGrow If true, any operation which results in an attempt to
46
  /// locate a free block when all available blocks have been exhausted will
47
  /// allocate a new block, thereby growing the size of the final MSF file.
48
  /// When false, any such attempt will result in an error.  This is especially
49
  /// useful in testing scenarios when you know your test isn't going to do
50
  /// anything to increase the size of the file, so having an Error returned if
51
  /// it were to happen would catch a programming error
52
  ///
53
  /// \returns an llvm::Error representing whether the operation succeeded or
54
  /// failed.  Currently the only way this can fail is if an invalid block size
55
  /// is specified, or `MinBlockCount` does not leave enough room for the
56
  /// mandatory reserved blocks required by an MSF file.
57
  static Expected<MSFBuilder> create(BumpPtrAllocator &Allocator,
58
                                     uint32_t BlockSize,
59
                                     uint32_t MinBlockCount = 0,
60
                                     bool CanGrow = true);
61
 
62
  /// Request the block map to be at a specific block address.  This is useful
63
  /// when editing a MSF and you want the layout to be as stable as possible.
64
  Error setBlockMapAddr(uint32_t Addr);
65
  Error setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks);
66
  void setFreePageMap(uint32_t Fpm);
67
  void setUnknown1(uint32_t Unk1);
68
 
69
  /// Add a stream to the MSF file with the given size, occupying the given
70
  /// list of blocks.  This is useful when reading a MSF file and you want a
71
  /// particular stream to occupy the original set of blocks.  If the given
72
  /// blocks are already allocated, or if the number of blocks specified is
73
  /// incorrect for the given stream size, this function will return an Error.
74
  Expected<uint32_t> addStream(uint32_t Size, ArrayRef<uint32_t> Blocks);
75
 
76
  /// Add a stream to the MSF file with the given size, occupying any available
77
  /// blocks that the builder decides to use.  This is useful when building a
78
  /// new PDB file from scratch and you don't care what blocks a stream occupies
79
  /// but you just want it to work.
80
  Expected<uint32_t> addStream(uint32_t Size);
81
 
82
  /// Update the size of an existing stream.  This will allocate or deallocate
83
  /// blocks as needed to match the requested size.  This can fail if `CanGrow`
84
  /// was set to false when initializing the `MSFBuilder`.
85
  Error setStreamSize(uint32_t Idx, uint32_t Size);
86
 
87
  /// Get the total number of streams in the MSF layout.  This should return 1
88
  /// for every call to `addStream`.
89
  uint32_t getNumStreams() const;
90
 
91
  /// Get the size of a stream by index.
92
  uint32_t getStreamSize(uint32_t StreamIdx) const;
93
 
94
  /// Get the list of blocks allocated to a particular stream.
95
  ArrayRef<uint32_t> getStreamBlocks(uint32_t StreamIdx) const;
96
 
97
  /// Get the total number of blocks that will be allocated to actual data in
98
  /// this MSF file.
99
  uint32_t getNumUsedBlocks() const;
100
 
101
  /// Get the total number of blocks that exist in the MSF file but are not
102
  /// allocated to any valid data.
103
  uint32_t getNumFreeBlocks() const;
104
 
105
  /// Get the total number of blocks in the MSF file.  In practice this is equal
106
  /// to `getNumUsedBlocks() + getNumFreeBlocks()`.
107
  uint32_t getTotalBlockCount() const;
108
 
109
  /// Check whether a particular block is allocated or free.
110
  bool isBlockFree(uint32_t Idx) const;
111
 
112
  /// Finalize the layout and build the headers and structures that describe the
113
  /// MSF layout and can be written directly to the MSF file.
114
  Expected<MSFLayout> generateLayout();
115
 
116
  /// Write the MSF layout to the underlying file.
117
  Expected<FileBufferByteStream> commit(StringRef Path, MSFLayout &Layout);
118
 
119
  BumpPtrAllocator &getAllocator() { return Allocator; }
120
 
121
private:
122
  MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
123
             BumpPtrAllocator &Allocator);
124
 
125
  Error allocateBlocks(uint32_t NumBlocks, MutableArrayRef<uint32_t> Blocks);
126
  uint32_t computeDirectoryByteSize() const;
127
 
128
  using BlockList = std::vector<uint32_t>;
129
 
130
  BumpPtrAllocator &Allocator;
131
 
132
  bool IsGrowable;
133
  uint32_t FreePageMap;
134
  uint32_t Unknown1 = 0;
135
  uint32_t BlockSize;
136
  uint32_t BlockMapAddr;
137
  BitVector FreeBlocks;
138
  std::vector<uint32_t> DirectoryBlocks;
139
  std::vector<std::pair<uint32_t, BlockList>> StreamData;
140
};
141
 
142
} // end namespace msf
143
} // end namespace llvm
144
 
145
#endif // LLVM_DEBUGINFO_MSF_MSFBUILDER_H