Skip to content

Commit

Permalink
pdbdump: Print "Publics" stream.
Browse files Browse the repository at this point in the history
Publics stream seems to contain information as to public symbols.
It actually contains a serialized hash table along with fixed-sized
headers. This patch is not complete. It scans only till the end of
the stream and dump the header information. I'll write code to
de-serialize the hash table later.

Reviewers: zturner

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D20256

llvm-svn: 269484
  • Loading branch information
rui314 committed May 13, 2016
1 parent 8d83fb6 commit 1f6b6e2
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 14 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h
Expand Up @@ -33,6 +33,7 @@ class DbiStream {

PdbRaw_DbiVer getDbiVersion() const;
uint32_t getAge() const;
uint16_t getPublicSymbolStreamIndex() const;

bool isIncrementallyLinked() const;
bool hasCTypes() const;
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/DebugInfo/PDB/Raw/PDBFile.h
Expand Up @@ -24,6 +24,7 @@ namespace pdb {
struct PDBFileContext;
class DbiStream;
class InfoStream;
class PublicsStream;
class TpiStream;

class PDBFile {
Expand Down Expand Up @@ -62,12 +63,14 @@ class PDBFile {
Expected<InfoStream &> getPDBInfoStream();
Expected<DbiStream &> getPDBDbiStream();
Expected<TpiStream &> getPDBTpiStream();
Expected<PublicsStream &> getPDBPublicsStream();

private:
std::unique_ptr<PDBFileContext> Context;
std::unique_ptr<InfoStream> Info;
std::unique_ptr<DbiStream> Dbi;
std::unique_ptr<TpiStream> Tpi;
std::unique_ptr<PublicsStream> Publics;
};
}
}
Expand Down
51 changes: 51 additions & 0 deletions llvm/include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
@@ -0,0 +1,51 @@
//===- PublicsStream.h - PDB Public Symbol Stream -------- ------*- 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_PUBLICSSTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PUBLICSSTREAM_H

#include "llvm/DebugInfo/CodeView/TypeStream.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/DebugInfo/PDB/Raw/ByteStream.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"

#include "llvm/Support/Error.h"

namespace llvm {
namespace pdb {
class PDBFile;

class PublicsStream {
struct HeaderInfo;
struct GSIHashHeader;
struct HRFile;

public:
PublicsStream(PDBFile &File, uint32_t StreamNum);
~PublicsStream();
Error reload();

uint32_t getStreamNum() const { return StreamNum; }
uint32_t getSymHash() const;
uint32_t getAddrMap() const;
uint32_t getNumBuckets() const { return NumBuckets; }

private:
uint32_t StreamNum;
MappedBlockStream Stream;
uint32_t NumBuckets = 0;

std::unique_ptr<HeaderInfo> Header;
std::unique_ptr<GSIHashHeader> HashHdr;
};
}
}

#endif
1 change: 1 addition & 0 deletions llvm/lib/DebugInfo/PDB/CMakeLists.txt
Expand Up @@ -37,6 +37,7 @@ add_pdb_impl_folder(Raw
Raw/NameHashTable.cpp
Raw/NameMap.cpp
Raw/PDBFile.cpp
Raw/PublicsStream.cpp
Raw/RawError.cpp
Raw/RawSession.cpp
Raw/StreamReader.cpp
Expand Down
26 changes: 15 additions & 11 deletions llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp
Expand Up @@ -52,17 +52,17 @@ const uint16_t BuildMajorShift = 8;
struct DbiStream::HeaderInfo {
little32_t VersionSignature;
ulittle32_t VersionHeader;
ulittle32_t Age; // Should match InfoStream.
ulittle16_t GSSyms; // Number of global symbols
ulittle16_t BuildNumber; // See DbiBuildNo structure.
ulittle16_t PSSyms; // Number of public symbols
ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
ulittle16_t SymRecords; // Number of symbols
ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
little32_t ModiSubstreamSize; // Size of module info stream
little32_t SecContrSubstreamSize; // Size of sec. contribution stream
little32_t SectionMapSize; // Size of sec. map substream
little32_t FileInfoSize; // Size of file info substream
ulittle32_t Age; // Should match InfoStream.
ulittle16_t GSSyms; // Number of global symbols
ulittle16_t BuildNumber; // See DbiBuildNo structure.
ulittle16_t PublicSymbolStreamIndex; // Number of public symbols
ulittle16_t PdbDllVersion; // version of mspdbNNN.dll
ulittle16_t SymRecords; // Number of symbols
ulittle16_t PdbDllRbld; // rbld number of mspdbNNN.dll
little32_t ModiSubstreamSize; // Size of module info stream
little32_t SecContrSubstreamSize; // Size of sec. contribution stream
little32_t SectionMapSize; // Size of sec. map substream
little32_t FileInfoSize; // Size of file info substream
little32_t TypeServerSize; // Size of type server map
ulittle32_t MFCTypeServerIndex; // Index of MFC Type Server
little32_t OptionalDbgHdrSize; // Size of DbgHeader info
Expand Down Expand Up @@ -184,6 +184,10 @@ PdbRaw_DbiVer DbiStream::getDbiVersion() const {

uint32_t DbiStream::getAge() const { return Header->Age; }

uint16_t DbiStream::getPublicSymbolStreamIndex() const {
return Header->PublicSymbolStreamIndex;
}

bool DbiStream::isIncrementallyLinked() const {
return (Header->Flags & FlagIncrementalMask) != 0;
}
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/DebugInfo/PDB/Raw/PDBFile.cpp
Expand Up @@ -11,6 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/DebugInfo/PDB/Raw/DbiStream.h"
#include "llvm/DebugInfo/PDB/Raw/InfoStream.h"
#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
#include "llvm/Support/Endian.h"
Expand Down Expand Up @@ -292,3 +293,17 @@ Expected<TpiStream &> PDBFile::getPDBTpiStream() {
}
return *Tpi;
}

Expected<PublicsStream &> PDBFile::getPDBPublicsStream() {
if (!Publics) {
auto DbiS = getPDBDbiStream();
if (auto EC = DbiS.takeError())
return std::move(EC);
uint32_t PublicsStreamNum = DbiS->getPublicSymbolStreamIndex();

Publics.reset(new PublicsStream(*this, PublicsStreamNum));
if (auto EC = Publics->reload())
return std::move(EC);
}
return *Publics;
}
132 changes: 132 additions & 0 deletions llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp
@@ -0,0 +1,132 @@
//===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// The data structures defined 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.
//
// The reference doesn't compile, so I learned just by reading code.
// It's not guaranteed to be correct.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"

#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawConstants.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/StreamReader.h"

#include "llvm/ADT/BitVector.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"

using namespace llvm;
using namespace llvm::support;
using namespace llvm::pdb;


static const unsigned IPHR_HASH = 4096;

// This is PSGSIHDR struct defined in
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct PublicsStream::HeaderInfo {
ulittle32_t SymHash;
ulittle32_t AddrMap;
ulittle32_t NumThunks;
ulittle32_t SizeOfThunk;
ulittle16_t ISectThunkTable;
char Padding[2];
ulittle32_t OffThunkTable;
ulittle32_t NumSects;
};


// This is GSIHashHdr struct defined in
struct PublicsStream::GSIHashHeader {
enum {
HdrSignature = -1,
HdrVersion = 0xeffe0000 + 19990810,
};
ulittle32_t VerSignature;
ulittle32_t VerHdr;
ulittle32_t HrSize;
ulittle32_t NumBuckets;
};

struct PublicsStream::HRFile {
ulittle32_t Off;
ulittle32_t CRef;
};

PublicsStream::PublicsStream(PDBFile &File, uint32_t StreamNum)
: StreamNum(StreamNum), Stream(StreamNum, File) {}

PublicsStream::~PublicsStream() {}

uint32_t PublicsStream::getSymHash() const { return Header->SymHash; }
uint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; }

// Publics stream contains fixed-size headers and a serialized hash table.
// This implementation is not complete yet. It reads till the end of the
// stream so that we verify the stream is at least not corrupted. However,
// we skip over the hash table which we believe contains information about
// public symbols.
Error PublicsStream::reload() {
StreamReader Reader(Stream);

// Check stream size.
if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");

// Read PSGSIHDR and GSIHashHdr structs.
Header.reset(new HeaderInfo());
if (Reader.readObject(Header.get()))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");
HashHdr.reset(new GSIHashHeader());
if (Reader.readObject(HashHdr.get()))
return make_error<RawError>(raw_error_code::corrupt_file,
"Publics Stream does not contain a header.");

// An array of HRFile follows. Read them.
if (HashHdr->HrSize % sizeof(HRFile))
return make_error<RawError>(raw_error_code::corrupt_file,
"Invalid HR array size.");
std::vector<HRFile> HRs(HashHdr->HrSize / sizeof(HRFile));
if (auto EC = Reader.readArray<HRFile>(HRs))
return make_error<RawError>(raw_error_code::corrupt_file,
"Could not read an HR array");

// A bitmap of a fixed length follows.
size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32);
std::vector<uint8_t> Bitmap(BitmapSizeInBits / 8);
if (auto EC = Reader.readArray<uint8_t>(Bitmap))
return make_error<RawError>(raw_error_code::corrupt_file,
"Could not read a bitmap.");
for (uint8_t B : Bitmap)
NumBuckets += countPopulation(B);

// Buckets follow.
if (Reader.bytesRemaining() < NumBuckets * sizeof(uint32_t))
return make_error<RawError>(raw_error_code::corrupt_file,
"Hash buckets corrupted.");

return Error::success();
}
9 changes: 8 additions & 1 deletion llvm/test/DebugInfo/PDB/pdbdump-headers.test
@@ -1,5 +1,5 @@
; RUN: llvm-pdbdump --dump-headers -dump-tpi-records -dump-tpi-record-bytes -dump-module-syms \
; RUN: %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
; RUN: --dump-publics %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
; RUN: llvm-pdbdump --dump-headers %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
; RUN: llvm-pdbdump --dump-headers %p/Inputs/bad-block-size.pdb | FileCheck -check-prefix=BAD-BLOCK-SIZE %s

Expand Down Expand Up @@ -308,6 +308,13 @@
; EMPTY-NEXT: )
; EMPTY-NEXT: }

