MSFBuilder.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- MSFBuilder.h - MSF Directory & Metadata Builder ----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_DEBUGINFO_MSF_MSFBUILDER_H
  14. #define LLVM_DEBUGINFO_MSF_MSFBUILDER_H
  15. #include "llvm/ADT/ArrayRef.h"
  16. #include "llvm/ADT/BitVector.h"
  17. #include "llvm/DebugInfo/MSF/MSFCommon.h"
  18. #include "llvm/Support/Allocator.h"
  19. #include "llvm/Support/Error.h"
  20. #include <cstdint>
  21. #include <utility>
  22. #include <vector>
  23. namespace llvm {
  24. class FileBufferByteStream;
  25. class WritableBinaryStream;
  26. namespace msf {
  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. /// Request the block map to be at a specific block address. This is useful
  62. /// when editing a MSF and you want the layout to be as stable as possible.
  63. Error setBlockMapAddr(uint32_t Addr);
  64. Error setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks);
  65. void setFreePageMap(uint32_t Fpm);
  66. void setUnknown1(uint32_t Unk1);
  67. /// Add a stream to the MSF file with the given size, occupying the given
  68. /// list of blocks. This is useful when reading a MSF file and you want a
  69. /// particular stream to occupy the original set of blocks. If the given
  70. /// blocks are already allocated, or if the number of blocks specified is
  71. /// incorrect for the given stream size, this function will return an Error.
  72. Expected<uint32_t> addStream(uint32_t Size, ArrayRef<uint32_t> Blocks);
  73. /// Add a stream to the MSF file with the given size, occupying any available
  74. /// blocks that the builder decides to use. This is useful when building a
  75. /// new PDB file from scratch and you don't care what blocks a stream occupies
  76. /// but you just want it to work.
  77. Expected<uint32_t> addStream(uint32_t Size);
  78. /// Update the size of an existing stream. This will allocate or deallocate
  79. /// blocks as needed to match the requested size. This can fail if `CanGrow`
  80. /// was set to false when initializing the `MSFBuilder`.
  81. Error setStreamSize(uint32_t Idx, uint32_t Size);
  82. /// Get the total number of streams in the MSF layout. This should return 1
  83. /// for every call to `addStream`.
  84. uint32_t getNumStreams() const;
  85. /// Get the size of a stream by index.
  86. uint32_t getStreamSize(uint32_t StreamIdx) const;
  87. /// Get the list of blocks allocated to a particular stream.
  88. ArrayRef<uint32_t> getStreamBlocks(uint32_t StreamIdx) const;
  89. /// Get the total number of blocks that will be allocated to actual data in
  90. /// this MSF file.
  91. uint32_t getNumUsedBlocks() const;
  92. /// Get the total number of blocks that exist in the MSF file but are not
  93. /// allocated to any valid data.
  94. uint32_t getNumFreeBlocks() const;
  95. /// Get the total number of blocks in the MSF file. In practice this is equal
  96. /// to `getNumUsedBlocks() + getNumFreeBlocks()`.
  97. uint32_t getTotalBlockCount() const;
  98. /// Check whether a particular block is allocated or free.
  99. bool isBlockFree(uint32_t Idx) const;
  100. /// Finalize the layout and build the headers and structures that describe the
  101. /// MSF layout and can be written directly to the MSF file.
  102. Expected<MSFLayout> generateLayout();
  103. /// Write the MSF layout to the underlying file.
  104. Expected<FileBufferByteStream> commit(StringRef Path, MSFLayout &Layout);
  105. BumpPtrAllocator &getAllocator() { return Allocator; }
  106. private:
  107. MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
  108. BumpPtrAllocator &Allocator);
  109. Error allocateBlocks(uint32_t NumBlocks, MutableArrayRef<uint32_t> Blocks);
  110. uint32_t computeDirectoryByteSize() const;
  111. using BlockList = std::vector<uint32_t>;
  112. BumpPtrAllocator &Allocator;
  113. bool IsGrowable;
  114. uint32_t FreePageMap;
  115. uint32_t Unknown1 = 0;
  116. uint32_t BlockSize;
  117. uint32_t BlockMapAddr;
  118. BitVector FreeBlocks;
  119. std::vector<uint32_t> DirectoryBlocks;
  120. std::vector<std::pair<uint32_t, BlockList>> StreamData;
  121. };
  122. } // end namespace msf
  123. } // end namespace llvm
  124. #endif // LLVM_DEBUGINFO_MSF_MSFBUILDER_H
  125. #ifdef __GNUC__
  126. #pragma GCC diagnostic pop
  127. #endif