From faa554b2fd6c327cb9cc0ac9983bd3c178f2276c Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Fri, 15 Jul 2016 22:16:56 +0000 Subject: [pdb] Use MsfBuilder to handle the writing PDBs. Previously we would read a PDB, then write some of it back out, but write the directory, super block, and other pertinent metadata back out unchanged. This generates incorrect PDBs since the amount of data written was not always the same as the amount of data read. This patch changes things to use the newly introduced `MsfBuilder` class to write out a correct and accurate set of Msf metadata for the data *actually* written, which opens up the door for adding and removing type records, symbol records, and other types of data to an existing PDB. llvm-svn: 275627 --- llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp | 53 ++++++---------------------------- 1 file changed, 9 insertions(+), 44 deletions(-) (limited to 'llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp') diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp index 2aa4d4c426f..8b09dc57cde 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -53,7 +53,7 @@ uint32_t PDBFile::getBlockMapIndex() const { return SB->BlockMapAddr; } uint32_t PDBFile::getUnknown1() const { return SB->Unknown1; } uint32_t PDBFile::getNumDirectoryBlocks() const { - return bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize); + return msf::bytesToBlocks(SB->NumDirectoryBytes, SB->BlockSize); } uint64_t PDBFile::getBlockMapOffset() const { @@ -75,7 +75,7 @@ uint32_t PDBFile::getFileSize() const { return Buffer->getLength(); } Expected> PDBFile::getBlockData(uint32_t BlockIndex, uint32_t NumBytes) const { - uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize()); + uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize()); ArrayRef Result; if (auto EC = Buffer->readBytes(StreamBlockOffset, NumBytes, Result)) @@ -94,7 +94,7 @@ Error PDBFile::setBlockData(uint32_t BlockIndex, uint32_t Offset, raw_error_code::invalid_block_address, "setBlockData attempted to write out of block bounds."); - uint64_t StreamBlockOffset = blockToOffset(BlockIndex, getBlockSize()); + uint64_t StreamBlockOffset = msf::blockToOffset(BlockIndex, getBlockSize()); StreamBlockOffset += Offset; return Buffer->writeBytes(StreamBlockOffset, Data); } @@ -143,7 +143,8 @@ Error PDBFile::parseStreamData() { uint32_t StreamSize = getStreamByteSize(I); // FIXME: What does StreamSize ~0U mean? uint64_t NumExpectedStreamBlocks = - StreamSize == UINT32_MAX ? 0 : bytesToBlocks(StreamSize, SB->BlockSize); + StreamSize == UINT32_MAX ? 0 : msf::bytesToBlocks(StreamSize, + SB->BlockSize); // For convenience, we store the block array contiguously. This is because // if someone calls setStreamMap(), it is more convenient to be able to call @@ -293,51 +294,15 @@ Expected PDBFile::getStringTable() { return *StringTable; } -Error PDBFile::setSuperBlock(const SuperBlock *Block) { - SB = Block; - - // Check the magic bytes. - if (memcmp(SB->MagicBytes, MsfMagic, sizeof(MsfMagic)) != 0) - return make_error(raw_error_code::corrupt_file, - "MSF magic header doesn't match"); - - // We don't support blocksizes which aren't a multiple of four bytes. - if (SB->BlockSize % sizeof(support::ulittle32_t) != 0) - return make_error(raw_error_code::corrupt_file, - "Block size is not multiple of 4."); - - switch (SB->BlockSize) { - case 512: - case 1024: - case 2048: - case 4096: - break; - default: - // An invalid block size suggests a corrupt PDB file. - return make_error(raw_error_code::corrupt_file, - "Unsupported block size."); - } +Error PDBFile::setSuperBlock(const msf::SuperBlock *Block) { + if (auto EC = msf::validateSuperBlock(*Block)) + return EC; if (Buffer->getLength() % SB->BlockSize != 0) return make_error(raw_error_code::corrupt_file, "File size is not a multiple of block size"); - // We don't support directories whose sizes aren't a multiple of four bytes. - if (SB->NumDirectoryBytes % sizeof(support::ulittle32_t) != 0) - return make_error(raw_error_code::corrupt_file, - "Directory size is not multiple of 4."); - - // The number of blocks which comprise the directory is a simple function of - // the number of bytes it contains. - uint64_t NumDirectoryBlocks = getNumDirectoryBlocks(); - - // The directory, as we understand it, is a block which consists of a list of - // block numbers. It is unclear what would happen if the number of blocks - // couldn't fit on a single block. - if (NumDirectoryBlocks > SB->BlockSize / sizeof(support::ulittle32_t)) - return make_error(raw_error_code::corrupt_file, - "Too many directory blocks."); - + SB = Block; return Error::success(); } -- cgit v1.2.3