[pdb/lld] Write a valid FPM.
The PDB reserves certain blocks for the FPM that describe which
blocks in the file are allocated and which are free. We weren't
filling that out at all, and in some cases we were even stomping
it with incorrect data. This patch writes a correct FPM.
Differential Revision: https://reviews.llvm.org/D36235
llvm-svn: 309896
diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
index e0bb460..de460d0 100644
--- a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -150,8 +150,7 @@
MappedBlockStream::createFpmStream(ContainerLayout, *Buffer, Allocator);
BinaryStreamReader FpmReader(*FpmStream);
ArrayRef<uint8_t> FpmBytes;
- if (auto EC = FpmReader.readBytes(FpmBytes,
- msf::getFullFpmByteSize(ContainerLayout)))
+ if (auto EC = FpmReader.readBytes(FpmBytes, FpmReader.bytesRemaining()))
return EC;
uint32_t BlocksRemaining = getBlockCount();
uint32_t BI = 0;
diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index a8b80ac..09e86bf 100644
--- a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -155,6 +155,31 @@
return SN;
}
+void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
+ const MSFLayout &Layout) {
+ auto FpmStream =
+ WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
+
+ // We only need to create the alt fpm stream so that it gets initialized.
+ WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
+ true);
+
+ uint32_t BI = 0;
+ BinaryStreamWriter FpmWriter(*FpmStream);
+ while (BI < Layout.SB->NumBlocks) {
+ uint8_t ThisByte = 0;
+ for (uint32_t I = 0; I < 8; ++I) {
+ bool IsFree =
+ (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
+ uint8_t Mask = uint8_t(IsFree) << I;
+ ThisByte |= Mask;
+ ++BI;
+ }
+ cantFail(FpmWriter.writeObject(ThisByte));
+ }
+ assert(FpmWriter.bytesRemaining() == 0);
+}
+
Error PDBFileBuilder::commit(StringRef Filename) {
assert(!Filename.empty());
auto ExpectedLayout = finalizeMsfLayout();
@@ -173,6 +198,9 @@
if (auto EC = Writer.writeObject(*Layout.SB))
return EC;
+
+ commitFpm(Buffer, Layout);
+
uint32_t BlockMapOffset =
msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
Writer.setOffset(BlockMapOffset);