Index: llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h +++ llvm/include/llvm/DebugInfo/PDB/Native/HashTable.h @@ -37,7 +37,7 @@ class HashTableIterator : public iterator_facade_base, std::forward_iterator_tag, - std::pair> { + const std::pair> { friend HashTable; HashTableIterator(const HashTable &Map, uint32_t Index, @@ -72,6 +72,12 @@ assert(Map->Present.test(Index)); return Map->Buckets[Index]; } + + // Implement postfix op++ in terms of prefix op++ by using the superclass + // implementation. + using iterator_facade_base, + std::forward_iterator_tag, + const std::pair>::operator++; HashTableIterator &operator++() { while (Index < Map->Buckets.size()) { ++Index; @@ -102,9 +108,6 @@ template > class HashTable { - using iterator = HashTableIterator; - friend iterator; - struct Header { support::ulittle32_t Size; support::ulittle32_t Capacity; @@ -113,6 +116,9 @@ using BucketList = std::vector>; public: + using const_iterator = HashTableIterator; + friend const_iterator; + HashTable() { Buckets.resize(8); } explicit HashTable(TraitsT Traits) : HashTable(8, std::move(Traits)) {} @@ -216,19 +222,19 @@ uint32_t capacity() const { return Buckets.size(); } uint32_t size() const { return Present.count(); } - iterator begin() const { return iterator(*this); } - iterator end() const { return iterator(*this, 0, true); } + const_iterator begin() const { return const_iterator(*this); } + const_iterator end() const { return const_iterator(*this, 0, true); } /// Find the entry whose key has the specified hash value, using the specified /// traits defining hash function and equality. - template iterator find_as(const Key &K) const { + template const_iterator find_as(const Key &K) const { uint32_t H = Traits.hashLookupKey(K) % capacity(); uint32_t I = H; Optional FirstUnused; do { if (isPresent(I)) { if (Traits.storageKeyToLookupKey(Buckets[I].first) == K) - return iterator(*this, I, false); + return const_iterator(*this, I, false); } else { if (!FirstUnused) FirstUnused = I; @@ -247,7 +253,7 @@ // table were Present. But this would violate the load factor constraints // that we impose, so it should never happen. assert(FirstUnused); - return iterator(*this, *FirstUnused, true); + return const_iterator(*this, *FirstUnused, true); } /// Set the entry using a key type that the specified Traits can convert Index: llvm/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h =================================================================== --- /dev/null +++ llvm/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h @@ -0,0 +1,60 @@ +//===- InjectedSourceStream.h - PDB Headerblock Stream Access ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINJECTEDSOURCESTREAM_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBINJECTEDSOURCESTREAM_H + +#include "llvm/DebugInfo/PDB/Native/HashTable.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace msf { +class MappedBlockStream; +} +namespace pdb { +class PDBFile; +class PDBStringTable; + +struct StringTableHashTraits { + const PDBStringTable &Strings; + + explicit StringTableHashTraits(const PDBStringTable &Strings); + uint16_t hashLookupKey(StringRef S) const; + StringRef storageKeyToLookupKey(uint32_t Offset) const; + uint32_t lookupKeyToStorageKey(StringRef S); +}; + +class InjectedSourceStream { +public: + InjectedSourceStream(std::unique_ptr Stream, + const PDBStringTable &Strings); + ~InjectedSourceStream(); + Error reload(); + + using const_iterator = + HashTable::const_iterator; + const_iterator begin() const { return InjectedSourceTable.begin(); } + const_iterator end() const { return InjectedSourceTable.end(); } + + uint32_t size() const { return InjectedSourceTable.size(); } + +private: + Error readHeader(BinaryStreamReader &Reader); + + std::unique_ptr Stream; + const PDBStringTable &Strings; + StringTableHashTraits Traits; + + const SrcHeaderBlockHeader* Header; + HashTable InjectedSourceTable; +}; +} +} + +#endif Index: llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h =================================================================== --- /dev/null +++ llvm/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h @@ -0,0 +1,43 @@ +//==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMINJECTEDSOURCES_H +#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMINJECTEDSOURCES_H + +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" +#include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h" + +namespace llvm { +namespace pdb { + +class InjectedSourceStream; +class PDBStringTable; + +class NativeEnumInjectedSources : public IPDBEnumChildren { +public: + NativeEnumInjectedSources(PDBFile &File, const InjectedSourceStream &IJS, + const PDBStringTable &Strings); + + uint32_t getChildCount() const override; + std::unique_ptr + getChildAtIndex(uint32_t Index) const override; + std::unique_ptr getNext() override; + void reset() override; + +private: + PDBFile &File; + const InjectedSourceStream &Stream; + const PDBStringTable &Strings; + InjectedSourceStream::const_iterator Cur; +}; + +} // namespace pdb +} // namespace llvm + +#endif Index: llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h +++ llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h @@ -32,6 +32,7 @@ class DbiStream; class GlobalsStream; class InfoStream; +class InjectedSourceStream; class PDBStringTable; class PDBFileBuilder; class PublicsStream; @@ -99,6 +100,7 @@ Expected getPDBPublicsStream(); Expected getPDBSymbolStream(); Expected getStringTable(); + Expected getInjectedSourceStream(); BumpPtrAllocator &getAllocator() { return Allocator; } @@ -110,15 +112,14 @@ bool hasPDBSymbolStream(); bool hasPDBTpiStream() const; bool hasPDBStringTable(); + bool hasPDBInjectedSourceStream(); uint32_t getPointerSize(); -private: Expected> - safelyCreateIndexedStream(const msf::MSFLayout &Layout, - BinaryStreamRef MsfData, - uint32_t StreamIndex) const; + safelyCreateIndexedStream(uint32_t StreamIndex) const; +private: std::string FilePath; BumpPtrAllocator &Allocator; @@ -135,6 +136,7 @@ std::unique_ptr Symbols; std::unique_ptr DirectoryStream; std::unique_ptr StringTableStream; + std::unique_ptr InjectedSources; std::unique_ptr Strings; }; } Index: llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h +++ llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -96,8 +96,9 @@ std::unique_ptr Ipi; PDBStringTableBuilder Strings; - StringTableHashTraits InjectedSourceHashTraits; - HashTable InjectedSourceTable; + StringTableBuilderHashTraits InjectedSourceHashTraits; + HashTable + InjectedSourceTable; SmallVector InjectedSources; Index: llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h =================================================================== --- llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h +++ llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -32,10 +32,10 @@ class PDBFileBuilder; class PDBStringTableBuilder; -struct StringTableHashTraits { +struct StringTableBuilderHashTraits { PDBStringTableBuilder *Table; - explicit StringTableHashTraits(PDBStringTableBuilder &Table); + explicit StringTableBuilderHashTraits(PDBStringTableBuilder &Table); uint32_t hashLookupKey(StringRef S) const; StringRef storageKeyToLookupKey(uint32_t Offset) const; uint32_t lookupKeyToStorageKey(StringRef S); Index: llvm/lib/DebugInfo/PDB/CMakeLists.txt =================================================================== --- llvm/lib/DebugInfo/PDB/CMakeLists.txt +++ llvm/lib/DebugInfo/PDB/CMakeLists.txt @@ -47,9 +47,11 @@ Native/HashTable.cpp Native/InfoStream.cpp Native/InfoStreamBuilder.cpp + Native/InjectedSourceStream.cpp Native/ModuleDebugStream.cpp Native/NativeCompilandSymbol.cpp Native/NativeEnumGlobals.cpp + Native/NativeEnumInjectedSources.cpp Native/NativeEnumModules.cpp Native/NativeEnumTypes.cpp Native/NativeExeSymbol.cpp Index: llvm/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp =================================================================== --- /dev/null +++ llvm/lib/DebugInfo/PDB/Native/InjectedSourceStream.cpp @@ -0,0 +1,90 @@ +//===- InjectedSourceStream.cpp - PDB Headerblock Stream Access -----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h" + +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryStreamReader.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::support; +using namespace llvm::pdb; + +StringTableHashTraits::StringTableHashTraits(const PDBStringTable &Strings) + : Strings(Strings) {} + +uint16_t StringTableHashTraits::hashLookupKey(StringRef S) const { + // See comment in StringTableBuilderHashTraits::hashLookupKey(). + return static_cast(hashStringV1(S)); +} + +StringRef StringTableHashTraits::storageKeyToLookupKey(uint32_t Offset) const { + auto Name = Strings.getStringForID(Offset); + if (!Name) { + assert(false); + consumeError(Name.takeError()); + return "XXX blah"; + } + return *Name; +} + +uint32_t StringTableHashTraits::lookupKeyToStorageKey(StringRef S) { + auto ID = Strings.getIDForString(S); + if (!ID) { + assert(false); + consumeError(ID.takeError()); + return 0; + } + return *ID; +} + +InjectedSourceStream::InjectedSourceStream( + std::unique_ptr Stream, const PDBStringTable &Strings) + : Stream(std::move(Stream)), Strings(Strings), Traits(Strings), + InjectedSourceTable(Traits) {} + +InjectedSourceStream::~InjectedSourceStream() {} + +Error InjectedSourceStream::readHeader(BinaryStreamReader &Reader) { + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} + +Error InjectedSourceStream::reload() { + BinaryStreamReader Reader(*Stream); + + if (auto EC = Reader.readObject(Header)) + return EC; + + if (Header->Version != + static_cast(PdbRaw_SrcHeaderBlockVer::SrcVerOne)) + return make_error(raw_error_code::corrupt_file, + "Invalid headerblock header version"); + + if (auto EC = InjectedSourceTable.load(Reader)) + return EC; + + for (const auto& Entry : *this) { + if (Entry.second.Size != sizeof(SrcHeaderBlockEntry)) + return make_error(raw_error_code::corrupt_file, + "Invalid headerbock entry size"); + if (Entry.second.Version != + static_cast(PdbRaw_SrcHeaderBlockVer::SrcVerOne)) + return make_error(raw_error_code::corrupt_file, + "Invalid headerbock entry version"); + } + + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} Index: llvm/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp =================================================================== --- /dev/null +++ llvm/lib/DebugInfo/PDB/Native/NativeEnumInjectedSources.cpp @@ -0,0 +1,142 @@ +//==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h" + +#include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/PDBFile.h" +#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" + +namespace llvm { +namespace pdb { + +namespace { + +class NativeInjectedSource : public IPDBInjectedSource { + InjectedSourceStream::const_iterator I; + const PDBStringTable &Strings; + PDBFile &File; + +public: + NativeInjectedSource(InjectedSourceStream::const_iterator I, + PDBFile &File, const PDBStringTable &Strings) + : I(I), Strings(Strings), File(File) {} + + uint32_t getCrc32() const override { return I->second.CRC; } + uint64_t getCodeByteSize() const override { return I->second.FileSize; } + + std::string getFileName() const override { + auto Name = Strings.getStringForID(I->second.FileNI); + if (!Name) { + consumeError(Name.takeError()); + return "(invalid file name ref)"; + } + return *Name; + } + + std::string getObjectFileName() const override { + auto ObjName = Strings.getStringForID(I->second.ObjNI); + if (!ObjName) { + consumeError(ObjName.takeError()); + return "(invalid object file name ref)"; + } + return *ObjName; + } + + std::string getVirtualFileName() const override { + auto VName = Strings.getStringForID(I->second.VFileNI); + if (!VName) { + consumeError(VName.takeError()); + return "(invalid virtual file name ref)"; + } + return *VName; + } + + PDB_SourceCompression getCompression() const override { + return static_cast(I->second.Compression); + } + + std::string getCode() const override { + auto VName = Strings.getStringForID(I->second.VFileNI); + if (!VName) { + consumeError(VName.takeError()); + return "(invalid virtual file name ref)"; + } + + auto IS = File.getPDBInfoStream(); + if (!IS) { + consumeError(IS.takeError()); + return "(no info stream)"; + } + + std::string StreamName = ("/src/files/" + *VName).str(); + Expected ExpectedNSI = IS->getNamedStreamIndex(StreamName); + if (!ExpectedNSI) { + consumeError(ExpectedNSI.takeError()); + return ("(no entry for " + *VName + ")").str(); + } + uint32_t NameStreamIndex = *ExpectedNSI; + auto ExpectedFileStream = File.safelyCreateIndexedStream(NameStreamIndex); + if (!ExpectedFileStream) { + consumeError(ExpectedFileStream.takeError()); + return ("(entry for " + *VName + " invalid)").str(); + } + + std::unique_ptr FileStream = + std::move(*ExpectedFileStream); + + std::string Result; + uint32_t DataLength = FileStream->getLength(); + uint32_t Offset = 0; + while (Offset < DataLength) { + ArrayRef Data; + if (auto E = FileStream->readLongestContiguousChunk(Offset, Data)) { + consumeError(std::move(E)); + return "(failed to read data)"; + } + Offset += Data.size(); + Result += toStringRef(Data); + } + + // This will have to call a future method in InjectedSourceStream that + // appends getVirtualFileName() to "/src/files" and return the data of that + // named stream. + // Really want: return InjectedSourceStream.getCodeFor(VName) (?) + return Result; + } +}; + +} // namespace + +NativeEnumInjectedSources::NativeEnumInjectedSources( + PDBFile &File, const InjectedSourceStream &IJS, + const PDBStringTable &Strings) + : File(File), Stream(IJS), Strings(Strings), Cur(Stream.begin()) {} + +uint32_t NativeEnumInjectedSources::getChildCount() const { + return static_cast(Stream.size()); +} + +std::unique_ptr +NativeEnumInjectedSources::getChildAtIndex(uint32_t N) const { + if (N >= getChildCount()) + return nullptr; + return make_unique(std::next(Stream.begin(), N), File, + Strings); +} + +std::unique_ptr NativeEnumInjectedSources::getNext() { + if (Cur == Stream.end()) + return nullptr; + return make_unique(Cur++, File, Strings); +} + +void NativeEnumInjectedSources::reset() { Cur = Stream.begin(); } + +} +} Index: llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ llvm/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h" +#include "llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h" #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h" #include "llvm/DebugInfo/PDB/Native/NativeExeSymbol.h" #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h" @@ -191,7 +192,17 @@ std::unique_ptr NativeSession::getInjectedSources() const { - return nullptr; + auto ISS = Pdb->getInjectedSourceStream(); + if (!ISS) { + consumeError(ISS.takeError()); + return nullptr; + } + auto ST = Pdb->getStringTable(); + if (!ST) { + consumeError(ST.takeError()); + return nullptr; + } + return make_unique(*Pdb, *ISS, *ST); } std::unique_ptr Index: llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" +#include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" @@ -258,8 +259,8 @@ if (!DbiS) return DbiS.takeError(); - auto GlobalS = safelyCreateIndexedStream( - ContainerLayout, *Buffer, DbiS->getGlobalSymbolStreamIndex()); + auto GlobalS = + safelyCreateIndexedStream(DbiS->getGlobalSymbolStreamIndex()); if (!GlobalS) return GlobalS.takeError(); auto TempGlobals = llvm::make_unique(std::move(*GlobalS)); @@ -272,7 +273,7 @@ Expected PDBFile::getPDBInfoStream() { if (!Info) { - auto InfoS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamPDB); + auto InfoS = safelyCreateIndexedStream(StreamPDB); if (!InfoS) return InfoS.takeError(); auto TempInfo = llvm::make_unique(std::move(*InfoS)); @@ -285,7 +286,7 @@ Expected PDBFile::getPDBDbiStream() { if (!Dbi) { - auto DbiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamDBI); + auto DbiS = safelyCreateIndexedStream(StreamDBI); if (!DbiS) return DbiS.takeError(); auto TempDbi = llvm::make_unique(std::move(*DbiS)); @@ -298,7 +299,7 @@ Expected PDBFile::getPDBTpiStream() { if (!Tpi) { - auto TpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamTPI); + auto TpiS = safelyCreateIndexedStream(StreamTPI); if (!TpiS) return TpiS.takeError(); auto TempTpi = llvm::make_unique(*this, std::move(*TpiS)); @@ -314,7 +315,7 @@ if (!hasPDBIpiStream()) return make_error(raw_error_code::no_stream); - auto IpiS = safelyCreateIndexedStream(ContainerLayout, *Buffer, StreamIPI); + auto IpiS = safelyCreateIndexedStream(StreamIPI); if (!IpiS) return IpiS.takeError(); auto TempIpi = llvm::make_unique(*this, std::move(*IpiS)); @@ -331,8 +332,8 @@ if (!DbiS) return DbiS.takeError(); - auto PublicS = safelyCreateIndexedStream( - ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex()); + auto PublicS = + safelyCreateIndexedStream(DbiS->getPublicSymbolStreamIndex()); if (!PublicS) return PublicS.takeError(); auto TempPublics = llvm::make_unique(std::move(*PublicS)); @@ -350,8 +351,7 @@ return DbiS.takeError(); uint32_t SymbolStreamNum = DbiS->getSymRecordStreamIndex(); - auto SymbolS = - safelyCreateIndexedStream(ContainerLayout, *Buffer, SymbolStreamNum); + auto SymbolS = safelyCreateIndexedStream(SymbolStreamNum); if (!SymbolS) return SymbolS.takeError(); @@ -374,8 +374,7 @@ return ExpectedNSI.takeError(); uint32_t NameStreamIndex = *ExpectedNSI; - auto NS = - safelyCreateIndexedStream(ContainerLayout, *Buffer, NameStreamIndex); + auto NS = safelyCreateIndexedStream(NameStreamIndex); if (!NS) return NS.takeError(); @@ -390,6 +389,35 @@ return *Strings; } +Expected PDBFile::getInjectedSourceStream() { + if (!InjectedSources) { + auto IS = getPDBInfoStream(); + if (!IS) + return IS.takeError(); + + Expected ExpectedNSI = + IS->getNamedStreamIndex("/src/headerblock"); + if (!ExpectedNSI) + return ExpectedNSI.takeError(); + uint32_t InjectedSourceStreamIndex = *ExpectedNSI; + + auto IJS = safelyCreateIndexedStream(InjectedSourceStreamIndex); + if (!IJS) + return IJS.takeError(); + + auto Strings = getStringTable(); + if (!Strings) + return Strings.takeError(); + + auto IJ = + llvm::make_unique(std::move(*IJS), *Strings); + if (auto EC = IJ->reload()) + return std::move(EC); + InjectedSources = std::move(IJ); + } + return *InjectedSources; +} + uint32_t PDBFile::getPointerSize() { auto DbiS = getPDBDbiStream(); if (!DbiS) @@ -458,16 +486,27 @@ return true; } +bool PDBFile::hasPDBInjectedSourceStream() { + auto IS = getPDBInfoStream(); + if (!IS) + return false; + Expected ExpectedNSI = IS->getNamedStreamIndex("/src/headerblock"); + if (!ExpectedNSI) { + consumeError(ExpectedNSI.takeError()); + return false; + } + assert(*ExpectedNSI < getNumStreams()); + return true; +} + /// 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, - BinaryStreamRef MsfData, - uint32_t StreamIndex) const { +PDBFile::safelyCreateIndexedStream(uint32_t StreamIndex) const { if (StreamIndex >= getNumStreams()) return make_error(raw_error_code::no_stream); - return MappedBlockStream::createIndexedStream(Layout, MsfData, StreamIndex, - Allocator); + return MappedBlockStream::createIndexedStream(ContainerLayout, *Buffer, + StreamIndex, Allocator); } Index: llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp =================================================================== --- llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp +++ llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp @@ -22,10 +22,11 @@ using namespace llvm::support::endian; using namespace llvm::pdb; -StringTableHashTraits::StringTableHashTraits(PDBStringTableBuilder &Table) +StringTableBuilderHashTraits::StringTableBuilderHashTraits( + PDBStringTableBuilder &Table) : Table(&Table) {} -uint32_t StringTableHashTraits::hashLookupKey(StringRef S) const { +uint32_t StringTableBuilderHashTraits::hashLookupKey(StringRef S) const { // The reference implementation doesn't include code for /src/headerblock // handling, but it can only read natvis entries lld's PDB files if // this hash function truncates the hash to 16 bit. @@ -35,11 +36,12 @@ return static_cast(Table->getIdForString(S)); } -StringRef StringTableHashTraits::storageKeyToLookupKey(uint32_t Offset) const { +StringRef +StringTableBuilderHashTraits::storageKeyToLookupKey(uint32_t Offset) const { return Table->getStringForId(Offset); } -uint32_t StringTableHashTraits::lookupKeyToStorageKey(StringRef S) { +uint32_t StringTableBuilderHashTraits::lookupKeyToStorageKey(StringRef S) { return Table->insert(S); } Index: llvm/test/tools/llvm-pdbutil/injected-sources-native.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-pdbutil/injected-sources-native.test @@ -0,0 +1,30 @@ +; This is identical to injected-sources.test, except that it uses the -native +; mode of pretty (and hence doesn't require diasdk and runs on all platforms). + +; RUN: llvm-pdbutil pretty -native -injected-sources -injected-source-content \ +; RUN: %p/Inputs/InjectedSource.pdb | FileCheck %s +; RUN: llvm-pdbutil pretty -native -injected-sources -injected-source-content \ +; RUN: %p/Inputs/ClassLayoutTest.pdb | FileCheck --check-prefix=NEGATIVE %s + +; CHECK: ---INJECTED SOURCES--- +; CHECK: c.natvis (140 bytes): obj=, vname=c.natvis, crc=334478030, compression=None +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK: a.natvis (140 bytes): obj=, vname=a.natvis, crc=334478030, compression=None +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK: b.natvis (294 bytes): obj=, vname=b.natvis, crc=2059731902, compression=None +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK-NEXT: Third test +; CHECK-NEXT: +; CHECK-NEXT: +; CHECK-NEXT: Fourth test +; CHECK-NEXT: +; CHECK-NEXT: + +; NEGATIVE: ---INJECTED SOURCES--- +; NEGATIVE-NEXT: There are no injected sources. Index: llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp =================================================================== --- llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -934,7 +934,7 @@ static void dumpInjectedSources(LinePrinter &Printer, IPDBSession &Session) { auto Sources = Session.getInjectedSources(); - if (0 == Sources->getChildCount()) { + if (!Sources || !Sources->getChildCount()) { Printer.printLine("There are no injected sources."); return; } @@ -1279,12 +1279,7 @@ WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---INJECTED SOURCES---"; AutoIndent Indent1(Printer); - - if (ReaderType == PDB_ReaderType::Native) - Printer.printLine( - "Injected sources are not supported with the native reader."); - else - dumpInjectedSources(Printer, *Session); + dumpInjectedSources(Printer, *Session); } Printer.NewLine(); Index: llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn =================================================================== --- llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn +++ llvm/utils/gn/secondary/llvm/lib/DebugInfo/PDB/BUILD.gn @@ -24,10 +24,12 @@ "Native/HashTable.cpp", "Native/InfoStream.cpp", "Native/InfoStreamBuilder.cpp", + "Native/InjectedSourceStream.cpp", "Native/ModuleDebugStream.cpp", "Native/NamedStreamMap.cpp", "Native/NativeCompilandSymbol.cpp", "Native/NativeEnumGlobals.cpp", + "Native/NativeEnumInjectedSources.cpp", "Native/NativeEnumModules.cpp", "Native/NativeEnumTypes.cpp", "Native/NativeExeSymbol.cpp",