diff options
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp index 05b3dc7fc31..d1369bade66 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/PDB/Raw/DbiStream.h" #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" +#include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/DebugInfo/PDB/Raw/TpiStream.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" @@ -54,18 +55,19 @@ struct llvm::pdb::PDBFileContext { DenseMap<uint32_t, std::vector<uint32_t>> StreamMap; }; -static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, - const uint64_t Size) { +static Error checkOffset(MemoryBufferRef M, uintptr_t Addr, + const uint64_t Size) { if (Addr + Size < Addr || Addr + Size < Size || Addr + Size > uintptr_t(M.getBufferEnd()) || Addr < uintptr_t(M.getBufferStart())) { - return std::make_error_code(std::errc::bad_address); + return make_error<RawError>(raw_error_code::corrupt_file, + "Invalid buffer address"); } - return std::error_code(); + return Error::success(); } template <typename T> -static std::error_code checkOffset(MemoryBufferRef M, ArrayRef<T> AR) { +static Error checkOffset(MemoryBufferRef M, ArrayRef<T> AR) { return checkOffset(M, uintptr_t(AR.data()), (uint64_t)AR.size() * sizeof(T)); } @@ -117,38 +119,45 @@ StringRef PDBFile::getBlockData(uint32_t BlockIndex, uint32_t NumBytes) const { NumBytes); } -std::error_code PDBFile::parseFileHeaders() { +Error PDBFile::parseFileHeaders() { std::error_code EC; MemoryBufferRef BufferRef = *Context->Buffer; // Make sure the file is sufficiently large to hold a super block. // Do this before attempting to read the super block. if (BufferRef.getBufferSize() < sizeof(SuperBlock)) - return std::make_error_code(std::errc::illegal_byte_sequence); + return make_error<RawError>(raw_error_code::corrupt_file, + "Does not contain superblock"); Context->SB = reinterpret_cast<const SuperBlock *>(BufferRef.getBufferStart()); const SuperBlock *SB = Context->SB; + // Check the magic bytes. + if (memcmp(SB->MagicBytes, Magic, sizeof(Magic)) != 0) + return make_error<RawError>(raw_error_code::corrupt_file, + "MSF magic header doesn't match"); + + if (BufferRef.getBufferSize() % SB->BlockSize != 0) + return make_error<RawError>(raw_error_code::corrupt_file, + "File size is not a multiple of block size"); + switch (SB->BlockSize) { case 512: case 1024: case 2048: case 4096: break; default: // An invalid block size suggests a corrupt PDB file. - return std::make_error_code(std::errc::illegal_byte_sequence); + return make_error<RawError>(raw_error_code::corrupt_file, + "Unsupported block size."); } - if (BufferRef.getBufferSize() % SB->BlockSize != 0) - return std::make_error_code(std::errc::illegal_byte_sequence); - - // Check the magic bytes. - if (memcmp(SB->MagicBytes, Magic, sizeof(Magic)) != 0) - return std::make_error_code(std::errc::illegal_byte_sequence); // We don't support blocksizes which aren't a multiple of four bytes. - if (SB->BlockSize == 0 || SB->BlockSize % sizeof(support::ulittle32_t) != 0) - return std::make_error_code(std::errc::not_supported); + if (SB->BlockSize % sizeof(support::ulittle32_t) != 0) + return make_error<RawError>(raw_error_code::corrupt_file, + "Block size is not multiple of 4."); // We don't support directories whose sizes aren't a multiple of four bytes. if (SB->NumDirectoryBytes % sizeof(support::ulittle32_t) != 0) - return std::make_error_code(std::errc::not_supported); + return make_error<RawError>(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. @@ -159,12 +168,13 @@ std::error_code PDBFile::parseFileHeaders() { // 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 std::make_error_code(std::errc::illegal_byte_sequence); + return make_error<RawError>(raw_error_code::corrupt_file, + "Too many directory blocks."); - return std::error_code(); + return Error::success(); } -std::error_code PDBFile::parseStreamData() { +Error PDBFile::parseStreamData() { assert(Context && Context->SB); bool SeenNumStreams = false; @@ -237,7 +247,8 @@ std::error_code PDBFile::parseStreamData() { // It seems this block doesn't belong to any stream? The stream is either // corrupt or something more mysterious is going on. if (StreamIdx == NumStreams) - return std::make_error_code(std::errc::illegal_byte_sequence); + return make_error<RawError>(raw_error_code::corrupt_file, + "Orphaned block found?"); StreamBlocks->push_back(Data); } @@ -245,7 +256,7 @@ std::error_code PDBFile::parseStreamData() { // We should have read exactly SB->NumDirectoryBytes bytes. assert(DirectoryBytesRead == SB->NumDirectoryBytes); - return std::error_code(); + return Error::success(); } llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() { @@ -255,26 +266,29 @@ llvm::ArrayRef<support::ulittle32_t> PDBFile::getDirectoryBlockArray() { getNumDirectoryBlocks()); } -InfoStream &PDBFile::getPDBInfoStream() { +Expected<InfoStream &> PDBFile::getPDBInfoStream() { if (!Info) { Info.reset(new InfoStream(*this)); - Info->reload(); + if (auto EC = Info->reload()) + return std::move(EC); } return *Info; } -DbiStream &PDBFile::getPDBDbiStream() { +Expected<DbiStream &> PDBFile::getPDBDbiStream() { if (!Dbi) { Dbi.reset(new DbiStream(*this)); - Dbi->reload(); + if (auto EC = Dbi->reload()) + return std::move(EC); } return *Dbi; } -TpiStream &PDBFile::getPDBTpiStream() { +Expected<TpiStream &> PDBFile::getPDBTpiStream() { if (!Tpi) { Tpi.reset(new TpiStream(*this)); - Tpi->reload(); + if (auto EC = Tpi->reload()) + return std::move(EC); } return *Tpi; } |