diff options
Diffstat (limited to 'llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp | 94 |
1 files changed, 57 insertions, 37 deletions
diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index fd3e69db86f..ee32f61f16f 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -1,5 +1,4 @@ -//===- PDBStringTable.cpp - PDB String Table -----------------------*- C++ -//-*-===// +//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -11,6 +10,7 @@ #include "llvm/DebugInfo/PDB/Native/PDBStringTable.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" @@ -21,71 +21,91 @@ using namespace llvm; using namespace llvm::support; using namespace llvm::pdb; -PDBStringTable::PDBStringTable() {} - -Error PDBStringTable::load(BinaryStreamReader &Stream) { - ByteSize = Stream.getLength(); +uint32_t PDBStringTable::getByteSize() const { return ByteSize; } +uint32_t PDBStringTable::getNameCount() const { return NameCount; } +uint32_t PDBStringTable::getHashVersion() const { return Header->HashVersion; } +uint32_t PDBStringTable::getSignature() const { return Header->Signature; } - const PDBStringTableHeader *H; - if (auto EC = Stream.readObject(H)) +Error PDBStringTable::readHeader(BinaryStreamReader &Reader) { + if (auto EC = Reader.readObject(Header)) return EC; - if (H->Signature != PDBStringTableSignature) + if (Header->Signature != PDBStringTableSignature) return make_error<RawError>(raw_error_code::corrupt_file, "Invalid hash table signature"); - if (H->HashVersion != 1 && H->HashVersion != 2) + if (Header->HashVersion != 1 && Header->HashVersion != 2) return make_error<RawError>(raw_error_code::corrupt_file, "Unsupported hash version"); - Signature = H->Signature; - HashVersion = H->HashVersion; - if (auto EC = Stream.readStreamRef(NamesBuffer, H->ByteSize)) + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} + +Error PDBStringTable::readStrings(BinaryStreamReader &Reader) { + if (auto EC = Strings.initialize(Reader)) { return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Invalid hash table byte length")); + } + + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} +Error PDBStringTable::readHashTable(BinaryStreamReader &Reader) { const support::ulittle32_t *HashCount; - if (auto EC = Stream.readObject(HashCount)) + if (auto EC = Reader.readObject(HashCount)) return EC; - if (auto EC = Stream.readArray(IDs, *HashCount)) + if (auto EC = Reader.readArray(IDs, *HashCount)) { return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Could not read bucket array")); + } - if (Stream.bytesRemaining() < sizeof(support::ulittle32_t)) - return make_error<RawError>(raw_error_code::corrupt_file, - "Missing name count"); + return Error::success(); +} - if (auto EC = Stream.readInteger(NameCount)) +Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) { + if (auto EC = Reader.readInteger(NameCount)) return EC; - if (Stream.bytesRemaining() > 0) - return make_error<RawError>(raw_error_code::stream_too_long, - "Unexpected bytes found in string table"); - + assert(Reader.bytesRemaining() == 0); return Error::success(); } -uint32_t PDBStringTable::getByteSize() const { return ByteSize; } +Error PDBStringTable::reload(BinaryStreamReader &Reader) { + + BinaryStreamReader SectionReader; + + std::tie(SectionReader, Reader) = Reader.split(sizeof(PDBStringTableHeader)); + if (auto EC = readHeader(SectionReader)) + return EC; + + std::tie(SectionReader, Reader) = Reader.split(Header->ByteSize); + if (auto EC = readStrings(SectionReader)) + return EC; + + // We don't know how long the hash table is until we parse it, so let the + // function responsible for doing that figure it out. + if (auto EC = readHashTable(Reader)) + return EC; + + std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t)); + if (auto EC = readEpilogue(SectionReader)) + return EC; + + assert(Reader.bytesRemaining() == 0); + return Error::success(); +} StringRef PDBStringTable::getStringForID(uint32_t ID) const { - if (ID == IDs[0]) - return StringRef(); - - // NamesBuffer is a buffer of null terminated strings back to back. ID is - // the starting offset of the string we're looking for. So just seek into - // the desired offset and a read a null terminated stream from that offset. - StringRef Result; - BinaryStreamReader NameReader(NamesBuffer); - NameReader.setOffset(ID); - if (auto EC = NameReader.readCString(Result)) - consumeError(std::move(EC)); - return Result; + return Strings.getString(ID); } uint32_t PDBStringTable::getIDForString(StringRef Str) const { - uint32_t Hash = (HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); + uint32_t Hash = + (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); size_t Count = IDs.size(); uint32_t Start = Hash % Count; for (size_t I = 0; I < Count; ++I) { |