diff options
Diffstat (limited to 'lib/DebugInfo/MSF')
| -rw-r--r-- | lib/DebugInfo/MSF/MSFBuilder.cpp | 49 | ||||
| -rw-r--r-- | lib/DebugInfo/MSF/MSFCommon.cpp | 24 | ||||
| -rw-r--r-- | lib/DebugInfo/MSF/MappedBlockStream.cpp | 51 |
3 files changed, 97 insertions, 27 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; } diff --git a/lib/DebugInfo/MSF/MSFCommon.cpp b/lib/DebugInfo/MSF/MSFCommon.cpp index 1facf5efb4bb..d7e1dcf31a3a 100644 --- a/lib/DebugInfo/MSF/MSFCommon.cpp +++ b/lib/DebugInfo/MSF/MSFCommon.cpp @@ -59,3 +59,27 @@ Error llvm::msf::validateSuperBlock(const SuperBlock &SB) { return Error::success(); } + +MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf, + bool IncludeUnusedFpmData, + bool AltFpm) { + MSFStreamLayout FL; + uint32_t NumFpmIntervals = getNumFpmIntervals(Msf, IncludeUnusedFpmData); + support::ulittle32_t FpmBlock = Msf.SB->FreeBlockMapBlock; + assert(FpmBlock == 1 || FpmBlock == 2); + if (AltFpm) { + // If they requested the alternate FPM, then 2 becomes 1 and 1 becomes 2. + FpmBlock = 3U - FpmBlock; + } + for (uint32_t I = 0; I < NumFpmIntervals; ++I) { + FL.Blocks.push_back(FpmBlock); + FpmBlock += msf::getFpmIntervalLength(Msf); + } + + if (IncludeUnusedFpmData) + FL.Length = NumFpmIntervals * Msf.SB->BlockSize; + else + FL.Length = divideCeil(Msf.SB->NumBlocks, 8); + + return FL; +} diff --git a/lib/DebugInfo/MSF/MappedBlockStream.cpp b/lib/DebugInfo/MSF/MappedBlockStream.cpp index e45f4ae0ed94..dec28eb30697 100644 --- a/lib/DebugInfo/MSF/MappedBlockStream.cpp +++ b/lib/DebugInfo/MSF/MappedBlockStream.cpp @@ -11,7 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/MSF/MSFCommon.h" -#include "llvm/DebugInfo/MSF/MSFStreamLayout.h" +#include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" #include "llvm/Support/MathExtras.h" @@ -36,19 +36,6 @@ public: } // end anonymous namespace -static void initializeFpmStreamLayout(const MSFLayout &Layout, - MSFStreamLayout &FpmLayout) { - uint32_t NumFpmIntervals = msf::getNumFpmIntervals(Layout); - support::ulittle32_t FpmBlock = Layout.SB->FreeBlockMapBlock; - assert(FpmBlock == 1 || FpmBlock == 2); - while (NumFpmIntervals > 0) { - FpmLayout.Blocks.push_back(FpmBlock); - FpmBlock += msf::getFpmIntervalLength(Layout); - --NumFpmIntervals; - } - FpmLayout.Length = msf::getFullFpmByteSize(Layout); -} - using Interval = std::pair<uint32_t, uint32_t>; static Interval intersect(const Interval &I1, const Interval &I2) { @@ -95,15 +82,14 @@ std::unique_ptr<MappedBlockStream> MappedBlockStream::createFpmStream(const MSFLayout &Layout, BinaryStreamRef MsfData, BumpPtrAllocator &Allocator) { - MSFStreamLayout SL; - initializeFpmStreamLayout(Layout, SL); + MSFStreamLayout SL(getFpmStreamLayout(Layout)); return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator); } Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, ArrayRef<uint8_t> &Buffer) { // Make sure we aren't trying to read beyond the end of the stream. - if (auto EC = checkOffset(Offset, Size)) + if (auto EC = checkOffsetForRead(Offset, Size)) return EC; if (tryReadContiguously(Offset, Size, Buffer)) @@ -181,7 +167,7 @@ Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, Error MappedBlockStream::readLongestContiguousChunk(uint32_t Offset, ArrayRef<uint8_t> &Buffer) { // Make sure we aren't trying to read beyond the end of the stream. - if (auto EC = checkOffset(Offset, 1)) + if (auto EC = checkOffsetForRead(Offset, 1)) return EC; uint32_t First = Offset / BlockSize; @@ -257,7 +243,7 @@ Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t OffsetInBlock = Offset % BlockSize; // Make sure we aren't trying to read beyond the end of the stream. - if (auto EC = checkOffset(Offset, Buffer.size())) + if (auto EC = checkOffsetForRead(Offset, Buffer.size())) return EC; uint32_t BytesLeft = Buffer.size(); @@ -362,10 +348,27 @@ WritableMappedBlockStream::createDirectoryStream( std::unique_ptr<WritableMappedBlockStream> WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, - BumpPtrAllocator &Allocator) { - MSFStreamLayout SL; - initializeFpmStreamLayout(Layout, SL); - return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator); + BumpPtrAllocator &Allocator, + bool AltFpm) { + // We only want to give the user a stream containing the bytes of the FPM that + // are actually valid, but we want to initialize all of the bytes, even those + // that come from reserved FPM blocks where the entire block is unused. To do + // this, we first create the full layout, which gives us a stream with all + // bytes and all blocks, and initialize everything to 0xFF (all blocks in the + // file are unused). Then we create the minimal layout (which contains only a + // subset of the bytes previously initialized), and return that to the user. + MSFStreamLayout MinLayout(getFpmStreamLayout(Layout, false, AltFpm)); + + MSFStreamLayout FullLayout(getFpmStreamLayout(Layout, true, AltFpm)); + auto Result = + createStream(Layout.SB->BlockSize, FullLayout, MsfData, Allocator); + if (!Result) + return Result; + std::vector<uint8_t> InitData(Layout.SB->BlockSize, 0xFF); + BinaryStreamWriter Initializer(*Result); + while (Initializer.bytesRemaining() > 0) + cantFail(Initializer.writeBytes(InitData)); + return createStream(Layout.SB->BlockSize, MinLayout, MsfData, Allocator); } Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, @@ -385,7 +388,7 @@ uint32_t WritableMappedBlockStream::getLength() { Error WritableMappedBlockStream::writeBytes(uint32_t Offset, ArrayRef<uint8_t> Buffer) { // Make sure we aren't trying to write beyond the end of the stream. - if (auto EC = checkOffset(Offset, Buffer.size())) + if (auto EC = checkOffsetForWrite(Offset, Buffer.size())) return EC; uint32_t BlockNum = Offset / getBlockSize(); |
