summaryrefslogtreecommitdiff
path: root/lib/DebugInfo/MSF
diff options
context:
space:
mode:
Diffstat (limited to 'lib/DebugInfo/MSF')
-rw-r--r--lib/DebugInfo/MSF/MSFBuilder.cpp49
-rw-r--r--lib/DebugInfo/MSF/MSFCommon.cpp24
-rw-r--r--lib/DebugInfo/MSF/MappedBlockStream.cpp51
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();