diff options
Diffstat (limited to 'lib/DebugInfo/MSF/MSFBuilder.cpp')
| -rw-r--r-- | lib/DebugInfo/MSF/MSFBuilder.cpp | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/lib/DebugInfo/MSF/MSFBuilder.cpp b/lib/DebugInfo/MSF/MSFBuilder.cpp index 0f4f785abf55..9cd22ab7d887 100644 --- a/lib/DebugInfo/MSF/MSFBuilder.cpp +++ b/lib/DebugInfo/MSF/MSFBuilder.cpp @@ -36,8 +36,7 @@ MSFBuilder::MSFBuilder(uint32_t BlockSize, uint32_t MinBlockCount, bool CanGrow, BumpPtrAllocator &Allocator) : Allocator(Allocator), IsGrowable(CanGrow), FreePageMap(kDefaultFreePageMap), BlockSize(BlockSize), - MininumBlocks(MinBlockCount), BlockMapAddr(kDefaultBlockMapAddr), - FreeBlocks(MinBlockCount, true) { + BlockMapAddr(kDefaultBlockMapAddr), FreeBlocks(MinBlockCount, true) { FreeBlocks[kSuperBlockBlock] = false; FreeBlocks[kFreePageMap0Block] = false; FreeBlocks[kFreePageMap1Block] = false; @@ -107,7 +106,23 @@ Error MSFBuilder::allocateBlocks(uint32_t NumBlocks, return make_error<MSFError>(msf_error_code::insufficient_buffer, "There are no free Blocks in the file"); uint32_t AllocBlocks = NumBlocks - NumFreeBlocks; - FreeBlocks.resize(AllocBlocks + FreeBlocks.size(), true); + uint32_t OldBlockCount = FreeBlocks.size(); + uint32_t NewBlockCount = AllocBlocks + OldBlockCount; + uint32_t NextFpmBlock = alignTo(OldBlockCount, BlockSize) + 1; + FreeBlocks.resize(NewBlockCount, true); + // If we crossed over an fpm page, we actually need to allocate 2 extra + // blocks for each FPM group crossed and mark both blocks from the group as + // used. We may not actually use them since there are many more FPM blocks + // present than are required to represent all blocks in a given PDB, but we + // need to make sure they aren't allocated to a stream or something else. + // At the end when committing the PDB, we'll go through and mark the + // extraneous ones unused. + while (NextFpmBlock < NewBlockCount) { + NewBlockCount += 2; + FreeBlocks.resize(NewBlockCount, true); + FreeBlocks.reset(NextFpmBlock, NextFpmBlock + 2); + NextFpmBlock += BlockSize; + } } int I = 0; @@ -229,6 +244,19 @@ uint32_t MSFBuilder::computeDirectoryByteSize() const { return Size; } +static void finalizeFpmBlockStatus(uint32_t B, ArrayRef<ulittle32_t> &FpmBlocks, + BitVector &Fpm) { + if (FpmBlocks.empty() || FpmBlocks.front() != B) { + Fpm.set(B); + return; + } + + // If the next block in the actual layout is this block, it should *not* be + // free. + assert(!Fpm.test(B)); + FpmBlocks = FpmBlocks.drop_front(); +} + Expected<MSFLayout> MSFBuilder::build() { SuperBlock *SB = Allocator.Allocate<SuperBlock>(); MSFLayout L; @@ -287,5 +315,20 @@ Expected<MSFLayout> MSFBuilder::build() { } } + // FPM blocks occur in pairs at every `BlockLength` interval. While blocks of + // this form are reserved for FPM blocks, not all blocks of this form will + // actually be needed for FPM data because there are more blocks of this form + // than are required to represent a PDB file with a given number of blocks. + // So we need to find out which blocks are *actually* going to be real FPM + // blocks, then mark the reset of the reserved blocks as unallocated. + MSFStreamLayout FpmLayout = msf::getFpmStreamLayout(L, true); + auto FpmBlocks = makeArrayRef(FpmLayout.Blocks); + for (uint32_t B = kFreePageMap0Block; B < SB->NumBlocks; + B += msf::getFpmIntervalLength(L)) { + finalizeFpmBlockStatus(B, FpmBlocks, FreeBlocks); + finalizeFpmBlockStatus(B + 1, FpmBlocks, FreeBlocks); + } + L.FreePageMap = FreeBlocks; + return L; } |