; EMPTY: Publics Stream {
; EMPTY-NEXT: Stream number: 7
; EMPTY-NEXT: SymHash: 556
; EMPTY-NEXT: AddrMap: 8
; EMPTY-NEXT: Number of buckets: 2
; EMPTY-NEXT: }

; BIG: FileHeaders {
; BIG-NEXT: BlockSize: 4096
; BIG-NEXT: Unknown0: 2
Expand Down
25 changes: 24 additions & 1 deletion llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
Expand Up @@ -44,6 +44,7 @@
#include "llvm/DebugInfo/PDB/Raw/ModStream.h"
#include "llvm/DebugInfo/PDB/Raw/NameHashTable.h"
#include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h"
#include "llvm/DebugInfo/PDB/Raw/RawError.h"
#include "llvm/DebugInfo/PDB/Raw/RawSession.h"
#include "llvm/DebugInfo/PDB/Raw/StreamReader.h"
Expand Down Expand Up @@ -122,6 +123,9 @@ cl::opt<std::string> DumpStreamData("dump-stream", cl::desc("dump stream data"),
cl::opt<bool> DumpModuleSyms("dump-module-syms",
cl::desc("dump module symbols"),
cl::cat(NativeOtions));
cl::opt<bool> DumpPublics("dump-publics",
cl::desc("dump Publics stream data"),
cl::cat(NativeOtions));

cl::list<std::string>
ExcludeTypes("exclude-types",
Expand Down Expand Up @@ -394,6 +398,22 @@ static Error dumpTpiStream(ScopedPrinter &P, PDBFile &File) {
return Error::success();
}

static Error dumpPublicsStream(ScopedPrinter &P, PDBFile &File) {
if (!opts::DumpPublics)
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());
P.printNumber("SymHash", Publics.getSymHash());
P.printNumber("AddrMap", Publics.getAddrMap());
P.printNumber("Number of buckets", Publics.getNumBuckets());
return Error::success();
}

static Error dumpStructure(RawSession &RS) {
PDBFile &File = RS.getPDBFile();
ScopedPrinter P(outs());
Expand Down Expand Up @@ -421,7 +441,10 @@ static Error dumpStructure(RawSession &RS) {

if (auto EC = dumpTpiStream(P, File))
return EC;
return Error::success();

if (auto EC = dumpPublicsStream(P, File))
return EC;
return Error::success();
}

static void dumpInput(StringRef Path) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/tools/llvm-pdbdump/llvm-pdbdump.h
Expand Up @@ -32,4 +32,4 @@ extern llvm::cl::list<std::string> IncludeSymbols;
extern llvm::cl::list<std::string> IncludeCompilands;
}

#endif
#endif

0 comments on commit 1f6b6e2

Please sign in to comment.