SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings;
};
+/// Read a complete record from a stream at a random offset.
+template <typename Kind>
+inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream,
+ uint32_t Offset) {
+ const RecordPrefix *Prefix = nullptr;
+ BinaryStreamReader Reader(Stream);
+ Reader.setOffset(Offset);
+
+ if (auto EC = Reader.readObject(Prefix))
+ return std::move(EC);
+ if (Prefix->RecordLen < 2)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+ Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
+
+ Reader.setOffset(Offset);
+ ArrayRef<uint8_t> RawData;
+ if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
+ return std::move(EC);
+ return codeview::CVRecord<Kind>(K, RawData);
+}
+
} // end namespace codeview
template <typename Kind>
struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::CVRecord<Kind> &Item) {
- using namespace codeview;
- const RecordPrefix *Prefix = nullptr;
- BinaryStreamReader Reader(Stream);
- uint32_t Offset = Reader.getOffset();
-
- if (auto EC = Reader.readObject(Prefix))
- return EC;
- if (Prefix->RecordLen < 2)
- return make_error<CodeViewError>(cv_error_code::corrupt_record);
- Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
-
- Reader.setOffset(Offset);
- ArrayRef<uint8_t> RawData;
- if (auto EC =
- Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
- return EC;
- Item = codeview::CVRecord<Kind>(K, RawData);
- Len = Item.length();
+ auto ExpectedRec = codeview::readCVRecordFromStream<Kind>(Stream, 0);
+ if (!ExpectedRec)
+ return ExpectedRec.takeError();
+ Item = *ExpectedRec;
+ Len = ExpectedRec->length();
return Error::success();
}
};
using CVSymbol = CVRecord<SymbolKind>;
using CVSymbolArray = VarStreamArray<CVSymbol>;
+Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
+ uint32_t Offset);
+
} // end namespace codeview
} // end namespace llvm
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Error.h"
+#include "llvm/ADT/iterator.h"
namespace llvm {
namespace pdb {
class DbiStream;
class PDBFile;
+/// Iterator over hash records producing symbol record offsets. Abstracts away
+/// the fact that symbol record offsets on disk are off-by-one.
+class GSIHashIterator
+ : public iterator_adaptor_base<
+ GSIHashIterator, FixedStreamArrayIterator<PSHashRecord>,
+ std::random_access_iterator_tag, const uint32_t> {
+public:
+ GSIHashIterator() = default;
+
+ template <typename T>
+ GSIHashIterator(T &&v)
+ : GSIHashIterator::iterator_adaptor_base(std::forward<T &&>(v)) {}
+
+ uint32_t operator*() const {
+ uint32_t Off = this->I->Off;
+ return --Off;
+ }
+};
+
+/// From https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp
+enum : unsigned { IPHR_HASH = 4096 };
+
+/// A readonly view of a hash table used in the globals and publics streams.
+/// Most clients will only want to iterate this to get symbol record offsets
+/// into the PDB symbol stream.
+class GSIHashTable {
+public:
+ const GSIHashHeader *HashHdr;
+ FixedStreamArray<PSHashRecord> HashRecords;
+ ArrayRef<uint8_t> HashBitmap;
+ FixedStreamArray<support::ulittle32_t> HashBuckets;
+
+ Error read(BinaryStreamReader &Reader);
+
+ typedef GSIHashHeader iterator;
+ GSIHashIterator begin() const { return GSIHashIterator(HashRecords.begin()); }
+ GSIHashIterator end() const { return GSIHashIterator(HashRecords.end()); }
+};
+
class GlobalsStream {
public:
explicit GlobalsStream(std::unique_ptr<msf::MappedBlockStream> Stream);
~GlobalsStream();
- Error commit();
- FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
- return HashBuckets;
- }
- uint32_t getNumBuckets() const { return NumBuckets; }
+ const GSIHashTable &getGlobalsTable() const { return GlobalsTable; }
Error reload();
private:
- FixedStreamArray<PSHashRecord> HashRecords;
- ArrayRef<uint8_t> HashBitmap;
- FixedStreamArray<support::ulittle32_t> HashBuckets;
- uint32_t NumBuckets;
+ GSIHashTable GlobalsTable;
std::unique_ptr<msf::MappedBlockStream> Stream;
};
}
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
class PublicsStream {
public:
- PublicsStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
+ PublicsStream(std::unique_ptr<msf::MappedBlockStream> Stream);
~PublicsStream();
Error reload();
uint32_t getSymHash() const;
uint32_t getAddrMap() const;
- uint32_t getNumBuckets() const { return NumBuckets; }
- Expected<const codeview::CVSymbolArray &> getSymbolArray() const;
- iterator_range<codeview::CVSymbolArray::Iterator>
- getSymbols(bool *HadError) const;
- FixedStreamArray<PSHashRecord> getHashRecords() const { return HashRecords; }
- ArrayRef<uint8_t> getHashBitmap() const { return HashBitmap; }
- FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
- return HashBuckets;
- }
+ const GSIHashTable &getPublicsTable() const { return PublicsTable; }
FixedStreamArray<support::ulittle32_t> getAddressMap() const {
return AddressMap;
}
return SectionOffsets;
}
- Error commit();
-
private:
- PDBFile &Pdb;
-
std::unique_ptr<msf::MappedBlockStream> Stream;
- uint32_t NumBuckets = 0;
- FixedStreamArray<PSHashRecord> HashRecords;
- ArrayRef<uint8_t> HashBitmap;
- FixedStreamArray<support::ulittle32_t> HashBuckets;
+ GSIHashTable PublicsTable;
FixedStreamArray<support::ulittle32_t> AddressMap;
FixedStreamArray<support::ulittle32_t> ThunkMap;
FixedStreamArray<SectionOffset> SectionOffsets;
const PublicsStreamHeader *Header;
- const GSIHashHeader *HashHdr;
};
}
}
char Padding[2];
};
+/// Header of the hash tables found in the globals and publics sections.
+/// Based on GSIHashHdr in
+/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+struct GSIHashHeader {
+ enum : unsigned {
+ HdrSignature = ~0U,
+ HdrVersion = 0xeffe0000 + 19990810,
+ };
+ support::ulittle32_t VerSignature;
+ support::ulittle32_t VerHdr;
+ support::ulittle32_t HrSize;
+ support::ulittle32_t NumBuckets;
+};
+
// This is HRFile.
struct PSHashRecord {
support::ulittle32_t Off; // Offset in the symbol record stream
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/BinaryByteStream.h"
return Reader.readCString(Item);
}
+
+Expected<CVSymbol> llvm::codeview::readSymbolFromStream(BinaryStreamRef Stream,
+ uint32_t Offset) {
+ return readCVRecordFromStream<SymbolKind>(Stream, Offset);
+}
Native/DbiStreamBuilder.cpp
Native/EnumTables.cpp
Native/GlobalsStream.cpp
- Native/GSI.cpp
Native/Hash.cpp
Native/HashTable.cpp
Native/InfoStream.cpp
+++ /dev/null
-//===- GSI.cpp - Common Functions for GlobalsStream and PublicsStream ----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "GSI.h"
-
-#include "llvm/DebugInfo/PDB/Native/RawError.h"
-#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
-#include "llvm/Support/BinaryStreamArray.h"
-#include "llvm/Support/BinaryStreamReader.h"
-
-#include "llvm/Support/Error.h"
-
-namespace llvm {
-namespace pdb {
-
-static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
- if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
- return make_error<RawError>(
- raw_error_code::feature_unsupported,
- "Encountered unsupported globals stream version.");
-
- return Error::success();
-}
-
-Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
- ArrayRef<uint8_t> &HashBitmap,
- const GSIHashHeader *HashHdr,
- BinaryStreamReader &Reader) {
- if (auto EC = checkHashHdrVersion(HashHdr))
- return EC;
-
- // Before the actual hash buckets, there is a bitmap of length determined by
- // IPHR_HASH.
- size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
- uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
- if (auto EC = Reader.readBytes(HashBitmap, NumBitmapEntries))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Could not read a bitmap."));
- uint32_t NumBuckets = 0;
- for (uint8_t B : HashBitmap)
- NumBuckets += countPopulation(B);
-
- // Hash buckets follow.
- if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Hash buckets corrupted."));
-
- return Error::success();
-}
-
-Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
- BinaryStreamReader &Reader) {
- if (Reader.readObject(HashHdr))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Stream does not contain a GSIHashHeader.");
-
- if (HashHdr->VerSignature != GSIHashHeader::HdrSignature)
- return make_error<RawError>(
- raw_error_code::feature_unsupported,
- "GSIHashHeader signature (0xffffffff) not found.");
-
- return Error::success();
-}
-
-Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
- const GSIHashHeader *HashHdr,
- BinaryStreamReader &Reader) {
- if (auto EC = checkHashHdrVersion(HashHdr))
- return EC;
-
- // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have.
- // Verify that we can read them all.
- if (HashHdr->HrSize % sizeof(PSHashRecord))
- return make_error<RawError>(raw_error_code::corrupt_file,
- "Invalid HR array size.");
- uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
- if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
- return joinErrors(std::move(EC),
- make_error<RawError>(raw_error_code::corrupt_file,
- "Error reading hash records."));
-
- return Error::success();
-}
-}
-}
namespace pdb {
-/// From https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp
-static const unsigned IPHR_HASH = 4096;
-
-/// Header of the hash tables found in the globals and publics sections.
-/// Based on GSIHashHdr in
-/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
-struct GSIHashHeader {
- enum : unsigned {
- HdrSignature = ~0U,
- HdrVersion = 0xeffe0000 + 19990810,
- };
- support::ulittle32_t VerSignature;
- support::ulittle32_t VerHdr;
- support::ulittle32_t HrSize;
- support::ulittle32_t NumBuckets;
-};
-
Error readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
ArrayRef<uint8_t> &HashBitmap,
const GSIHashHeader *HashHdr,
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+//
+// The on-disk structores used in this file are based on the reference
+// implementation which is available at
+// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+//
+// When you are reading the reference source code, you'd find the
+// information below useful.
+//
+// - ppdb1->m_fMinimalDbgInfo seems to be always true.
+// - SMALLBUCKETS macro is defined.
+//
+//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
-#include "GSI.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Error.h"
#include <algorithm>
Error GlobalsStream::reload() {
BinaryStreamReader Reader(*Stream);
+ if (auto E = GlobalsTable.read(Reader))
+ return E;
+ return Error::success();
+}
- const GSIHashHeader *HashHdr;
- if (auto EC = readGSIHashHeader(HashHdr, Reader))
- return EC;
+static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) {
+ if (HashHdr->VerHdr != GSIHashHeader::HdrVersion)
+ return make_error<RawError>(
+ raw_error_code::feature_unsupported,
+ "Encountered unsupported globals stream version.");
- if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
+ return Error::success();
+}
+
+static Error readGSIHashHeader(const GSIHashHeader *&HashHdr,
+ BinaryStreamReader &Reader) {
+ if (Reader.readObject(HashHdr))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Stream does not contain a GSIHashHeader.");
+
+ if (HashHdr->VerSignature != GSIHashHeader::HdrSignature)
+ return make_error<RawError>(
+ raw_error_code::feature_unsupported,
+ "GSIHashHeader signature (0xffffffff) not found.");
+
+ return Error::success();
+}
+
+static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords,
+ const GSIHashHeader *HashHdr,
+ BinaryStreamReader &Reader) {
+ if (auto EC = checkHashHdrVersion(HashHdr))
return EC;
- if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader))
+ // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have.
+ // Verify that we can read them all.
+ if (HashHdr->HrSize % sizeof(PSHashRecord))
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid HR array size.");
+ uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord);
+ if (auto EC = Reader.readArray(HashRecords, NumHashRecords))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Error reading hash records."));
+
+ return Error::success();
+}
+
+static Error
+readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets,
+ ArrayRef<uint8_t> &HashBitmap, const GSIHashHeader *HashHdr,
+ BinaryStreamReader &Reader) {
+ if (auto EC = checkHashHdrVersion(HashHdr))
return EC;
- NumBuckets = HashBuckets.size();
+
+ // Before the actual hash buckets, there is a bitmap of length determined by
+ // IPHR_HASH.
+ size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
+ uint32_t NumBitmapEntries = BitmapSizeInBits / 8;
+ if (auto EC = Reader.readBytes(HashBitmap, NumBitmapEntries))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Could not read a bitmap."));
+ uint32_t NumBuckets = 0;
+ for (uint8_t B : HashBitmap)
+ NumBuckets += countPopulation(B);
+
+ // Hash buckets follow.
+ if (auto EC = Reader.readArray(HashBuckets, NumBuckets))
+ return joinErrors(std::move(EC),
+ make_error<RawError>(raw_error_code::corrupt_file,
+ "Hash buckets corrupted."));
return Error::success();
}
-Error GlobalsStream::commit() { return Error::success(); }
+Error GSIHashTable::read(BinaryStreamReader &Reader) {
+ if (auto EC = readGSIHashHeader(HashHdr, Reader))
+ return EC;
+ if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
+ return EC;
+ if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader))
+ return EC;
+ return Error::success();
+}
ContainerLayout, *Buffer, DbiS->getPublicSymbolStreamIndex());
if (!PublicS)
return PublicS.takeError();
- auto TempPublics =
- llvm::make_unique<PublicsStream>(*this, std::move(*PublicS));
+ auto TempPublics = llvm::make_unique<PublicsStream>(std::move(*PublicS));
if (auto EC = TempPublics->reload())
return std::move(EC);
Publics = std::move(TempPublics);
using namespace llvm::support;
using namespace llvm::pdb;
-PublicsStream::PublicsStream(PDBFile &File,
- std::unique_ptr<MappedBlockStream> Stream)
- : Pdb(File), Stream(std::move(Stream)) {}
+PublicsStream::PublicsStream(std::unique_ptr<MappedBlockStream> Stream)
+ : Stream(std::move(Stream)) {}
PublicsStream::~PublicsStream() = default;
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
- // Read PSGSIHDR and GSIHashHdr structs.
+ // Read PSGSIHDR struct.
if (Reader.readObject(Header))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
- if (auto EC = readGSIHashHeader(HashHdr, Reader))
- return EC;
-
- if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader))
- return EC;
-
- if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader))
- return EC;
- NumBuckets = HashBuckets.size();
+ // Read the hash table.
+ if (auto E = PublicsTable.read(Reader))
+ return E;
// Something called "address map" follows.
uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t);
"Corrupted publics stream.");
return Error::success();
}
-
-iterator_range<codeview::CVSymbolArray::Iterator>
-PublicsStream::getSymbols(bool *HadError) const {
- auto SymbolS = Pdb.getPDBSymbolStream();
- if (SymbolS.takeError()) {
- codeview::CVSymbolArray::Iterator Iter;
- return make_range(Iter, Iter);
- }
- SymbolStream &SS = SymbolS.get();
-
- return SS.getSymbols(HadError);
-}
-
-Expected<const codeview::CVSymbolArray &>
-PublicsStream::getSymbolArray() const {
- auto SymbolS = Pdb.getPDBSymbolStream();
- if (!SymbolS)
- return SymbolS.takeError();
-
- return SymbolS->getSymbolArray();
-}
-
-Error PublicsStream::commit() { return Error::success(); }
//===----------------------------------------------------------------------===//
#include "llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h"
-
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "GSI.h"
ALL: Type Index Offsets:
ALL-NEXT: TI: 0x1000, Offset: 0
ALL: Hash Adjusters:
+ALL: Global Symbols
+ALL-NEXT: ============================================================
+ALL-NEXT: 56 | S_PROCREF [size = 20] `main`
+ALL-NEXT: module = 1, sum name = 0, offset = 120
+ALL-NEXT: 76 | S_GDATA32 [size = 28] `__purecall`
+ALL-NEXT: type = 0x0403 (void*), addr = 0003:0000
+ALL-NOT: S_PUB32
ALL: Public Symbols
ALL-NEXT: ============================================================
ALL-NEXT: 0 | S_PUB32 [size = 36] `?__purecall@@3PAXA`
ALL-NEXT: flags = none, addr = 0003:0000
ALL-NEXT: 36 | S_PUB32 [size = 20] `_main`
ALL-NEXT: flags = function, addr = 0001:0016
-ALL-NEXT: 56 | S_PROCREF [size = 20] `main`
-ALL-NEXT: module = 1, sum name = 0, offset = 120
-ALL-NEXT: 76 | S_GDATA32 [size = 28] `__purecall`
-ALL-NEXT: type = 0x0403 (void*), addr = 0003:0000
+ALL-NOT: S_PROCREF
ALL: Symbols
ALL-NEXT: ============================================================
ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
return EC;
}
+ if (opts::dump::DumpGlobals) {
+ if (auto EC = dumpGlobals())
+ return EC;
+ }
+
if (opts::dump::DumpPublics) {
if (auto EC = dumpPublics())
return EC;
return Error::success();
}
+Error DumpOutputStyle::dumpGlobals() {
+ printHeader(P, "Global Symbols");
+ AutoIndent Indent(P);
+ if (!File.hasPDBGlobalsStream()) {
+ P.formatLine("Globals stream not present");
+ return Error::success();
+ }
+ ExitOnError Err("Error dumping globals stream");
+ auto &Globals = Err(File.getPDBGlobalsStream());
+
+ const GSIHashTable &Table = Globals.getGlobalsTable();
+ Err(dumpSymbolsFromGSI(Table, opts::dump::DumpGlobalExtras));
+ return Error::success();
+}
+
Error DumpOutputStyle::dumpPublics() {
printHeader(P, "Public Symbols");
-
AutoIndent Indent(P);
if (!File.hasPDBPublicsStream()) {
P.formatLine("Publics stream not present");
return Error::success();
}
-
ExitOnError Err("Error dumping publics stream");
-
- auto &Types = Err(initializeTypes(StreamTPI));
auto &Publics = Err(File.getPDBPublicsStream());
- SymbolVisitorCallbackPipeline Pipeline;
- SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
- MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, Types);
- Pipeline.addCallbackToPipeline(Deserializer);
- Pipeline.addCallbackToPipeline(Dumper);
- CVSymbolVisitor Visitor(Pipeline);
-
- auto ExpectedSymbols = Publics.getSymbolArray();
- if (!ExpectedSymbols) {
- P.formatLine("Could not read public symbol record stream");
- return Error::success();
- }
-
- if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols, 0))
- P.formatLine("Error while processing public symbol records. {0}",
- toString(std::move(EC)));
+ const GSIHashTable &PublicsTable = Publics.getPublicsTable();
+ Err(dumpSymbolsFromGSI(PublicsTable, opts::dump::DumpPublicExtras));
- // Return early if we aren't dumping public hash table and address map info.
+ // Skip the rest if we aren't dumping extras.
if (!opts::dump::DumpPublicExtras)
return Error::success();
- P.formatLine("Hash Records");
- {
- AutoIndent Indent2(P);
- for (const PSHashRecord &HR : Publics.getHashRecords())
- P.formatLine("off = {0}, refcnt = {1}", uint32_t(HR.Off),
- uint32_t(HR.CRef));
- }
-
- // FIXME: Dump the bitmap.
-
- P.formatLine("Hash Buckets");
- {
- AutoIndent Indent2(P);
- for (uint32_t Hash : Publics.getHashBuckets())
- P.formatLine("{0:x8}", Hash);
- }
-
P.formatLine("Address Map");
{
// These are offsets into the publics stream sorted by secidx:secrel.
return Error::success();
}
+Error DumpOutputStyle::dumpSymbolsFromGSI(const GSIHashTable &Table,
+ bool HashExtras) {
+ auto ExpectedSyms = File.getPDBSymbolStream();
+ if (!ExpectedSyms)
+ return ExpectedSyms.takeError();
+ auto ExpectedTypes = initializeTypes(StreamTPI);
+ if (!ExpectedTypes)
+ return ExpectedTypes.takeError();
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedTypes);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+
+ BinaryStreamRef SymStream =
+ ExpectedSyms->getSymbolArray().getUnderlyingStream();
+ for (uint32_t PubSymOff : Table) {
+ Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
+ if (!Sym)
+ return Sym.takeError();
+ if (auto E = Visitor.visitSymbolRecord(*Sym, PubSymOff))
+ return E;
+ }
+
+ // Return early if we aren't dumping public hash table and address map info.
+ if (!HashExtras)
+ return Error::success();
+
+ P.formatLine("Hash Records");
+ {
+ AutoIndent Indent2(P);
+ for (const PSHashRecord &HR : Table.HashRecords)
+ P.formatLine("off = {0}, refcnt = {1}", uint32_t(HR.Off),
+ uint32_t(HR.CRef));
+ }
+
+ // FIXME: Dump the bitmap.
+
+ P.formatLine("Hash Buckets");
+ {
+ AutoIndent Indent2(P);
+ for (uint32_t Hash : Table.HashBuckets)
+ P.formatLine("{0:x8}", Hash);
+ }
+
+ return Error::success();
+}
+
static std::string formatSectionCharacteristics(uint32_t IndentLevel,
uint32_t C) {
using SC = COFF::SectionCharacteristics;
}
namespace pdb {
+class GSIHashTable;
+
class DumpOutputStyle : public OutputStyle {
public:
DumpOutputStyle(PDBFile &File);
Error dumpModules();
Error dumpModuleFiles();
Error dumpModuleSyms();
+ Error dumpGlobals();
Error dumpPublics();
+ Error dumpSymbolsFromGSI(const GSIHashTable &Table, bool HashExtras);
Error dumpSectionContribs();
Error dumpSectionMap();
cl::cat(TypeOptions), cl::sub(DumpSubcommand));
// SYMBOL OPTIONS
+cl::opt<bool> DumpGlobals("globals", cl::desc("dump Globals symbol records"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpGlobalExtras("global-extras", cl::desc("dump Globals hashes"),
+ cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
cl::cat(SymbolOptions), cl::sub(DumpSubcommand));
cl::opt<bool> DumpPublicExtras("public-extras",
opts::dump::DumpXme = true;
opts::dump::DumpXmi = true;
opts::dump::DumpIds = true;
+ opts::dump::DumpGlobals = true;
opts::dump::DumpPublics = true;
opts::dump::DumpSectionContribs = true;
opts::dump::DumpSectionMap = true;
extern llvm::cl::list<uint32_t> DumpIdIndex;
extern llvm::cl::opt<bool> DumpSymbols;
extern llvm::cl::opt<bool> DumpSymRecordBytes;
+extern llvm::cl::opt<bool> DumpGlobals;
+extern llvm::cl::opt<bool> DumpGlobalExtras;
extern llvm::cl::opt<bool> DumpPublics;
extern llvm::cl::opt<bool> DumpPublicExtras;
extern llvm::cl::opt<bool> DumpSectionContribs;