mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
pdbdump: Print "Publics" stream.
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
This commit is contained in:
parent
fe65f9093f
commit
497f2c0f25
@ -33,6 +33,7 @@ public:
|
||||
|
||||
PdbRaw_DbiVer getDbiVersion() const;
|
||||
uint32_t getAge() const;
|
||||
uint16_t getPublicSymbolStreamIndex() const;
|
||||
|
||||
bool isIncrementallyLinked() const;
|
||||
bool hasCTypes() const;
|
||||
|
@ -24,6 +24,7 @@ namespace pdb {
|
||||
struct PDBFileContext;
|
||||
class DbiStream;
|
||||
class InfoStream;
|
||||
class PublicsStream;
|
||||
class TpiStream;
|
||||
|
||||
class PDBFile {
|
||||
@ -62,12 +63,14 @@ public:
|
||||
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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
51
include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
Normal file
51
include/llvm/DebugInfo/PDB/Raw/PublicsStream.h
Normal file
@ -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
|
@ -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
|
||||
|
@ -55,7 +55,7 @@ struct DbiStream::HeaderInfo {
|
||||
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 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
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
@ -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
lib/DebugInfo/PDB/Raw/PublicsStream.cpp
Normal file
132
lib/DebugInfo/PDB/Raw/PublicsStream.cpp
Normal file
@ -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();
|
||||
}
|
@ -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
|
||||
|
||||
@ -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
|
||||
|
@ -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"
|
||||
@ -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",
|
||||
@ -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());
|
||||
@ -421,6 +441,9 @@ static Error dumpStructure(RawSession &RS) {
|
||||
|
||||
if (auto EC = dumpTpiStream(P, File))
|
||||
return EC;
|
||||
|
||||
if (auto EC = dumpPublicsStream(P, File))
|
||||
return EC;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user