[PATCH] D36235: [pdb/lld] Write a valid FPM

Zachary Turner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 2 11:45:23 PDT 2017


zturner created this revision.
Herald added subscribers: hiraditya, mgorny.

Prior to this patch, we did not emit a free page map to the PDB.  Instead, we just wrote 0 bytes for the free page map.  Since an a free page map represents a minimum of `BlockSize * 8` blocks, this had the effect of saying that every PDB is a minimum of `4096*8*4096 = 134,217,728` bytes.  This had undesirable side effects when re-linking our PDB with MSVC, which would output a PDB of slightly above the aforementioned size.

The fix for this is to simply write the actual bits of the FPM to appropriate block, but it is not quite that simple.  Since one block of FPM data can only describe the state of `4096*8 = 32,768` blocks, supporting PDBs larger than this requires extra magic.  To handle this, blocks of the form `{1,2} + k * BlockSize` are reserved and should not be allocated to any other type of PDB data.  The FPM itself can then be viewed as a stream over the blocks {1 + 4096*0, 1 + 4096*1, 1 + 4096*2, ...} or {2 + 4096*0, 2 + 4096*1, 2 + 4096*2, ...} depending on the value of `SuperBlock->FreeBlockMapBlock`.

So we need some extra complexity that when allocating blocks from a stream, we check if the MSF file requires growing to vend the requested blocks.  If it does, then we look to see if the growth would allocated blocks with the aforementioned indices, and if so we mark them as used in the FPM so that they will not be vended by the block allocator.

But that's not all!  Another source of trickiness is in the fact that not all FPM blocks are even used.  For example, if a PDB file has 5000 blocks, and `SuperBlock->FreeBlockMapBlock == 1` , then blocks `1`, `2`, `4097`, and `4098` are FPM blocks but only block `1` is allocated.  And from block `1`, only `625` bytes are needed.  But blocks `2`, `4097`, and `4098` still need to be initialized to `0xFF`, as do the extraneous bytes of block `1`.  Getting this to work invisibly while allowing the user of the API to see only those bytes of the FPM that describe actual blocks required some finesse.


https://reviews.llvm.org/D36235

Files:
  llvm/include/llvm/DebugInfo/MSF/MSFCommon.h
  llvm/include/llvm/DebugInfo/MSF/MappedBlockStream.h
  llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
  llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
  llvm/lib/DebugInfo/MSF/MSFCommon.cpp
  llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
  llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
  llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
  llvm/test/DebugInfo/PDB/write-fpm.test
  llvm/unittests/DebugInfo/MSF/CMakeLists.txt
  llvm/unittests/DebugInfo/MSF/MSFBuilderTest.cpp
  llvm/unittests/DebugInfo/MSF/MSFCommonTest.cpp
  llvm/unittests/DebugInfo/MSF/MappedBlockStreamTest.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D36235.109390.patch
Type: text/x-patch
Size: 21348 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170802/f51d57c1/attachment.bin>


More information about the llvm-commits mailing list