1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===- PublicsStream.cpp - PDB Public Symbol Stream -----------------------===// 2de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The LLVM Compiler Infrastructure 4de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 5de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// License. See LICENSE.TXT for details. 7de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 8de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===// 9de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The data structures defined in this file are based on the reference 11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// implementation which is available at 12de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h 13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// When you are reading the reference source code, you'd find the 15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// information below useful. 16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 17de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// - ppdb1->m_fMinimalDbgInfo seems to be always true. 18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// - SMALLBUCKETS macro is defined. 19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 20de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The reference doesn't compile, so I learned just by reading code. 21de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// It's not guaranteed to be correct. 22de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===// 24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/PDB/Raw/PublicsStream.h" 26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/CodeView/CodeView.h" 28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/CodeView/StreamReader.h" 29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/CodeView/TypeRecord.h" 30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/PDB/Raw/IndexedStreamData.h" 31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" 32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/PDB/Raw/PDBFile.h" 33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/PDB/Raw/RawConstants.h" 34de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/PDB/Raw/RawError.h" 35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/DebugInfo/PDB/Raw/SymbolStream.h" 36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/ADT/BitVector.h" 38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/Endian.h" 39de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/Format.h" 40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/Support/MathExtras.h" 41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace llvm; 43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace llvm::support; 44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing namespace llvm::pdb; 45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic const unsigned IPHR_HASH = 4096; 48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This is PSGSIHDR struct defined in 50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h 51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstruct PublicsStream::HeaderInfo { 52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t SymHash; 53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t AddrMap; 54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t NumThunks; 55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t SizeOfThunk; 56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle16_t ISectThunkTable; 57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar char Padding[2]; 58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t OffThunkTable; 59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t NumSections; 60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}; 61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This is GSIHashHdr. 63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstruct PublicsStream::GSIHashHeader { 64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar enum : unsigned { 65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar HdrSignature = ~0U, 66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar HdrVersion = 0xeffe0000 + 19990810, 67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar }; 68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t VerSignature; 69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t VerHdr; 70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t HrSize; 71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ulittle32_t NumBuckets; 72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}; 73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarPublicsStream::PublicsStream(PDBFile &File, 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar std::unique_ptr<MappedBlockStream> Stream) 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar : Pdb(File), Stream(std::move(Stream)) {} 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarPublicsStream::~PublicsStream() {} 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainaruint32_t PublicsStream::getSymHash() const { return Header->SymHash; } 81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainaruint32_t PublicsStream::getAddrMap() const { return Header->AddrMap; } 82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Publics stream contains fixed-size headers and a serialized hash table. 84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This implementation is not complete yet. It reads till the end of the 85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// stream so that we verify the stream is at least not corrupted. However, 86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// we skip over the hash table which we believe contains information about 87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// public symbols. 88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarError PublicsStream::reload() { 89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar codeview::StreamReader Reader(*Stream); 90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Check stream size. 92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reader.bytesRemaining() < sizeof(HeaderInfo) + sizeof(GSIHashHeader)) 93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return make_error<RawError>(raw_error_code::corrupt_file, 94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Publics Stream does not contain a header."); 95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Read PSGSIHDR and GSIHashHdr structs. 97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reader.readObject(Header)) 98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return make_error<RawError>(raw_error_code::corrupt_file, 99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Publics Stream does not contain a header."); 100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reader.readObject(HashHdr)) 102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return make_error<RawError>(raw_error_code::corrupt_file, 103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Publics Stream does not contain a header."); 104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // An array of HashRecord follows. Read them. 106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (HashHdr->HrSize % sizeof(PSHashRecord)) 107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return make_error<RawError>(raw_error_code::corrupt_file, 108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Invalid HR array size."); 109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord); 110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = Reader.readArray(HashRecords, NumHashRecords)) 111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return joinErrors(std::move(EC), 112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar make_error<RawError>(raw_error_code::corrupt_file, 113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Could not read an HR array")); 114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // A bitmap of a fixed length follows. 116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); 117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t NumBitmapEntries = BitmapSizeInBits / 8; 118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = Reader.readBytes(Bitmap, NumBitmapEntries)) 119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return joinErrors(std::move(EC), 120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar make_error<RawError>(raw_error_code::corrupt_file, 121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Could not read a bitmap.")); 122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (uint8_t B : Bitmap) 123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar NumBuckets += countPopulation(B); 124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // We don't yet understand the following data structures completely, 126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // but we at least know the types and sizes. Here we are trying 127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // to read the stream till end so that we at least can detect 128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // corrupted streams. 129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Hash buckets follow. 131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = Reader.readArray(HashBuckets, NumBuckets)) 132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return joinErrors(std::move(EC), 133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar make_error<RawError>(raw_error_code::corrupt_file, 134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Hash buckets corrupted.")); 135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Something called "address map" follows. 137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t NumAddressMapEntries = Header->AddrMap / sizeof(uint32_t); 138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = Reader.readArray(AddressMap, NumAddressMapEntries)) 139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return joinErrors(std::move(EC), 140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar make_error<RawError>(raw_error_code::corrupt_file, 141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Could not read an address map.")); 142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Something called "thunk map" follows. 144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = Reader.readArray(ThunkMap, Header->NumThunks)) 145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return joinErrors(std::move(EC), 146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar make_error<RawError>(raw_error_code::corrupt_file, 147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Could not read a thunk map.")); 148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Something called "section map" follows. 150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (auto EC = Reader.readArray(SectionOffsets, Header->NumSections)) 151de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return joinErrors(std::move(EC), 152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar make_error<RawError>(raw_error_code::corrupt_file, 153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Could not read a section map.")); 154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 155de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (Reader.bytesRemaining() > 0) 156de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return make_error<RawError>(raw_error_code::corrupt_file, 157de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Corrupted publics stream."); 158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return Error::success(); 159de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 160de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 161de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainariterator_range<codeview::CVSymbolArray::Iterator> 162de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarPublicsStream::getSymbols(bool *HadError) const { 163de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar auto SymbolS = Pdb.getPDBSymbolStream(); 164de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (SymbolS.takeError()) { 165de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar codeview::CVSymbolArray::Iterator Iter; 166de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return llvm::make_range(Iter, Iter); 167de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 168de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SymbolStream &SS = SymbolS.get(); 169de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 170de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return SS.getSymbols(HadError); 171de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 172de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 173de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarError PublicsStream::commit() { return Error::success(); } 174