diff options
author | Rui Ueyama <ruiu@google.com> | 2016-05-13 21:21:53 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2016-05-13 21:21:53 +0000 |
commit | 1f6b6e2c539fbf3f85f02761707fc916673eea35 (patch) | |
tree | 70c2110c04890bfcd957dadde64f8c86185e3aea /llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp | |
parent | 8d83fb6132a9851ffe16d1caf4df02eaf1c6a0e0 (diff) | |
download | llvm-1f6b6e2c539fbf3f85f02761707fc916673eea35.zip llvm-1f6b6e2c539fbf3f85f02761707fc916673eea35.tar.gz llvm-1f6b6e2c539fbf3f85f02761707fc916673eea35.tar.bz2 |
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
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/PublicsStream.cpp new file mode 100644 index 0000000..dbdb1c5 --- /dev/null +++ b/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(); +} |