Index: include/llvm/DebugInfo/PDB/Raw/DbiStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -36,7 +36,7 @@ struct HeaderInfo; public: - DbiStream(PDBFile &File); + DbiStream(PDBFile &File, std::unique_ptr Stream); ~DbiStream(); Error reload(); @@ -79,7 +79,7 @@ Error initializeFpoRecords(); PDBFile &Pdb; - MappedBlockStream Stream; + std::unique_ptr Stream; std::vector ModuleInfos; NameHashTable ECNames; Index: include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h @@ -0,0 +1,37 @@ +//===- DirectoryStreamData.h ---------------------------------- *- C++ --*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_DIRECTORYSTREAMDATA_H +#define LLVM_DEBUGINFO_PDB_RAW_DIRECTORYSTREAMDATA_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" +#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" +#include "llvm/Support/Endian.h" + +namespace llvm { +namespace pdb { +class IPDBFile; + +class DirectoryStreamData : public IPDBStreamData { +public: + DirectoryStreamData(const PDBFile &File) : File(File) {} + + virtual uint32_t getLength() { return File.getNumDirectoryBytes(); } + virtual llvm::ArrayRef getStreamBlocks() { + return File.getDirectoryBlockArray(); + } + +private: + const PDBFile &File; +}; +} +} + +#endif Index: include/llvm/DebugInfo/PDB/Raw/InfoStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/InfoStream.h +++ include/llvm/DebugInfo/PDB/Raw/InfoStream.h @@ -24,7 +24,7 @@ class PDBFile; class InfoStream { public: - InfoStream(const PDBFile &File); + InfoStream(std::unique_ptr Stream); Error reload(); @@ -37,7 +37,7 @@ iterator_range> named_streams() const; private: - MappedBlockStream Stream; + std::unique_ptr Stream; // PDB file format version. We only support VC70. See the enumeration // `PdbRaw_ImplVer` for the other possible values. Index: include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h +++ include/llvm/DebugInfo/PDB/Raw/MappedBlockStream.h @@ -12,6 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/CodeView/StreamInterface.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Endian.h" @@ -24,11 +25,10 @@ class IPDBFile; class IPDBStreamData; +class PDBFile; class MappedBlockStream : public codeview::StreamInterface { public: - MappedBlockStream(std::unique_ptr Data, const IPDBFile &File); - Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef &Buffer) const override; @@ -36,7 +36,14 @@ uint32_t getNumBytesCopied() const; -private: + static Expected> + createIndexedStream(uint32_t StreamIdx, const IPDBFile &File); + static Expected> + createDirectoryStream(const PDBFile &File); + +protected: + MappedBlockStream(std::unique_ptr Data, const IPDBFile &File); + Error readBytes(uint32_t Offset, MutableArrayRef Buffer) const; bool tryReadContiguously(uint32_t Offset, uint32_t Size, ArrayRef &Buffer) const; Index: include/llvm/DebugInfo/PDB/Raw/ModStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/ModStream.h +++ include/llvm/DebugInfo/PDB/Raw/ModStream.h @@ -26,7 +26,7 @@ class ModStream { public: - ModStream(const PDBFile &File, const ModInfo &Module); + ModStream(const ModInfo &Module, std::unique_ptr Stream); ~ModStream(); Error reload(); @@ -40,7 +40,7 @@ private: const ModInfo &Mod; - MappedBlockStream Stream; + std::unique_ptr Stream; codeview::CVSymbolArray SymbolsSubstream; codeview::StreamRef LinesSubstream; Index: include/llvm/DebugInfo/PDB/Raw/PublicsStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/PublicsStream.h +++ include/llvm/DebugInfo/PDB/Raw/PublicsStream.h @@ -29,11 +29,10 @@ struct HeaderInfo; public: - PublicsStream(PDBFile &File, uint32_t StreamNum); + PublicsStream(PDBFile &File, std::unique_ptr Stream); ~PublicsStream(); Error reload(); - uint32_t getStreamNum() const { return StreamNum; } uint32_t getSymHash() const; uint32_t getAddrMap() const; uint32_t getNumBuckets() const { return NumBuckets; } @@ -55,8 +54,7 @@ private: PDBFile &Pdb; - uint32_t StreamNum; - MappedBlockStream Stream; + std::unique_ptr Stream; uint32_t NumBuckets = 0; ArrayRef Bitmap; codeview::FixedStreamArray HashRecords; Index: include/llvm/DebugInfo/PDB/Raw/RawError.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/RawError.h +++ include/llvm/DebugInfo/PDB/Raw/RawError.h @@ -14,6 +14,62 @@ #include +/// Extracts the value from an Expected or returns an llvm::Error. Saves +/// the value into an existing variable. Note: If you try to use std::move() +/// on the return statement, compiler warns about copy elision, so the macro +/// cannot be shared with EXPECTED_GET_OR_RETURN_EXPECTED. +#define EXPECTED_GET_OR_RETURN(Result, ExpectedExpr) \ + auto Expected_##Result = ExpectedExpr; \ + if (auto EC = Expected_##Result.takeError()) \ + return EC; \ + Result = std::move(Expected_##Result.get()); + +/// Extracts the value from an Expected or returns the Expected. Saves +/// the value into an existing variable. Note: If you don't use std::move on +/// the return statement, you get an error about llvm::Error not being copyable, +/// so the macro cannot be shared with EXPECTED_GET_OR_RETURN. +#define EXPECTED_GET_OR_RETURN_EXPECTED(Result, ExpectedExpr) \ + auto Expected_##Result = ExpectedExpr; \ + if (auto EC = Expected_##Result.takeError()) \ + return std::move(EC); \ + Result = std::move(Expected_##Result.get()); + +/// Extracts the value from an Expected or returns an llvm::Error. Declares +/// a new variable to save the value into. Assumes that is *not* a +/// reference type. If it, this macro will complain when T is not moveable, +/// because `auto Result` will declare an instance, not a reference. So the +/// macro cannot be shared with EXPECTED_GET_DECL_REF_OR_RETURN. +#define EXPECTED_GET_DECL_OR_RETURN(Result, ExpectedExpr) \ + auto Expected_##Result = ExpectedExpr; \ + if (auto EC = Expected_##Result.takeError()) \ + return EC; \ + auto Result = std::move(Expected_##Result.get()); + +/// Extracts the value from an Expected or returns the Expected. Declares +/// a new variable to save the value into. Assumes that is *not* a +/// reference type. +#define EXPECTED_GET_DECL_OR_RETURN_EXPECTED(Result, ExpectedExpr) \ + auto Expected_##Result = ExpectedExpr; \ + if (auto EC = Expected_##Result.takeError()) \ + return std::move(EC); \ + auto Result = std::move(Expected_##Result.get()); + +/// Extracts the value from an Expected or returns an llvm::Error. Declares +/// a new variable to save the value into. Assumes that is a reference type +#define EXPECTED_GET_DECL_REF_OR_RETURN(Result, ExpectedExpr) \ + auto Expected_##Result = ExpectedExpr; \ + if (auto EC = Expected_##Result.takeError()) \ + return EC; \ + auto &Result = Expected_##Result.get(); + +/// Extracts the value from an Expected or returns the Expected. Declares +/// a new variable to save the value into. Assumes that is a reference type +#define EXPECTED_GET_DECL_REF_OR_RETURN_EXPECTED(Result, ExpectedExpr) \ + auto Expected_##Result = ExpectedExpr; \ + if (auto EC = Expected_##Result.takeError()) \ + return std::move(EC); \ + auto &Result = Expected_##Result.get(); + namespace llvm { namespace pdb { enum class raw_error_code { Index: include/llvm/DebugInfo/PDB/Raw/SymbolStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/SymbolStream.h +++ include/llvm/DebugInfo/PDB/Raw/SymbolStream.h @@ -22,7 +22,7 @@ class SymbolStream { public: - SymbolStream(const PDBFile &File, uint32_t StreamNum); + SymbolStream(std::unique_ptr Stream); ~SymbolStream(); Error reload(); @@ -31,7 +31,7 @@ private: codeview::CVSymbolArray SymbolRecords; - MappedBlockStream MappedStream; + std::unique_ptr Stream; }; } } Index: include/llvm/DebugInfo/PDB/Raw/TpiStream.h =================================================================== --- include/llvm/DebugInfo/PDB/Raw/TpiStream.h +++ include/llvm/DebugInfo/PDB/Raw/TpiStream.h @@ -31,7 +31,7 @@ struct HeaderInfo; public: - TpiStream(const PDBFile &File, uint32_t StreamIdx); + TpiStream(const PDBFile &File, std::unique_ptr Stream); ~TpiStream(); Error reload(); @@ -53,7 +53,7 @@ private: const PDBFile &Pdb; - MappedBlockStream Stream; + std::unique_ptr Stream; HashFunctionType HashFunction; codeview::CVTypeArray TypeRecords; Index: include/llvm/Support/Error.h =================================================================== --- include/llvm/Support/Error.h +++ include/llvm/Support/Error.h @@ -614,6 +614,7 @@ public: typedef typename std::conditional::type storage_type; + typedef T value_type; private: typedef typename std::remove_reference::type &reference; Index: lib/DebugInfo/PDB/Raw/DbiStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -93,19 +93,17 @@ return Error::success(); } -DbiStream::DbiStream(PDBFile &File) - : Pdb(File), - Stream(llvm::make_unique(StreamDBI, File), File), - Header(nullptr) { +DbiStream::DbiStream(PDBFile &File, std::unique_ptr Stream) + : Pdb(File), Stream(std::move(Stream)), Header(nullptr) { static_assert(sizeof(HeaderInfo) == 64, "Invalid HeaderInfo size!"); } DbiStream::~DbiStream() {} Error DbiStream::reload() { - StreamReader Reader(Stream); + StreamReader Reader(*Stream); - if (Stream.getLength() < sizeof(HeaderInfo)) + if (Stream->getLength() < sizeof(HeaderInfo)) return make_error(raw_error_code::corrupt_file, "DBI Stream does not contain a header."); if (auto EC = Reader.readObject(Header)) @@ -123,15 +121,13 @@ return make_error(raw_error_code::feature_unsupported, "Unsupported DBI version."); - auto InfoStream = Pdb.getPDBInfoStream(); - if (auto EC = InfoStream.takeError()) - return EC; + EXPECTED_GET_DECL_REF_OR_RETURN(IS, Pdb.getPDBInfoStream()); - if (Header->Age != InfoStream.get().getAge()) + if (Header->Age != IS.getAge()) return make_error(raw_error_code::corrupt_file, "DBI Age does not match PDB Age."); - if (Stream.getLength() != + if (Stream->getLength() != sizeof(HeaderInfo) + Header->ModiSubstreamSize + Header->SecContrSubstreamSize + Header->SectionMapSize + Header->FileInfoSize + Header->TypeServerSize + @@ -296,8 +292,9 @@ if (StreamNum >= Pdb.getNumStreams()) return make_error(raw_error_code::no_stream); - SectionHeaderStream.reset(new MappedBlockStream( - llvm::make_unique(StreamNum, Pdb), Pdb)); + EXPECTED_GET_OR_RETURN( + SectionHeaderStream, + MappedBlockStream::createIndexedStream(StreamNum, Pdb)); size_t StreamLen = SectionHeaderStream->getLength(); if (StreamLen % sizeof(object::coff_section)) @@ -318,8 +315,8 @@ if (StreamNum >= Pdb.getNumStreams()) return make_error(raw_error_code::no_stream); - FpoStream.reset(new MappedBlockStream( - llvm::make_unique(StreamNum, Pdb), Pdb)); + EXPECTED_GET_OR_RETURN( + FpoStream, MappedBlockStream::createIndexedStream(StreamNum, Pdb)); size_t StreamLen = FpoStream->getLength(); if (StreamLen % sizeof(object::FpoData)) @@ -418,10 +415,8 @@ uint32_t NumFiles = ModFileCountArray[I]; ModuleInfos[I].SourceFiles.resize(NumFiles); for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) { - if (auto Name = getFileNameForIndex(NextFileIndex)) - ModuleInfos[I].SourceFiles[J] = Name.get(); - else - return Name.takeError(); + EXPECTED_GET_DECL_OR_RETURN(ThisName, getFileNameForIndex(NextFileIndex)); + ModuleInfos[I].SourceFiles[J] = ThisName; } } Index: lib/DebugInfo/PDB/Raw/InfoStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/InfoStream.cpp +++ lib/DebugInfo/PDB/Raw/InfoStream.cpp @@ -19,11 +19,11 @@ using namespace llvm; using namespace llvm::pdb; -InfoStream::InfoStream(const PDBFile &File) - : Stream(llvm::make_unique(StreamPDB, File), File) {} +InfoStream::InfoStream(std::unique_ptr Stream) + : Stream(std::move(Stream)) {} Error InfoStream::reload() { - codeview::StreamReader Reader(Stream); + codeview::StreamReader Reader(*Stream); struct Header { support::ulittle32_t Version; Index: lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp +++ lib/DebugInfo/PDB/Raw/MappedBlockStream.cpp @@ -8,13 +8,27 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h" #include "llvm/DebugInfo/PDB/Raw/IPDBStreamData.h" +#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h" #include "llvm/DebugInfo/PDB/Raw/PDBFile.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" using namespace llvm; using namespace llvm::pdb; +namespace { +// This exists so that we can use make_unique while still keeping the +// constructor of MappedBlockStream private, forcing users to go through +// the `create` interface. +class MappedBlockStreamImpl : public MappedBlockStream { +public: + MappedBlockStreamImpl(std::unique_ptr Data, + const IPDBFile &File) + : MappedBlockStream(std::move(Data), File) {} +}; +} + MappedBlockStream::MappedBlockStream(std::unique_ptr Data, const IPDBFile &Pdb) : Pdb(Pdb), Data(std::move(Data)) {} @@ -122,3 +136,19 @@ uint32_t MappedBlockStream::getNumBytesCopied() const { return static_cast(Pool.getBytesAllocated()); } + +Expected> +MappedBlockStream::createIndexedStream(uint32_t StreamIdx, + const IPDBFile &File) { + if (StreamIdx >= File.getNumStreams()) + return make_error(raw_error_code::no_stream); + + auto Data = llvm::make_unique(StreamIdx, File); + return llvm::make_unique(std::move(Data), File); +} + +Expected> +MappedBlockStream::createDirectoryStream(const PDBFile &File) { + auto Data = llvm::make_unique(File); + return llvm::make_unique(std::move(Data), File); +} Index: lib/DebugInfo/PDB/Raw/ModStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/ModStream.cpp +++ lib/DebugInfo/PDB/Raw/ModStream.cpp @@ -19,15 +19,14 @@ using namespace llvm; using namespace llvm::pdb; -ModStream::ModStream(const PDBFile &File, const ModInfo &Module) - : Mod(Module), Stream(llvm::make_unique( - Module.getModuleStreamIndex(), File), - File) {} +ModStream::ModStream(const ModInfo &Module, + std::unique_ptr Stream) + : Mod(Module), Stream(std::move(Stream)) {} ModStream::~ModStream() {} Error ModStream::reload() { - codeview::StreamReader Reader(Stream); + codeview::StreamReader Reader(*Stream); uint32_t SymbolSize = Mod.getSymbolDebugInfoByteSize(); uint32_t C11Size = Mod.getLineInfoByteSize(); Index: lib/DebugInfo/PDB/Raw/PDBFile.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PDBFile.cpp +++ lib/DebugInfo/PDB/Raw/PDBFile.cpp @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/StreamReader.h" #include "llvm/DebugInfo/PDB/Raw/DbiStream.h" +#include "llvm/DebugInfo/PDB/Raw/DirectoryStreamData.h" #include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h" #include "llvm/DebugInfo/PDB/Raw/InfoStream.h" #include "llvm/DebugInfo/PDB/Raw/NameHashTable.h" @@ -54,19 +55,6 @@ support::ulittle32_t BlockMapAddr; }; -class DirectoryStreamData : public IPDBStreamData { -public: - DirectoryStreamData(const PDBFile &File) : File(File) {} - - virtual uint32_t getLength() { return File.getNumDirectoryBytes(); } - virtual llvm::ArrayRef getStreamBlocks() { - return File.getDirectoryBlockArray(); - } - -private: - const PDBFile &File; -}; - typedef codeview::FixedStreamArray ulittle_array; } @@ -222,8 +210,8 @@ // is exactly what we are attempting to parse. By specifying a custom // subclass of IPDBStreamData which only accesses the fields that have already // been parsed, we can avoid this and reuse MappedBlockStream. - auto SD = llvm::make_unique(*this); - DirectoryStream = llvm::make_unique(std::move(SD), *this); + EXPECTED_GET_OR_RETURN(DirectoryStream, + MappedBlockStream::createDirectoryStream(*this)); codeview::StreamReader Reader(*DirectoryStream); if (auto EC = Reader.readInteger(NumStreams)) return EC; @@ -253,7 +241,9 @@ Expected PDBFile::getPDBInfoStream() { if (!Info) { - Info.reset(new InfoStream(*this)); + EXPECTED_GET_DECL_OR_RETURN_EXPECTED( + InfoS, MappedBlockStream::createIndexedStream(StreamPDB, *this)); + Info.reset(new InfoStream(std::move(InfoS))); if (auto EC = Info->reload()) return std::move(EC); } @@ -262,7 +252,9 @@ Expected PDBFile::getPDBDbiStream() { if (!Dbi) { - Dbi.reset(new DbiStream(*this)); + EXPECTED_GET_DECL_OR_RETURN_EXPECTED( + DbiS, MappedBlockStream::createIndexedStream(StreamDBI, *this)); + Dbi.reset(new DbiStream(*this, std::move(DbiS))); if (auto EC = Dbi->reload()) return std::move(EC); } @@ -271,7 +263,9 @@ Expected PDBFile::getPDBTpiStream() { if (!Tpi) { - Tpi.reset(new TpiStream(*this, StreamTPI)); + EXPECTED_GET_DECL_OR_RETURN_EXPECTED( + TpiS, MappedBlockStream::createIndexedStream(StreamTPI, *this)); + Tpi.reset(new TpiStream(*this, std::move(TpiS))); if (auto EC = Tpi->reload()) return std::move(EC); } @@ -280,7 +274,9 @@ Expected PDBFile::getPDBIpiStream() { if (!Ipi) { - Ipi.reset(new TpiStream(*this, StreamIPI)); + EXPECTED_GET_DECL_OR_RETURN_EXPECTED( + IpiS, MappedBlockStream::createIndexedStream(StreamIPI, *this)); + Ipi.reset(new TpiStream(*this, std::move(IpiS))); if (auto EC = Ipi->reload()) return std::move(EC); } @@ -289,12 +285,13 @@ Expected PDBFile::getPDBPublicsStream() { if (!Publics) { - auto DbiS = getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return std::move(EC); - uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex(); + EXPECTED_GET_DECL_REF_OR_RETURN_EXPECTED(DbiS, getPDBDbiStream()); + uint32_t PublicsStreamNum = DbiS.getPublicSymbolStreamIndex(); - Publics.reset(new PublicsStream(*this, PublicsStreamNum)); + EXPECTED_GET_DECL_OR_RETURN_EXPECTED( + PublicS, + MappedBlockStream::createIndexedStream(PublicsStreamNum, *this)); + Publics.reset(new PublicsStream(*this, std::move(PublicS))); if (auto EC = Publics->reload()) return std::move(EC); } @@ -303,12 +300,13 @@ Expected PDBFile::getPDBSymbolStream() { if (!Symbols) { - auto DbiS = getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return std::move(EC); - uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex(); + EXPECTED_GET_DECL_REF_OR_RETURN_EXPECTED(DbiS, getPDBDbiStream()); + uint32_t SymbolStreamNum = DbiS.getSymRecordStreamIndex(); - Symbols.reset(new SymbolStream(*this, SymbolStreamNum)); + EXPECTED_GET_DECL_OR_RETURN_EXPECTED( + SymbolS, + MappedBlockStream::createIndexedStream(SymbolStreamNum, *this)); + Symbols.reset(new SymbolStream(std::move(SymbolS))); if (auto EC = Symbols->reload()) return std::move(EC); } @@ -317,10 +315,8 @@ Expected PDBFile::getStringTable() { if (!StringTable || !StringTableStream) { - auto InfoS = getPDBInfoStream(); - if (auto EC = InfoS.takeError()) - return std::move(EC); - auto &IS = InfoS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN_EXPECTED(IS, getPDBInfoStream()); + uint32_t NameStreamIndex = IS.getNamedStreamIndex("/names"); if (NameStreamIndex == 0) @@ -328,8 +324,9 @@ if (NameStreamIndex >= getNumStreams()) return make_error(raw_error_code::no_stream); - auto SD = llvm::make_unique(NameStreamIndex, *this); - auto S = llvm::make_unique(std::move(SD), *this); + std::unique_ptr S; + EXPECTED_GET_OR_RETURN_EXPECTED( + S, MappedBlockStream::createIndexedStream(NameStreamIndex, *this)); codeview::StreamReader Reader(*S); auto N = llvm::make_unique(); if (auto EC = N->load(Reader)) Index: lib/DebugInfo/PDB/Raw/PublicsStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/PublicsStream.cpp +++ lib/DebugInfo/PDB/Raw/PublicsStream.cpp @@ -71,9 +71,9 @@ ulittle32_t NumBuckets; }; -PublicsStream::PublicsStream(PDBFile &File, uint32_t StreamNum) - : Pdb(File), StreamNum(StreamNum), - Stream(llvm::make_unique(StreamNum, File), File) {} +PublicsStream::PublicsStream(PDBFile &File, + std::unique_ptr Stream) + : Pdb(File), Stream(std::move(Stream)) {} PublicsStream::~PublicsStream() {} @@ -86,7 +86,7 @@ // we skip over the hash table which we believe contains information about // public symbols. Error PublicsStream::reload() { - codeview::StreamReader Reader(Stream); + codeview::StreamReader Reader(*Stream); // Check stream size. if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader)) Index: lib/DebugInfo/PDB/Raw/SymbolStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/SymbolStream.cpp +++ lib/DebugInfo/PDB/Raw/SymbolStream.cpp @@ -24,16 +24,15 @@ using namespace llvm::support; using namespace llvm::pdb; -SymbolStream::SymbolStream(const PDBFile &File, uint32_t StreamNum) - : MappedStream(llvm::make_unique(StreamNum, File), - File) {} +SymbolStream::SymbolStream(std::unique_ptr Stream) + : Stream(std::move(Stream)) {} SymbolStream::~SymbolStream() {} Error SymbolStream::reload() { - codeview::StreamReader Reader(MappedStream); + codeview::StreamReader Reader(*Stream); - if (auto EC = Reader.readArray(SymbolRecords, MappedStream.getLength())) + if (auto EC = Reader.readArray(SymbolRecords, Stream->getLength())) return EC; return Error::success(); Index: lib/DebugInfo/PDB/Raw/TpiStream.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/TpiStream.cpp +++ lib/DebugInfo/PDB/Raw/TpiStream.cpp @@ -62,15 +62,14 @@ EmbeddedBuf HashAdjBuffer; }; -TpiStream::TpiStream(const PDBFile &File, uint32_t StreamIdx) - : Pdb(File), - Stream(llvm::make_unique(StreamIdx, File), File), - HashFunction(nullptr) {} +TpiStream::TpiStream(const PDBFile &File, + std::unique_ptr Stream) + : Pdb(File), Stream(std::move(Stream)), HashFunction(nullptr) {} TpiStream::~TpiStream() {} Error TpiStream::reload() { - codeview::StreamReader Reader(Stream); + codeview::StreamReader Reader(*Stream); if (Reader.bytesRemaining() < sizeof(HeaderInfo)) return make_error(raw_error_code::corrupt_file, @@ -108,8 +107,8 @@ return make_error(raw_error_code::corrupt_file, "Invalid TPI hash stream index."); - HashStream.reset(new MappedBlockStream( - llvm::make_unique(Header->HashStreamIndex, Pdb), Pdb)); + EXPECTED_GET_OR_RETURN(HashStream, MappedBlockStream::createIndexedStream( + Header->HashStreamIndex, Pdb)); codeview::StreamReader HSR(*HashStream); uint32_t NumHashValues = Header->HashValueBuffer.Length / sizeof(ulittle32_t); Index: tools/llvm-pdbdump/LLVMOutputStyle.cpp =================================================================== --- tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -67,33 +67,21 @@ if (!opts::DumpStreamSummary) return Error::success(); - auto DbiS = File.getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return EC; - auto TpiS = File.getPDBTpiStream(); - if (auto EC = TpiS.takeError()) - return EC; - auto IpiS = File.getPDBIpiStream(); - if (auto EC = IpiS.takeError()) - return EC; - auto InfoS = File.getPDBInfoStream(); - if (auto EC = InfoS.takeError()) - return EC; - DbiStream &DS = DbiS.get(); - TpiStream &TS = TpiS.get(); - TpiStream &TIS = IpiS.get(); - InfoStream &IS = InfoS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(Dbi, File.getPDBDbiStream()); + EXPECTED_GET_DECL_REF_OR_RETURN(Tpi, File.getPDBTpiStream()); + EXPECTED_GET_DECL_REF_OR_RETURN(Ipi, File.getPDBIpiStream()); + EXPECTED_GET_DECL_REF_OR_RETURN(Info, File.getPDBInfoStream()); ListScope L(P, "Streams"); uint32_t StreamCount = File.getNumStreams(); std::unordered_map ModStreams; std::unordered_map NamedStreams; - for (auto &ModI : DS.modules()) { + for (auto &ModI : Dbi.modules()) { uint16_t SN = ModI.Info.getModuleStreamIndex(); ModStreams[SN] = &ModI; } - for (auto &NSE : IS.named_streams()) { + for (auto &NSE : Info.named_streams()) { NamedStreams[NSE.second] = NSE.first(); } @@ -111,41 +99,42 @@ Value = "TPI Stream"; else if (StreamIdx == StreamIPI) Value = "IPI Stream"; - else if (StreamIdx == DS.getGlobalSymbolStreamIndex()) + else if (StreamIdx == Dbi.getGlobalSymbolStreamIndex()) Value = "Global Symbol Hash"; - else if (StreamIdx == DS.getPublicSymbolStreamIndex()) + else if (StreamIdx == Dbi.getPublicSymbolStreamIndex()) Value = "Public Symbol Hash"; - else if (StreamIdx == DS.getSymRecordStreamIndex()) + else if (StreamIdx == Dbi.getSymRecordStreamIndex()) Value = "Public Symbol Records"; - else if (StreamIdx == TS.getTypeHashStreamIndex()) + else if (StreamIdx == Tpi.getTypeHashStreamIndex()) Value = "TPI Hash"; - else if (StreamIdx == TS.getTypeHashStreamAuxIndex()) + else if (StreamIdx == Tpi.getTypeHashStreamAuxIndex()) Value = "TPI Aux Hash"; - else if (StreamIdx == TIS.getTypeHashStreamIndex()) + else if (StreamIdx == Ipi.getTypeHashStreamIndex()) Value = "IPI Hash"; - else if (StreamIdx == TIS.getTypeHashStreamAuxIndex()) + else if (StreamIdx == Ipi.getTypeHashStreamAuxIndex()) Value = "IPI Aux Hash"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Exception)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::Exception)) Value = "Exception Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Fixup)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::Fixup)) Value = "Fixup Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::FPO)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::FPO)) Value = "FPO Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::NewFPO)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::NewFPO)) Value = "New FPO Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapFromSrc)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::OmapFromSrc)) Value = "Omap From Source Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::OmapToSrc)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::OmapToSrc)) Value = "Omap To Source Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Pdata)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::Pdata)) Value = "Pdata"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdr)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::SectionHdr)) Value = "Section Header Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig)) + else if (StreamIdx == + Dbi.getDebugStreamIndex(DbgHeaderType::SectionHdrOrig)) Value = "Section Header Original Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::TokenRidMap)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::TokenRidMap)) Value = "Token Rid Data"; - else if (StreamIdx == DS.getDebugStreamIndex(DbgHeaderType::Xdata)) + else if (StreamIdx == Dbi.getDebugStreamIndex(DbgHeaderType::Xdata)) Value = "Xdata"; else { auto ModIter = ModStreams.find(StreamIdx); @@ -197,9 +186,9 @@ if (DumpStreamNum >= StreamCount) return make_error(raw_error_code::no_stream); - MappedBlockStream S(llvm::make_unique(DumpStreamNum, File), - File); - codeview::StreamReader R(S); + EXPECTED_GET_DECL_OR_RETURN( + S, MappedBlockStream::createIndexedStream(DumpStreamNum, File)); + codeview::StreamReader R(*S); while (R.bytesRemaining() > 0) { ArrayRef Data; uint32_t BytesToReadInBlock = std::min( @@ -216,11 +205,7 @@ Error LLVMOutputStyle::dumpInfoStream() { if (!opts::DumpHeaders) return Error::success(); - auto InfoS = File.getPDBInfoStream(); - if (auto EC = InfoS.takeError()) - return EC; - - InfoStream &IS = InfoS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(IS, File.getPDBInfoStream()); DictScope D(P, "PDB Stream"); P.printNumber("Version", IS.getVersion()); @@ -234,10 +219,7 @@ if (opts::DumpStreamDataName.empty()) return Error::success(); - auto InfoS = File.getPDBInfoStream(); - if (auto EC = InfoS.takeError()) - return EC; - InfoStream &IS = InfoS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(IS, File.getPDBInfoStream()); uint32_t NameStreamIndex = IS.getNamedStreamIndex(opts::DumpStreamDataName); if (NameStreamIndex == 0 || NameStreamIndex >= File.getNumStreams()) @@ -250,9 +232,10 @@ DictScope D(P, Name); P.printNumber("Index", NameStreamIndex); - MappedBlockStream NameStream( - llvm::make_unique(NameStreamIndex, File), File); - codeview::StreamReader Reader(NameStream); + EXPECTED_GET_DECL_OR_RETURN( + NameStream, + MappedBlockStream::createIndexedStream(NameStreamIndex, File)); + codeview::StreamReader Reader(*NameStream); NameHashTable NameTable; if (auto EC = NameTable.load(Reader)) @@ -311,11 +294,9 @@ if (!DumpRecordBytes && !DumpRecords && !opts::DumpModuleSyms) return Error::success(); - auto TpiS = (StreamIdx == StreamTPI) ? File.getPDBTpiStream() - : File.getPDBIpiStream(); - if (auto EC = TpiS.takeError()) - return EC; - TpiStream &Tpi = TpiS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(Tpi, (StreamIdx == StreamTPI) + ? File.getPDBTpiStream() + : File.getPDBIpiStream()); if (DumpRecords || DumpRecordBytes) { DictScope D(P, Label); @@ -367,10 +348,7 @@ if (!opts::DumpHeaders && !DumpModules) return Error::success(); - auto DbiS = File.getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return EC; - DbiStream &DS = DbiS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(DS, File.getPDBDbiStream()); DictScope D(P, "DBI Stream"); P.printNumber("Dbi Version", DS.getDbiVersion()); @@ -421,7 +399,10 @@ bool ShouldDumpSymbols = (opts::DumpModuleSyms || opts::DumpSymRecordBytes); if (HasModuleDI && (ShouldDumpSymbols || opts::DumpLineInfo)) { - ModStream ModS(File, Modi.Info); + EXPECTED_GET_DECL_OR_RETURN( + ModStreamData, MappedBlockStream::createIndexedStream( + Modi.Info.getModuleStreamIndex(), File)); + ModStream ModS(Modi.Info, std::move(ModStreamData)); if (auto EC = ModS.reload()) return EC; @@ -513,17 +494,11 @@ private: Expected getFileNameForOffset(uint32_t Offset) { - auto StringT = F.getStringTable(); - if (auto EC = StringT.takeError()) - return std::move(EC); - NameHashTable &ST = StringT.get(); + EXPECTED_GET_DECL_REF_OR_RETURN_EXPECTED(ST, F.getStringTable()); return ST.getStringForID(Offset); } Expected getFileNameForOffset2(uint32_t Offset) { - auto DbiS = F.getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return std::move(EC); - auto &DS = DbiS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN_EXPECTED(DS, F.getPDBDbiStream()); return DS.getFileNameForIndex(Offset); } ScopedPrinter &P; @@ -546,10 +521,7 @@ if (!opts::DumpSectionContribs) return Error::success(); - auto DbiS = File.getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return EC; - DbiStream &DS = DbiS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(Dbi, File.getPDBDbiStream()); ListScope L(P, "Section Contributions"); class Visitor : public ISectionContribVisitor { public: @@ -584,8 +556,8 @@ ScopedPrinter &P; DbiStream &DS; }; - Visitor V(P, DS); - DS.visitSectionContributions(V); + Visitor V(P, Dbi); + Dbi.visitSectionContributions(V); return Error::success(); } @@ -593,12 +565,9 @@ if (!opts::DumpSectionMap) return Error::success(); - auto DbiS = File.getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return EC; - DbiStream &DS = DbiS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(Dbi, File.getPDBDbiStream()); ListScope L(P, "Section Map"); - for (auto &M : DS.getSectionMap()) { + for (auto &M : Dbi.getSectionMap()) { DictScope D(P, "Entry"); P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames()); P.printNumber("Flags", M.Flags); @@ -619,11 +588,9 @@ return Error::success(); DictScope D(P, "Publics Stream"); - auto PublicsS = File.getPDBPublicsStream(); - if (auto EC = PublicsS.takeError()) - return EC; - PublicsStream &Publics = PublicsS.get(); - P.printNumber("Stream number", Publics.getStreamNum()); + EXPECTED_GET_DECL_REF_OR_RETURN(Publics, File.getPDBPublicsStream()); + EXPECTED_GET_DECL_REF_OR_RETURN(Dbi, File.getPDBDbiStream()); + P.printNumber("Stream number", Dbi.getPublicSymbolStreamIndex()); P.printNumber("SymHash", Publics.getSymHash()); P.printNumber("AddrMap", Publics.getAddrMap()); P.printNumber("Number of buckets", Publics.getNumBuckets()); @@ -654,13 +621,10 @@ if (!opts::DumpSectionHeaders) return Error::success(); - auto DbiS = File.getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return EC; - DbiStream &DS = DbiS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(Dbi, File.getPDBDbiStream()); ListScope D(P, "Section Headers"); - for (const object::coff_section &Section : DS.getSectionHeaders()) { + for (const object::coff_section &Section : Dbi.getSectionHeaders()) { DictScope DD(P, ""); // If a name is 8 characters long, there is no NUL character at end. @@ -684,13 +648,10 @@ if (!opts::DumpFpo) return Error::success(); - auto DbiS = File.getPDBDbiStream(); - if (auto EC = DbiS.takeError()) - return EC; - DbiStream &DS = DbiS.get(); + EXPECTED_GET_DECL_REF_OR_RETURN(Dbi, File.getPDBDbiStream()); ListScope D(P, "New FPO"); - for (const object::FpoData &Fpo : DS.getFpoRecords()) { + for (const object::FpoData &Fpo : Dbi.getFpoRecords()) { DictScope DD(P, ""); P.printNumber("Offset", Fpo.Offset); P.printNumber("Size", Fpo.Size);