PDBStringTable.cpp revision 341825
1217309Snwhitehorn//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===// 2251843Sbapt// 3217309Snwhitehorn// The LLVM Compiler Infrastructure 4251843Sbapt// 5217309Snwhitehorn// This file is distributed under the University of Illinois Open Source 6217309Snwhitehorn// License. See LICENSE.TXT for details. 7217309Snwhitehorn// 8217309Snwhitehorn//===----------------------------------------------------------------------===// 9217309Snwhitehorn 10217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" 11217309Snwhitehorn 12217309Snwhitehorn#include "llvm/ADT/ArrayRef.h" 13217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/Hash.h" 14217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/RawError.h" 15217309Snwhitehorn#include "llvm/DebugInfo/PDB/Native/RawTypes.h" 16217309Snwhitehorn#include "llvm/Support/BinaryStreamReader.h" 17217309Snwhitehorn#include "llvm/Support/Endian.h" 18217309Snwhitehorn 19217309Snwhitehornusing namespace llvm; 20217309Snwhitehornusing namespace llvm::support; 21217309Snwhitehornusing namespace llvm::pdb; 22217309Snwhitehorn 23217309Snwhitehornuint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; } 24217309Snwhitehornuint32_t PDBStringTable::getNameCount() const { return NameCount; } 25217309Snwhitehornuint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; } 26217309Snwhitehornuint32_t PDBStringTable::getSignature() const { return Header->Signature; } 27217309Snwhitehorn 28217309SnwhitehornError PDBStringTable::readHeader(BinaryStreamReader &Reader) { 29217309Snwhitehorn if (auto EC = Reader.readObject(Header)) 30217309Snwhitehorn return EC; 31217309Snwhitehorn 32217309Snwhitehorn if (Header->Signature != PDBStringTableSignature) 33251843Sbapt return make_error<RawError>(raw_error_code::corrupt_file, 34217309Snwhitehorn "Invalid hash table signature"); 35217309Snwhitehorn if (Header->HashVersion != 1 && Header->HashVersion != 2) 36217309Snwhitehorn return make_error<RawError>(raw_error_code::corrupt_file, 37217309Snwhitehorn "Unsupported hash version"); 38217309Snwhitehorn 39217309Snwhitehorn assert(Reader.bytesRemaining() == 0); 40220749Snwhitehorn return Error::success(); 41217309Snwhitehorn} 42217309Snwhitehorn 43217309SnwhitehornError PDBStringTable::readStrings(BinaryStreamReader &Reader) { 44217309Snwhitehorn BinaryStreamRef Stream; 45217309Snwhitehorn if (auto EC = Reader.readStreamRef(Stream)) 46217309Snwhitehorn return EC; 47217309Snwhitehorn 48217309Snwhitehorn if (auto EC = Strings.initialize(Stream)) { 49217309Snwhitehorn return joinErrors(std::move(EC), 50217309Snwhitehorn make_error<RawError>(raw_error_code::corrupt_file, 51217309Snwhitehorn "Invalid hash table byte length")); 52217309Snwhitehorn } 53217309Snwhitehorn 54217309Snwhitehorn assert(Reader.bytesRemaining() == 0); 55217309Snwhitehorn return Error::success(); 56217309Snwhitehorn} 57217309Snwhitehorn 58217309Snwhitehornconst codeview::DebugStringTableSubsectionRef & 59217309SnwhitehornPDBStringTable::getStringTable() const { 60217309Snwhitehorn return Strings; 61217309Snwhitehorn} 62217309Snwhitehorn 63217309SnwhitehornError PDBStringTable::readHashTable(BinaryStreamReader &Reader) { 64217309Snwhitehorn const support::ulittle32_t *HashCount; 65217309Snwhitehorn if (auto EC = Reader.readObject(HashCount)) 66217309Snwhitehorn return EC; 67217309Snwhitehorn 68217309Snwhitehorn if (auto EC = Reader.readArray(IDs, *HashCount)) { 69217309Snwhitehorn return joinErrors(std::move(EC), 70217309Snwhitehorn make_error<RawError>(raw_error_code::corrupt_file, 71217309Snwhitehorn "Could not read bucket array")); 72217309Snwhitehorn } 73217309Snwhitehorn 74217309Snwhitehorn return Error::success(); 75217309Snwhitehorn} 76217309Snwhitehorn 77217309SnwhitehornError PDBStringTable::readEpilogue(BinaryStreamReader &Reader) { 78217309Snwhitehorn if (auto EC = Reader.readInteger(NameCount)) 79217309Snwhitehorn return EC; 80217309Snwhitehorn 81217309Snwhitehorn assert(Reader.bytesRemaining() == 0); 82217309Snwhitehorn return Error::success(); 83217309Snwhitehorn} 84217309Snwhitehorn 85217309SnwhitehornError PDBStringTable::reload(BinaryStreamReader &Reader) { 86217309Snwhitehorn 87217309Snwhitehorn BinaryStreamReader SectionReader; 88217309Snwhitehorn 89217309Snwhitehorn std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader)); 90217309Snwhitehorn if (auto EC = readHeader(SectionReader)) 91217309Snwhitehorn return EC; 92217309Snwhitehorn 93217309Snwhitehorn std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize); 94217309Snwhitehorn if (auto EC = readStrings(SectionReader)) 95217309Snwhitehorn return EC; 96217309Snwhitehorn 97217309Snwhitehorn // We don't know how long the hash table is until we parse it, so let the 98217309Snwhitehorn // function responsible for doing that figure it out. 99217309Snwhitehorn if (auto EC = readHashTable(Reader)) 100217309Snwhitehorn return EC; 101217309Snwhitehorn 102217309Snwhitehorn std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t)); 103217309Snwhitehorn if (auto EC = readEpilogue(SectionReader)) 104217309Snwhitehorn return EC; 105217309Snwhitehorn 106217309Snwhitehorn assert(Reader.bytesRemaining() == 0); 107217309Snwhitehorn return Error::success(); 108217309Snwhitehorn} 109217309Snwhitehorn 110217309SnwhitehornExpected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const { 111217309Snwhitehorn return Strings.getString(ID); 112217309Snwhitehorn} 113217309Snwhitehorn 114217309SnwhitehornExpected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const { 115217309Snwhitehorn uint32_t Hash = 116217309Snwhitehorn (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); 117217309Snwhitehorn size_t Count = IDs.size(); 118217309Snwhitehorn uint32_t Start = Hash % Count; 119217309Snwhitehorn for (size_t I = 0; I < Count; ++I) { 120217309Snwhitehorn // The hash is just a starting point for the search, but if it 121217309Snwhitehorn // doesn't work we should find the string no matter what, because 122217309Snwhitehorn // we iterate the entire array. 123217309Snwhitehorn uint32_t Index = (Start + I) % Count; 124217309Snwhitehorn 125217309Snwhitehorn // If we find 0, it means the item isn't in the hash table. 126217309Snwhitehorn uint32_t ID = IDs[Index]; 127217309Snwhitehorn if (ID == 0) 128217309Snwhitehorn return make_error<RawError>(raw_error_code::no_entry); 129217309Snwhitehorn auto ExpectedStr = getStringForID(ID); 130217309Snwhitehorn if (!ExpectedStr) 131217309Snwhitehorn return ExpectedStr.takeError(); 132217309Snwhitehorn 133217309Snwhitehorn if (*ExpectedStr == Str) 134217309Snwhitehorn return ID; 135217309Snwhitehorn } 136217309Snwhitehorn return make_error<RawError>(raw_error_code::no_entry); 137} 138 139FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const { 140 return IDs; 141} 142