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 28 using namespace llvm; 29 using namespace llvm::msf; 30 using namespace llvm::pdb; 31 32 GlobalsStream::GlobalsStream(std::unique_ptr<MappedBlockStream> Stream) 33 : Stream(std::move(Stream)) {} 34 35 GlobalsStream::~GlobalsStream() = default; 36 37 Error GlobalsStream::reload() { 38 BinaryStreamReader Reader(*Stream); 39 if (auto E = GlobalsTable.read(Reader)) 40 return E; 41 return Error::success(); 42 } 43 44 static 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 53 static 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 67 static 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 87 static Error 88 readGSIHashBuckets(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 115 Error 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