MSFBuilder.h 6.1 KB

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