summaryrefslogtreecommitdiffstats
path: root/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2016-07-15 22:16:56 +0000
committerZachary Turner <zturner@google.com>2016-07-15 22:16:56 +0000
commitfaa554b2fd6c327cb9cc0ac9983bd3c178f2276c (patch)
tree7cb1be7bc7dfee1244fb8d6767036955aa276875 /llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
parent93be6e8c0ada7f77b93db16c81b2160f82780ae6 (diff)
downloadbcm5719-llvm-faa554b2fd6c327cb9cc0ac9983bd3c178f2276c.tar.gz
bcm5719-llvm-faa554b2fd6c327cb9cc0ac9983bd3c178f2276c.zip
[pdb] Use MsfBuilder to handle the writing PDBs.
Previously we would read a PDB, then write some of it back out, but write the directory, super block, and other pertinent metadata back out unchanged. This generates incorrect PDBs since the amount of data written was not always the same as the amount of data read. This patch changes things to use the newly introduced `MsfBuilder` class to write out a correct and accurate set of Msf metadata for the data *actually* written, which opens up the door for adding and removing type records, symbol records, and other types of data to an existing PDB. llvm-svn: 275627
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp')
-rw-r--r--llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp47
1 files changed, 39 insertions, 8 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp b/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
index ab739d339a9..fecefbfeb8d 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/MsfBuilder.cpp
@@ -24,7 +24,7 @@ MsfBuilder::MsfBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow,
BumpPtrAllocator &Allocator)
: Allocator(Allocator), IsGrowable(CanGrow), BlockSize(BlockSize),
MininumBlocks(MinBlockCount), BlockMapAddr(kDefaultBlockMapAddr),
- FreeBlocks(MinBlockCount + 2U, true) {
+ FreeBlocks(std::max(MinBlockCount, 2U), true) {
FreeBlocks[kSuperBlockBlock] = false;
FreeBlocks[BlockMapAddr] = false;
}
@@ -59,6 +59,25 @@ Error MsfBuilder::setBlockMapAddr(uint32_t Addr) {
return Error::success();
}
+void MsfBuilder::setUnknown0(uint32_t Unk0) { Unknown0 = Unk0; }
+
+void MsfBuilder::setUnknown1(uint32_t Unk1) { Unknown1 = Unk1; }
+
+Error MsfBuilder::setDirectoryBlocksHint(ArrayRef<uint32_t> DirBlocks) {
+ for (auto B : DirectoryBlocks)
+ FreeBlocks[B] = true;
+ for (auto B : DirBlocks) {
+ if (!isBlockFree(B)) {
+ return make_error<RawError>(raw_error_code::unspecified,
+ "Attempt to reuse an allocated block");
+ }
+ FreeBlocks[B] = false;
+ }
+
+ DirectoryBlocks = DirBlocks;
+ return Error::success();
+}
+
Error MsfBuilder::allocateBlocks(uint32_t NumBlocks,
MutableArrayRef<uint32_t> Blocks) {
if (NumBlocks == 0)
@@ -198,16 +217,28 @@ Expected<Layout> MsfBuilder::build() {
L.SB->BlockMapAddr = BlockMapAddr;
L.SB->BlockSize = BlockSize;
L.SB->NumDirectoryBytes = computeDirectoryByteSize();
- L.SB->Unknown0 = 0;
- L.SB->Unknown1 = 0;
+ L.SB->Unknown0 = Unknown0;
+ L.SB->Unknown1 = Unknown1;
uint32_t NumDirectoryBlocks =
bytesToBlocks(L.SB->NumDirectoryBytes, BlockSize);
- // The directory blocks should be re-allocated as a stable pointer.
- std::vector<uint32_t> DirectoryBlocks;
- DirectoryBlocks.resize(NumDirectoryBlocks);
- if (auto EC = allocateBlocks(NumDirectoryBlocks, DirectoryBlocks))
- return std::move(EC);
+ if (NumDirectoryBlocks > DirectoryBlocks.size()) {
+ // Our hint wasn't enough to satisfy the entire directory. Allocate
+ // remaining pages.
+ std::vector<uint32_t> ExtraBlocks;
+ uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
+ ExtraBlocks.resize(NumExtraBlocks);
+ if (auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
+ return std::move(EC);
+ DirectoryBlocks.insert(DirectoryBlocks.end(), ExtraBlocks.begin(),
+ ExtraBlocks.end());
+ } else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
+ uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
+ for (auto B :
+ ArrayRef<uint32_t>(DirectoryBlocks).drop_back(NumUnnecessaryBlocks))
+ FreeBlocks[B] = true;
+ DirectoryBlocks.resize(NumDirectoryBlocks);
+ }
// Don't set the number of blocks in the file until after allocating Blocks
// for
OpenPOWER on IntegriCloud