1 //===- PDBStringTable.cpp - PDB String Table ---------------------*- 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 #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" 11 12 #include "llvm/ADT/ArrayRef.h" 13 #include "llvm/DebugInfo/MSF/MappedBlockStream.h" 14 #include "llvm/DebugInfo/PDB/Native/Hash.h" 15 #include "llvm/DebugInfo/PDB/Native/RawError.h" 16 #include "llvm/DebugInfo/PDB/Native/RawTypes.h" 17 #include "llvm/Support/BinaryStreamReader.h" 18 #include "llvm/Support/Endian.h" 19 20 using namespace llvm; 21 using namespace llvm::support; 22 using namespace llvm::pdb; 23 24 uint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; } 25 uint32_t PDBStringTable::getNameCount() const { return NameCount; } 26 uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; } 27 uint32_t PDBStringTable::getSignature() const { return Header->Signature; } 28 29 Error PDBStringTable::readHeader(BinaryStreamReader &Reader) { 30 if (auto EC = Reader.readObject(Header)) 31 return EC; 32 33 if (Header->Signature != PDBStringTableSignature) 34 return make_error<RawError>(raw_error_code::corrupt_file, 35 "Invalid hash table signature"); 36 if (Header->HashVersion != 1 && Header->HashVersion != 2) 37 return make_error<RawError>(raw_error_code::corrupt_file, 38 "Unsupported hash version"); 39 40 assert(Reader.bytesRemaining() == 0); 41 return Error::success(); 42 } 43 44 Error PDBStringTable::readStrings(BinaryStreamReader &Reader) { 45 BinaryStreamRef Stream; 46 if (auto EC = Reader.readStreamRef(Stream)) 47 return EC; 48 49 if (auto EC = Strings.initialize(Stream)) { 50 return joinErrors(std::move(EC), 51 make_error<RawError>(raw_error_code::corrupt_file, 52 "Invalid hash table byte length")); 53 } 54 55 assert(Reader.bytesRemaining() == 0); 56 return Error::success(); 57 } 58 59 const codeview::DebugStringTableSubsectionRef & 60 PDBStringTable::getStringTable() const { 61 return Strings; 62 } 63 64 Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) { 65 const support::ulittle32_t *HashCount; 66 if (auto EC = Reader.readObject(HashCount)) 67 return EC; 68 69 if (auto EC = Reader.readArray(IDs, *HashCount)) { 70 return joinErrors(std::move(EC), 71 make_error<RawError>(raw_error_code::corrupt_file, 72 "Could not read bucket array")); 73 } 74 75 return Error::success(); 76 } 77 78 Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) { 79 if (auto EC = Reader.readInteger(NameCount)) 80 return EC; 81 82 assert(Reader.bytesRemaining() == 0); 83 return Error::success(); 84 } 85 86 Error PDBStringTable::reload(BinaryStreamReader &Reader) { 87 88 BinaryStreamReader SectionReader; 89 90 std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader)); 91 if (auto EC = readHeader(SectionReader)) 92 return EC; 93 94 std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize); 95 if (auto EC = readStrings(SectionReader)) 96 return EC; 97 98 // We don't know how long the hash table is until we parse it, so let the 99 // function responsible for doing that figure it out. 100 if (auto EC = readHashTable(Reader)) 101 return EC; 102 103 std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t)); 104 if (auto EC = readEpilogue(SectionReader)) 105 return EC; 106 107 assert(Reader.bytesRemaining() == 0); 108 return Error::success(); 109 } 110 111 Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const { 112 return Strings.getString(ID); 113 } 114 115 Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const { 116 uint32_t Hash = 117 (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); 118 size_t Count = IDs.size(); 119 uint32_t Start = Hash % Count; 120 for (size_t I = 0; I < Count; ++I) { 121 // The hash is just a starting point for the search, but if it 122 // doesn't work we should find the string no matter what, because 123 // we iterate the entire array. 124 uint32_t Index = (Start + I) % Count; 125 126 uint32_t ID = IDs[Index]; 127 auto ExpectedStr = getStringForID(ID); 128 if (!ExpectedStr) 129 return ExpectedStr.takeError(); 130 131 if (*ExpectedStr == Str) 132 return ID; 133 } 134 return make_error<RawError>(raw_error_code::no_entry); 135 } 136 137 FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const { 138 return IDs; 139 } 140