GlobalsStream.cpp revision 327952
1//===- GlobalsStream.cpp - PDB Index of Symbols by Name ---------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// The on-disk structores used in this file are based on the reference 11// implementation which is available at 12// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h 13// 14// When you are reading the reference source code, you'd find the 15// information below useful. 16// 17// - ppdb1->m_fMinimalDbgInfo seems to be always true. 18// - SMALLBUCKETS macro is defined. 19// 20//===----------------------------------------------------------------------===// 21 22#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 23#include "llvm/DebugInfo/PDB/Native/RawError.h" 24#include "llvm/Support/BinaryStreamReader.h" 25#include "llvm/Support/Error.h" 26#include <algorithm> 27 28using namespace llvm; 29using namespace llvm::msf; 30using namespace llvm::pdb; 31 32GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream) 33 : Stream(std::move(Stream)) {} 34 35GlobalsStream::~GlobalsStream() = default; 36 37Error GlobalsStream::reload() { 38 BinaryStreamReader Reader(*Stream); 39 if (auto E = GlobalsTable.read(Reader)) 40 return E; 41 return Error::success(); 42} 43 44static Error checkHashHdrVersion(const GSIHashHeader *HashHdr) { 45 if (HashHdr->VerHdr != GSIHashHeader::HdrVersion) 46 return make_error<RawError>( 47 raw_error_code::feature_unsupported, 48 "Encountered unsupported globals stream version."); 49 50 return Error::success(); 51} 52 53static Error readGSIHashHeader(const GSIHashHeader *&HashHdr, 54 BinaryStreamReader &Reader) { 55 if (Reader.readObject(HashHdr)) 56 return make_error<RawError>(raw_error_code::corrupt_file, 57 "Stream does not contain a GSIHashHeader."); 58 59 if (HashHdr->VerSignature != GSIHashHeader::HdrSignature) 60 return make_error<RawError>( 61 raw_error_code::feature_unsupported, 62 "GSIHashHeader signature (0xffffffff) not found."); 63 64 return Error::success(); 65} 66 67static Error readGSIHashRecords(FixedStreamArray<PSHashRecord> &HashRecords, 68 const GSIHashHeader *HashHdr, 69 BinaryStreamReader &Reader) { 70 if (auto EC = checkHashHdrVersion(HashHdr)) 71 return EC; 72 73 // HashHdr->HrSize specifies the number of bytes of PSHashRecords we have. 74 // Verify that we can read them all. 75 if (HashHdr->HrSize % sizeof(PSHashRecord)) 76 return make_error<RawError>(raw_error_code::corrupt_file, 77 "Invalid HR array size."); 78 uint32_t NumHashRecords = HashHdr->HrSize / sizeof(PSHashRecord); 79 if (auto EC = Reader.readArray(HashRecords, NumHashRecords)) 80 return joinErrors(std::move(EC), 81 make_error<RawError>(raw_error_code::corrupt_file, 82 "Error reading hash records.")); 83 84 return Error::success(); 85} 86 87static Error 88readGSIHashBuckets(FixedStreamArray<support::ulittle32_t> &HashBuckets, 89 ArrayRef<uint8_t> &HashBitmap, const GSIHashHeader *HashHdr, 90 BinaryStreamReader &Reader) { 91 if (auto EC = checkHashHdrVersion(HashHdr)) 92 return EC; 93 94 // Before the actual hash buckets, there is a bitmap of length determined by 95 // IPHR_HASH. 96 size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); 97 uint32_t NumBitmapEntries = BitmapSizeInBits / 8; 98 if (auto EC = Reader.readBytes(HashBitmap, NumBitmapEntries)) 99 return joinErrors(std::move(EC), 100 make_error<RawError>(raw_error_code::corrupt_file, 101 "Could not read a bitmap.")); 102 uint32_t NumBuckets = 0; 103 for (uint8_t B : HashBitmap) 104 NumBuckets += countPopulation(B); 105 106 // Hash buckets follow. 107 if (auto EC = Reader.readArray(HashBuckets, NumBuckets)) 108 return joinErrors(std::move(EC), 109 make_error<RawError>(raw_error_code::corrupt_file, 110 "Hash buckets corrupted.")); 111 112 return Error::success(); 113} 114 115Error GSIHashTable::read(BinaryStreamReader &Reader) { 116 if (auto EC = readGSIHashHeader(HashHdr, Reader)) 117 return EC; 118 if (auto EC = readGSIHashRecords(HashRecords, HashHdr, Reader)) 119 return EC; 120 if (HashHdr->HrSize > 0) 121 if (auto EC = readGSIHashBuckets(HashBuckets, HashBitmap, HashHdr, Reader)) 122 return EC; 123 return Error::success(); 124} 125