Index: include/llvm/DebugInfo/PDB/Raw/PDBFile.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PDBFile.h +++ include/llvm/DebugInfo/PDB/Raw/PDBFile.h @@ -26,7 +26,6 @@ namespace msf { class MappedBlockStream; -class WritableStream; } namespace pdb { @@ -96,7 +95,21 @@ BumpPtrAllocator &getAllocator() { return Allocator; } + bool hasPDBDbiStream() const; + bool hasPDBGlobalsStream(); + bool hasPDBInfoStream(); + bool hasPDBIpiStream() const; + bool hasPDBPublicsStream(); + bool hasPDBSymbolStream(); + bool hasPDBTpiStream() const; + bool hasStringTable(); + private: + Expected> + safelyCreateIndexedStream(const msf::MSFLayout &Layout, + const msf::ReadableStream &MsfData, + uint32_t StreamIndex) const; + BumpPtrAllocator &Allocator; std::unique_ptr Buffer; Index: lib/DebugInfo/MSF/MappedBlockStream.cpp =================================================================== --- lib/DebugInfo/MSF/MappedBlockStream.cpp +++ lib/DebugInfo/MSF/MappedBlockStream.cpp @@ -63,6 +63,7 @@ MappedBlockStream::createIndexedStream(const MSFLayout &Layout, const ReadableStream &MsfData, uint32_t StreamIndex) { + assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index"); MSFStreamLayout SL; SL.Blocks = Layout.StreamMap[StreamIndex]; SL.Length = Layout.StreamSizes[StreamIndex]; @@ -334,6 +335,7 @@ WritableMappedBlockStream::createIndexedStream(const MSFLayout &Layout, const WritableStream &MsfData, uint32_t StreamIndex) { + assert(StreamIndex < Layout.StreamMap.size() && "Invalid stream index"); MSFStreamLayout SL; SL.Blocks = Layout.StreamMap[StreamIndex]; SL.Length = Layout.StreamSizes[StreamIndex]; Index: lib/DebugInfo/PDB/Raw/PDBFile.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -227,9 +227,11 @@ if (!DbiS) return DbiS.takeError(); - auto GlobalS = MappedBlockStream::createIndexedStream( - ContainerLayout, *Buffer, DbiS->getGlobalSymbolStreamIndex()); - auto TempGlobals = llvm::make_unique(std::move(GlobalS)); + auto GlobalS = safelyCreateIndexedStream(ContainerLayout, + *Buffer, + DbiS->getGlobalSymbolStreamIndex()); + if (!GlobalS) return GlobalS.takeError(); + auto TempGlobals = llvm::make_unique(std::move(*GlobalS)); if (auto EC = TempGlobals->reload()) return std::move(EC); Globals = std::move(TempGlobals); @@ -239,9 +241,10 @@ Expected PDBFile::getPDBInfoStream() { if (!Info) { - auto InfoS = MappedBlockStream::createIndexedStream(ContainerLayout, - *Buffer, StreamPDB); - auto TempInfo = llvm::make_unique(std::move(InfoS)); + auto InfoS = safelyCreateIndexedStream(ContainerLayout, + *Buffer, StreamPDB); + if (!InfoS) return InfoS.takeError(); + auto TempInfo = llvm::make_unique(std::move(*InfoS)); if (auto EC = TempInfo->reload()) return std::move(EC); Info = std::move(TempInfo); @@ -251,9 +254,10 @@ Expected PDBFile::getPDBDbiStream() { if (!Dbi) { - auto DbiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, - StreamDBI); - auto TempDbi = llvm::make_unique(*this, std::move(DbiS)); + auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, + StreamDBI); + if (!DbiS) return DbiS.takeError(); + auto TempDbi = llvm::make_unique(*this, std::move(*DbiS)); if (auto EC = TempDbi->reload()) return std::move(EC); Dbi = std::move(TempDbi); @@ -263,9 +267,10 @@ Expected PDBFile::getPDBTpiStream() { if (!Tpi) { - auto TpiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, - StreamTPI); - auto TempTpi = llvm::make_unique(*this, std::move(TpiS)); + auto TpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, + StreamTPI); + if (!TpiS) return TpiS.takeError(); + auto TempTpi = llvm::make_unique(*this, std::move(*TpiS)); if (auto EC = TempTpi->reload()) return std::move(EC); Tpi = std::move(TempTpi); @@ -275,9 +280,10 @@ Expected PDBFile::getPDBIpiStream() { if (!Ipi) { - auto IpiS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, - StreamIPI); - auto TempIpi = llvm::make_unique(*this, std::move(IpiS)); + auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, + StreamIPI); + if (!IpiS) return IpiS.takeError(); + auto TempIpi = llvm::make_unique(*this, std::move(*IpiS)); if (auto EC = TempIpi->reload()) return std::move(EC); Ipi = std::move(TempIpi); @@ -291,12 +297,12 @@ if (!DbiS) return DbiS.takeError(); - uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex(); - - auto PublicS = MappedBlockStream::createIndexedStream( - ContainerLayout, *Buffer, PublicsStreamNum); + auto PublicS = safelyCreateIndexedStream(ContainerLayout, + *Buffer, + DbiS->getPublicSymbolStreamIndex()); + if (!PublicS) return PublicS.takeError(); auto TempPublics = - llvm::make_unique(*this, std::move(PublicS)); + llvm::make_unique(*this, std::move(*PublicS)); if (auto EC = TempPublics->reload()) return std::move(EC); Publics = std::move(TempPublics); @@ -311,10 +317,11 @@ return DbiS.takeError(); uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex(); - auto SymbolS = MappedBlockStream::createIndexedStream( + auto SymbolS = safelyCreateIndexedStream( ContainerLayout, *Buffer, SymbolStreamNum); + if (!SymbolS) return SymbolS.takeError(); - auto TempSymbols = llvm::make_unique(std::move(SymbolS)); + auto TempSymbols = llvm::make_unique(std::move(*SymbolS)); if (auto EC = TempSymbols->reload()) return std::move(EC); Symbols = std::move(TempSymbols); @@ -330,19 +337,72 @@ uint32_t NameStreamIndex = IS->getNamedStreamIndex("/names"); - if (NameStreamIndex == 0) - return make_error(raw_error_code::no_stream); - if (NameStreamIndex >= getNumStreams()) - return make_error(raw_error_code::no_stream); - auto NS = MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, - NameStreamIndex); + auto NS = safelyCreateIndexedStream(ContainerLayout, *Buffer, + NameStreamIndex); + if (!NS) return NS.takeError(); - StreamReader Reader(*NS); + StreamReader Reader(**NS); auto N = llvm::make_unique(); if (auto EC = N->load(Reader)) return std::move(EC); StringTable = std::move(N); - StringTableStream = std::move(NS); + StringTableStream = std::move(*NS); } return *StringTable; } + +bool PDBFile::hasPDBDbiStream() const { + return StreamDBI < getNumStreams(); +} + +bool PDBFile::hasPDBGlobalsStream() { + auto DbiS = getPDBDbiStream(); + if (!DbiS) return false; + return DbiS->getGlobalSymbolStreamIndex() < getNumStreams(); +} + +bool PDBFile::hasPDBInfoStream() { + return StreamPDB < getNumStreams(); +} + +bool PDBFile::hasPDBIpiStream() const { + return StreamIPI < getNumStreams(); +} + +bool PDBFile::hasPDBPublicsStream() { + auto DbiS = getPDBDbiStream(); + if (!DbiS) return false; + return DbiS->getPublicSymbolStreamIndex() < getNumStreams(); +} + +bool PDBFile::hasPDBSymbolStream() { + auto DbiS = getPDBDbiStream(); + if (!DbiS) return false; + return DbiS->getSymRecordStreamIndex() < getNumStreams(); +} + +bool PDBFile::hasPDBTpiStream() const { + return StreamTPI < getNumStreams(); +} + +bool PDBFile::hasStringTable() { + auto IS = getPDBInfoStream(); + if (!IS) return false; + return IS->getNamedStreamIndex("/names") < getNumStreams(); +} + +/// Wrapper around MappedBlockStream::createIndexedStream() +/// that checks if a stream with that index actually exists. +/// If it does not, the return value will have an MSFError with +/// code msf_error_code::no_stream. Else, the return value will +/// contain the stream returned by createIndexedStream(). +Expected> +PDBFile::safelyCreateIndexedStream(const MSFLayout &Layout, + const ReadableStream &MsfData, + uint32_t StreamIndex) const { + if (StreamIndex >= getNumStreams()) + return make_error(raw_error_code::no_stream); + return MappedBlockStream::createIndexedStream(Layout, + MsfData, + StreamIndex); +} Index: tools/llvm-pdbdump/LLVMOutputStyle.cpp =================================================================== --- tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -350,11 +350,23 @@ Error LLVMOutputStyle::dumpGlobalsStream() { if (!opts::raw::DumpGlobals) return Error::success(); + if (!File.hasPDBGlobalsStream()) { + P.printString("Globals Stream not present"); + return Error::success(); + } - DictScope D(P, "Globals Stream"); auto Globals = File.getPDBGlobalsStream(); if (!Globals) - return Globals.takeError(); + return handleErrors(Globals.takeError(), + [&](const msf::MSFError &E) -> Error { + if (E.Code == msf::msf_error_code::no_stream) { + P.printString("Globals Stream not present"); + return Error::success(); + } else { + return make_error(E); + } + }); + DictScope D(P, "Globals Stream"); auto Dbi = File.getPDBDbiStream(); if (!Dbi) @@ -447,6 +459,10 @@ Error LLVMOutputStyle::dumpInfoStream() { if (!opts::raw::DumpHeaders) return Error::success(); + if (!File.hasPDBInfoStream()) { + P.printString("PDB Stream not present"); + return Error::success(); + } auto IS = File.getPDBInfoStream(); if (!IS) return IS.takeError(); @@ -485,11 +501,19 @@ StringRef Label; StringRef VerLabel; if (StreamIdx == StreamTPI) { + if (!File.hasPDBTpiStream()) { + P.printString("Type Info Stream (TPI) not present"); + return Error::success(); + } DumpRecordBytes = opts::raw::DumpTpiRecordBytes; DumpRecords = opts::raw::DumpTpiRecords; Label = "Type Info Stream (TPI)"; VerLabel = "TPI Version"; } else if (StreamIdx == StreamIPI) { + if (!File.hasPDBIpiStream()) { + P.printString("Type Info Stream (IPI) not present"); + return Error::success(); + } DumpRecordBytes = opts::raw::DumpIpiRecordBytes; DumpRecords = opts::raw::DumpIpiRecords; Label = "Type Info Stream (IPI)"; @@ -556,6 +580,10 @@ opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo; if (!opts::raw::DumpHeaders && !DumpModules) return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } auto DS = File.getPDBDbiStream(); if (!DS) @@ -742,6 +770,10 @@ Error LLVMOutputStyle::dumpSectionContribs() { if (!opts::raw::DumpSectionContribs) return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } auto Dbi = File.getPDBDbiStream(); if (!Dbi) @@ -789,6 +821,10 @@ Error LLVMOutputStyle::dumpSectionMap() { if (!opts::raw::DumpSectionMap) return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } auto Dbi = File.getPDBDbiStream(); if (!Dbi) @@ -813,11 +849,15 @@ Error LLVMOutputStyle::dumpPublicsStream() { if (!opts::raw::DumpPublics) return Error::success(); + if (!File.hasPDBPublicsStream()) { + P.printString("Publics Stream not present"); + return Error::success(); + } - DictScope D(P, "Publics Stream"); auto Publics = File.getPDBPublicsStream(); if (!Publics) return Publics.takeError(); + DictScope D(P, "Publics Stream"); auto Dbi = File.getPDBDbiStream(); if (!Dbi) @@ -856,6 +896,10 @@ Error LLVMOutputStyle::dumpSectionHeaders() { if (!opts::raw::DumpSectionHeaders) return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } auto Dbi = File.getPDBDbiStream(); if (!Dbi) @@ -885,6 +929,10 @@ Error LLVMOutputStyle::dumpFpoStream() { if (!opts::raw::DumpFpo) return Error::success(); + if (!File.hasPDBDbiStream()) { + P.printString("DBI Stream not present"); + return Error::success(); + } auto Dbi = File.getPDBDbiStream(); if (!Dbi)