Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
35293 views
//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"910#include "llvm/DebugInfo/PDB/Native/Hash.h"11#include "llvm/DebugInfo/PDB/Native/RawError.h"12#include "llvm/DebugInfo/PDB/Native/RawTypes.h"13#include "llvm/Support/BinaryStreamReader.h"14#include "llvm/Support/Endian.h"1516using namespace llvm;17using namespace llvm::support;18using namespace llvm::pdb;1920uint32_t PDBStringTable::getByteSize() const { return Header->ByteSize; }21uint32_t PDBStringTable::getNameCount() const { return NameCount; }22uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; }23uint32_t PDBStringTable::getSignature() const { return Header->Signature; }2425Error PDBStringTable::readHeader(BinaryStreamReader &Reader) {26if (auto EC = Reader.readObject(Header))27return EC;2829if (Header->Signature != PDBStringTableSignature)30return make_error<RawError>(raw_error_code::corrupt_file,31"Invalid hash table signature");32if (Header->HashVersion != 1 && Header->HashVersion != 2)33return make_error<RawError>(raw_error_code::corrupt_file,34"Unsupported hash version");3536assert(Reader.bytesRemaining() == 0);37return Error::success();38}3940Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {41BinaryStreamRef Stream;42if (auto EC = Reader.readStreamRef(Stream))43return EC;4445if (auto EC = Strings.initialize(Stream)) {46return joinErrors(std::move(EC),47make_error<RawError>(raw_error_code::corrupt_file,48"Invalid hash table byte length"));49}5051assert(Reader.bytesRemaining() == 0);52return Error::success();53}5455const codeview::DebugStringTableSubsectionRef &56PDBStringTable::getStringTable() const {57return Strings;58}5960Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) {61const support::ulittle32_t *HashCount;62if (auto EC = Reader.readObject(HashCount))63return EC;6465if (auto EC = Reader.readArray(IDs, *HashCount)) {66return joinErrors(std::move(EC),67make_error<RawError>(raw_error_code::corrupt_file,68"Could not read bucket array"));69}7071return Error::success();72}7374Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) {75if (auto EC = Reader.readInteger(NameCount))76return EC;7778assert(Reader.bytesRemaining() == 0);79return Error::success();80}8182Error PDBStringTable::reload(BinaryStreamReader &Reader) {8384BinaryStreamReader SectionReader;8586std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader));87if (auto EC = readHeader(SectionReader))88return EC;8990std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize);91if (auto EC = readStrings(SectionReader))92return EC;9394// We don't know how long the hash table is until we parse it, so let the95// function responsible for doing that figure it out.96if (auto EC = readHashTable(Reader))97return EC;9899std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t));100if (auto EC = readEpilogue(SectionReader))101return EC;102103assert(Reader.bytesRemaining() == 0);104return Error::success();105}106107Expected<StringRef> PDBStringTable::getStringForID(uint32_t ID) const {108return Strings.getString(ID);109}110111Expected<uint32_t> PDBStringTable::getIDForString(StringRef Str) const {112uint32_t Hash =113(Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str);114size_t Count = IDs.size();115uint32_t Start = Hash % Count;116for (size_t I = 0; I < Count; ++I) {117// The hash is just a starting point for the search, but if it118// doesn't work we should find the string no matter what, because119// we iterate the entire array.120uint32_t Index = (Start + I) % Count;121122// If we find 0, it means the item isn't in the hash table.123uint32_t ID = IDs[Index];124if (ID == 0)125return make_error<RawError>(raw_error_code::no_entry);126auto ExpectedStr = getStringForID(ID);127if (!ExpectedStr)128return ExpectedStr.takeError();129130if (*ExpectedStr == Str)131return ID;132}133return make_error<RawError>(raw_error_code::no_entry);134}135136FixedStreamArray<support::ulittle32_t> PDBStringTable::name_ids() const {137return IDs;138}139140141