Index: llvm/trunk/include/llvm/DebugInfo/MSF/MSFCommon.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/MSF/MSFCommon.h +++ llvm/trunk/include/llvm/DebugInfo/MSF/MSFCommon.h @@ -84,6 +84,19 @@ return BlockNumber * BlockSize; } +inline uint32_t getFpmIntervalLength(const MSFLayout &L) { + return L.SB->BlockSize; +} + +inline uint32_t getNumFpmIntervals(const MSFLayout &L) { + uint32_t Length = getFpmIntervalLength(L); + return llvm::alignTo(L.SB->NumBlocks, Length) / Length; +} + +inline uint32_t getFullFpmByteSize(const MSFLayout &L) { + return llvm::alignTo(L.SB->NumBlocks, 8) / 8; +} + Error validateSuperBlock(const SuperBlock &SB); } // namespace msf } // namespace llvm Index: llvm/trunk/include/llvm/DebugInfo/MSF/MSFStreamLayout.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/MSF/MSFStreamLayout.h +++ llvm/trunk/include/llvm/DebugInfo/MSF/MSFStreamLayout.h @@ -10,10 +10,10 @@ #ifndef LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H #define LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H -#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" #include +#include namespace llvm { namespace msf { @@ -27,7 +27,7 @@ class MSFStreamLayout { public: uint32_t Length; - ArrayRef Blocks; + std::vector Blocks; }; } // namespace msf } // namespace llvm Index: llvm/trunk/include/llvm/DebugInfo/MSF/MappedBlockStream.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/MSF/MappedBlockStream.h +++ llvm/trunk/include/llvm/DebugInfo/MSF/MappedBlockStream.h @@ -39,7 +39,6 @@ /// of bytes. class MappedBlockStream : public ReadableStream { friend class WritableMappedBlockStream; - public: static std::unique_ptr createStream(uint32_t BlockSize, uint32_t NumBlocks, @@ -50,6 +49,9 @@ uint32_t StreamIndex); static std::unique_ptr + createFpmStream(const MSFLayout &Layout, const ReadableStream &MsfData); + + static std::unique_ptr createDirectoryStream(const MSFLayout &Layout, const ReadableStream &MsfData); Error readBytes(uint32_t Offset, uint32_t Size, @@ -105,6 +107,9 @@ static std::unique_ptr createDirectoryStream(const MSFLayout &Layout, const WritableStream &MsfData); + static std::unique_ptr + createFpmStream(const MSFLayout &Layout, const WritableStream &MsfData); + Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef &Buffer) const override; Error readLongestContiguousChunk(uint32_t Offset, Index: llvm/trunk/lib/DebugInfo/MSF/MappedBlockStream.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/MSF/MappedBlockStream.cpp +++ llvm/trunk/lib/DebugInfo/MSF/MappedBlockStream.cpp @@ -26,6 +26,19 @@ }; } +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); +} + typedef std::pair Interval; static Interval intersect(const Interval &I1, const Interval &I2) { return std::make_pair(std::max(I1.first, I2.first), @@ -66,6 +79,14 @@ return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData); } +std::unique_ptr +MappedBlockStream::createFpmStream(const MSFLayout &Layout, + const ReadableStream &MsfData) { + MSFStreamLayout SL; + initializeFpmStreamLayout(Layout, SL); + return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData); +} + Error MappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, ArrayRef &Buffer) const { // Make sure we aren't trying to read beyond the end of the stream. @@ -324,6 +345,14 @@ return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData); } +std::unique_ptr +WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout, + const WritableStream &MsfData) { + MSFStreamLayout SL; + initializeFpmStreamLayout(Layout, SL); + return createStream(Layout.SB->BlockSize, Layout.SB->NumBlocks, SL, MsfData); +} + Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size, ArrayRef &Buffer) const { return ReadInterface.readBytes(Offset, Size, Buffer); Index: llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -122,7 +122,6 @@ // Initialize Free Page Map. ContainerLayout.FreePageMap.resize(SB->NumBlocks); - ArrayRef FpmBytes; // The Fpm exists either at block 1 or block 2 of the MSF. However, this // allows for a maximum of getBlockSize() * 8 blocks bits in the Fpm, and // thusly an equal number of total blocks in the file. For a block size @@ -136,25 +135,22 @@ // at getBlockSize() intervals, so we have to be compatible. // See the function fpmPn() for more information: // https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/msf/msf.cpp#L489 - - uint32_t BlocksPerSection = getBlockSize(); - uint64_t FpmBlockOffset = SB->FreeBlockMapBlock; + auto FpmStream = MappedBlockStream::createFpmStream(ContainerLayout, *Buffer); + StreamReader FpmReader(*FpmStream); + ArrayRef FpmBytes; + if (auto EC = FpmReader.readBytes(FpmBytes, + msf::getFullFpmByteSize(ContainerLayout))) + return EC; uint32_t BlocksRemaining = getBlockCount(); - for (uint32_t SI = 0; BlocksRemaining > 0; ++SI) { - uint32_t FpmFileOffset = FpmBlockOffset * getBlockSize(); - - if (auto EC = Buffer->readBytes(FpmFileOffset, getBlockSize(), FpmBytes)) - return EC; - - uint32_t BlocksThisSection = std::min(BlocksRemaining, BlocksPerSection); - for (uint32_t I = 0; I < BlocksThisSection; ++I) { - uint32_t BI = I + BlocksPerSection * SI; - - if (FpmBytes[I / 8] & (1 << (I % 8))) + uint32_t BI = 0; + for (auto Byte : FpmBytes) { + uint32_t BlocksThisByte = std::min(BlocksRemaining, 8U); + for (uint32_t I = 0; I < BlocksThisByte; ++I) { + if (Byte & (1 << I)) ContainerLayout.FreePageMap[BI] = true; + --BlocksRemaining; + ++BI; } - BlocksRemaining -= BlocksThisSection; - FpmBlockOffset += BlocksPerSection; } Reader.setOffset(getBlockMapOffset()); Index: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -291,9 +291,8 @@ recordKnownUsedPage(PS, 0); // MSF Super Block - uint32_t BlocksPerSection = File.getBlockSize(); - uint32_t NumSections = - llvm::alignTo(File.getBlockCount(), BlocksPerSection) / BlocksPerSection; + uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout()); + uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout()); for (uint32_t I = 0; I < NumSections; ++I) { uint32_t Fpm0 = 1 + BlocksPerSection * I; // 2 Fpm blocks spaced at `getBlockSize()` block intervals