diff options
19 files changed, 110 insertions, 476 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/StringTable.h b/llvm/include/llvm/DebugInfo/CodeView/StringTable.h deleted file mode 100644 index 35f1a57ffe2..00000000000 --- a/llvm/include/llvm/DebugInfo/CodeView/StringTable.h +++ /dev/null @@ -1,70 +0,0 @@ -//===- StringTable.h - CodeView String Table Reader/Writer ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H -#define LLVM_DEBUGINFO_CODEVIEW_STRINGTABLE_H - -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" - -#include "llvm/Support/BinaryStreamRef.h" -#include "llvm/Support/Error.h" - -#include <stdint.h> - -namespace llvm { - -class BinaryStreamReader; -class BinaryStreamRef; -class BinaryStreamWriter; - -namespace codeview { - -/// Represents a read-only view of a CodeView string table. This is a very -/// simple flat buffer consisting of null-terminated strings, where strings -/// are retrieved by their offset in the buffer. StringTableRef does not own -/// the underlying storage for the buffer. -class StringTableRef { -public: - StringTableRef(); - - Error initialize(BinaryStreamReader &Stream); - - StringRef getString(uint32_t Offset) const; - -private: - BinaryStreamRef Stream; -}; - -/// Represents a read-write view of a CodeView string table. StringTable owns -/// the underlying storage for the table, and is capable of serializing the -/// string table into a format understood by StringTableRef. -class StringTable { -public: - // If string S does not exist in the string table, insert it. - // Returns the ID for S. - uint32_t insert(StringRef S); - - uint32_t calculateSerializedSize() const; - Error commit(BinaryStreamWriter &Writer) const; - - uint32_t size() const; - - StringMap<uint32_t>::const_iterator begin() const { return Strings.begin(); } - - StringMap<uint32_t>::const_iterator end() const { return Strings.end(); } - -private: - StringMap<uint32_t> Strings; - uint32_t StringSize = 1; -}; -} -} - -#endif diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h index 3bed67141c5..5510360ff0f 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFile.h @@ -130,7 +130,7 @@ private: std::unique_ptr<PublicsStream> Publics; std::unique_ptr<SymbolStream> Symbols; std::unique_ptr<msf::MappedBlockStream> DirectoryStream; - std::unique_ptr<msf::MappedBlockStream> StringTableStream; + std::unique_ptr<msf::MappedBlockStream> PDBStringTableStream; std::unique_ptr<PDBStringTable> Strings; }; } diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h index cd7d3b06379..941d3119f60 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -50,10 +50,8 @@ public: Error commit(StringRef Filename); - Expected<uint32_t> getNamedStreamIndex(StringRef Name) const; - Error addNamedStream(StringRef Name, uint32_t Size); - private: + Error addNamedStream(StringRef Name, uint32_t Size); Expected<msf::MSFLayout> finalizeMsfLayout(); BumpPtrAllocator &Allocator; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h index 7d5db065cd5..a0c9bf6f2fb 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h @@ -13,7 +13,6 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/BinaryStreamRef.h" #include "llvm/Support/Endian.h" @@ -24,22 +23,19 @@ namespace llvm { class BinaryStreamReader; -namespace msf { -class MappedBlockStream; -} - namespace pdb { -struct PDBStringTableHeader; - class PDBStringTable { public: - Error reload(BinaryStreamReader &Reader); + PDBStringTable(); + + Error load(BinaryStreamReader &Stream); uint32_t getByteSize() const; - uint32_t getNameCount() const; - uint32_t getHashVersion() const; - uint32_t getSignature() const; + + uint32_t getNameCount() const { return NameCount; } + uint32_t getHashVersion() const { return HashVersion; } + uint32_t getSignature() const { return Signature; } StringRef getStringForID(uint32_t ID) const; uint32_t getIDForString(StringRef Str) const; @@ -47,15 +43,11 @@ public: FixedStreamArray<support::ulittle32_t> name_ids() const; private: - Error readHeader(BinaryStreamReader &Reader); - Error readStrings(BinaryStreamReader &Reader); - Error readHashTable(BinaryStreamReader &Reader); - Error readEpilogue(BinaryStreamReader &Reader); - - const PDBStringTableHeader *Header = nullptr; - codeview::StringTableRef Strings; + BinaryStreamRef NamesBuffer; FixedStreamArray<support::ulittle32_t> IDs; uint32_t ByteSize = 0; + uint32_t Signature = 0; + uint32_t HashVersion = 0; uint32_t NameCount = 0; }; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h index 198c35c1aa4..71ed5b403f4 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h @@ -16,39 +16,27 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/StringTable.h" #include "llvm/Support/Error.h" #include <vector> namespace llvm { class BinaryStreamWriter; -class WritableBinaryStreamRef; - -namespace msf { -struct MSFLayout; -} namespace pdb { -class PDBFileBuilder; - class PDBStringTableBuilder { public: // If string S does not exist in the string table, insert it. // Returns the ID for S. uint32_t insert(StringRef S); + uint32_t getStringIndex(StringRef S); - uint32_t calculateSerializedSize() const; + uint32_t finalize(); Error commit(BinaryStreamWriter &Writer) const; private: - uint32_t calculateHashTableSize() const; - Error writeHeader(BinaryStreamWriter &Writer) const; - Error writeStrings(BinaryStreamWriter &Writer) const; - Error writeHashTable(BinaryStreamWriter &Writer) const; - Error writeEpilogue(BinaryStreamWriter &Writer) const; - - codeview::StringTable Strings; + DenseMap<StringRef, uint32_t> Strings; + uint32_t StringSize = 1; }; } // end namespace pdb diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h index 93622d0a439..ba0c75b7f23 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -308,9 +308,9 @@ struct InfoStreamHeader { /// The header preceeding the /names stream. struct PDBStringTableHeader { - support::ulittle32_t Signature; // PDBStringTableSignature - support::ulittle32_t HashVersion; // 1 or 2 - support::ulittle32_t ByteSize; // Number of bytes of names buffer. + support::ulittle32_t Signature; + support::ulittle32_t HashVersion; + support::ulittle32_t ByteSize; }; const uint32_t PDBStringTableSignature = 0xEFFEEFFE; diff --git a/llvm/include/llvm/Support/BinaryStreamReader.h b/llvm/include/llvm/Support/BinaryStreamReader.h index 77738077f5f..ef153e24452 100644 --- a/llvm/include/llvm/Support/BinaryStreamReader.h +++ b/llvm/include/llvm/Support/BinaryStreamReader.h @@ -31,7 +31,6 @@ namespace llvm { /// are overridable. class BinaryStreamReader { public: - BinaryStreamReader() = default; explicit BinaryStreamReader(BinaryStreamRef Stream); virtual ~BinaryStreamReader() {} @@ -244,9 +243,6 @@ public: /// \returns the next byte in the stream. uint8_t peek() const; - std::pair<BinaryStreamReader, BinaryStreamReader> - split(uint32_t Offset) const; - private: BinaryStreamRef Stream; uint32_t Offset; diff --git a/llvm/include/llvm/Support/BinaryStreamWriter.h b/llvm/include/llvm/Support/BinaryStreamWriter.h index 1b61c32a254..6734a797ccc 100644 --- a/llvm/include/llvm/Support/BinaryStreamWriter.h +++ b/llvm/include/llvm/Support/BinaryStreamWriter.h @@ -20,7 +20,6 @@ #include "llvm/Support/Error.h" #include <cstdint> #include <type_traits> -#include <utility> namespace llvm { @@ -31,6 +30,8 @@ namespace llvm { /// although no methods are overridable. class BinaryStreamWriter { public: + // FIXME: We should be able to slice and drop_front etc on Writers / Readers. + BinaryStreamWriter() = default; explicit BinaryStreamWriter(WritableBinaryStreamRef Stream); virtual ~BinaryStreamWriter() {} @@ -151,9 +152,6 @@ public: return writeStreamRef(Array.getUnderlyingStream()); } - /// Splits the Writer into two Writers at a given offset. - std::pair<BinaryStreamWriter, BinaryStreamWriter> split(uint32_t Off) const; - void setOffset(uint32_t Off) { Offset = Off; } uint32_t getOffset() const { return Offset; } uint32_t getLength() const { return Stream.getLength(); } diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 410d5a3777d..421f22ca5d8 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -15,7 +15,6 @@ add_llvm_library(LLVMDebugInfoCodeView ModuleDebugLineFragment.cpp ModuleDebugUnknownFragment.cpp RecordSerialization.cpp - StringTable.cpp SymbolRecordMapping.cpp SymbolDumper.cpp SymbolSerializer.cpp diff --git a/llvm/lib/DebugInfo/CodeView/StringTable.cpp b/llvm/lib/DebugInfo/CodeView/StringTable.cpp deleted file mode 100644 index 5d3a0dd9cfa..00000000000 --- a/llvm/lib/DebugInfo/CodeView/StringTable.cpp +++ /dev/null @@ -1,65 +0,0 @@ -//===- StringTable.cpp - CodeView String Table Reader/Writer ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/CodeView/StringTable.h" - -#include "llvm/Support/BinaryStream.h" -#include "llvm/Support/BinaryStreamReader.h" -#include "llvm/Support/BinaryStreamWriter.h" - -using namespace llvm; -using namespace llvm::codeview; - -StringTableRef::StringTableRef() {} - -Error StringTableRef::initialize(BinaryStreamReader &Reader) { - return Reader.readStreamRef(Stream, Reader.bytesRemaining()); -} - -StringRef StringTableRef::getString(uint32_t Offset) const { - BinaryStreamReader Reader(Stream); - Reader.setOffset(Offset); - StringRef Result; - Error EC = Reader.readCString(Result); - assert(!EC); - consumeError(std::move(EC)); - return Result; -} - -uint32_t StringTable::insert(StringRef S) { - auto P = Strings.insert({S, StringSize}); - - // If a given string didn't exist in the string table, we want to increment - // the string table size. - if (P.second) - StringSize += S.size() + 1; // +1 for '\0' - return P.first->second; -} - -uint32_t StringTable::calculateSerializedSize() const { return StringSize; } - -Error StringTable::commit(BinaryStreamWriter &Writer) const { - assert(Writer.bytesRemaining() == StringSize); - uint32_t MaxOffset = 1; - - for (auto &Pair : Strings) { - StringRef S = Pair.getKey(); - uint32_t Offset = Pair.getValue(); - Writer.setOffset(Offset); - if (auto EC = Writer.writeCString(S)) - return EC; - MaxOffset = std::max<uint32_t>(MaxOffset, Offset + S.size() + 1); - } - - Writer.setOffset(MaxOffset); - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} - -uint32_t StringTable::size() const { return Strings.size(); } diff --git a/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp index db703809f7c..4802cc6e819 100644 --- a/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp @@ -146,7 +146,7 @@ Error DbiStream::reload() { if (ECSubstream.getLength() > 0) { BinaryStreamReader ECReader(ECSubstream); - if (auto EC = ECNames.reload(ECReader)) + if (auto EC = ECNames.load(ECReader)) return EC; } diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp index 859295d2c7d..f158c5c5386 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -338,7 +338,7 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() { } Expected<PDBStringTable &> PDBFile::getStringTable() { - if (!Strings) { + if (!Strings || !PDBStringTableStream) { auto IS = getPDBInfoStream(); if (!IS) return IS.takeError(); @@ -350,13 +350,12 @@ Expected<PDBStringTable &> PDBFile::getStringTable() { if (!NS) return NS.takeError(); - auto N = llvm::make_unique<PDBStringTable>(); BinaryStreamReader Reader(**NS); - if (auto EC = N->reload(Reader)) + auto N = llvm::make_unique<PDBStringTable>(); + if (auto EC = N->load(Reader)) return std::move(EC); - assert(Reader.bytesRemaining() == 0); - StringTableStream = std::move(*NS); Strings = std::move(N); + PDBStringTableStream = std::move(*NS); } return *Strings; } diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp index 4dd965c6907..972c995bf4b 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -80,9 +80,9 @@ Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) { } Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() { - uint32_t StringsLen = Strings.calculateSerializedSize(); + uint32_t PDBStringTableSize = Strings.finalize(); - if (auto EC = addNamedStream("/names", StringsLen)) + if (auto EC = addNamedStream("/names", PDBStringTableSize)) return std::move(EC); if (auto EC = addNamedStream("/LinkInfo", 0)) return std::move(EC); @@ -109,13 +109,6 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() { return Msf->build(); } -Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const { - uint32_t SN = 0; - if (!NamedStreams.get(Name, SN)) - return llvm::make_error<pdb::RawError>(raw_error_code::no_stream); - return SN; -} - Error PDBFileBuilder::commit(StringRef Filename) { auto ExpectedLayout = finalizeMsfLayout(); if (!ExpectedLayout) @@ -153,12 +146,12 @@ Error PDBFileBuilder::commit(StringRef Filename) { return EC; } - auto ExpectedSN = getNamedStreamIndex("/names"); - if (!ExpectedSN) - return ExpectedSN.takeError(); + uint32_t PDBStringTableStreamNo = 0; + if (!NamedStreams.get("/names", PDBStringTableStreamNo)) + return llvm::make_error<pdb::RawError>(raw_error_code::no_stream); - auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer, - *ExpectedSN); + auto NS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, PDBStringTableStreamNo); BinaryStreamWriter NSWriter(*NS); if (auto EC = Strings.commit(NSWriter)) return EC; diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp index ee32f61f16f..fd3e69db86f 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBStringTable.cpp @@ -1,4 +1,5 @@ -//===- PDBStringTable.cpp - PDB String Table ---------------------*- C++-*-===// +//===- PDBStringTable.cpp - PDB String Table -----------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,7 +11,6 @@ #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,91 +21,71 @@ using namespace llvm; using namespace llvm::support; using namespace llvm::pdb; -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; } +PDBStringTable::PDBStringTable() {} + +Error PDBStringTable::load(BinaryStreamReader &Stream) { + ByteSize = Stream.getLength(); -Error PDBStringTable::readHeader(BinaryStreamReader &Reader) { - if (auto EC = Reader.readObject(Header)) + const PDBStringTableHeader *H; + if (auto EC = Stream.readObject(H)) return EC; - if (Header->Signature != PDBStringTableSignature) + if (H->Signature != PDBStringTableSignature) return make_error<RawError>(raw_error_code::corrupt_file, "Invalid hash table signature"); - if (Header->HashVersion != 1 && Header->HashVersion != 2) + if (H->HashVersion != 1 && H->HashVersion != 2) return make_error<RawError>(raw_error_code::corrupt_file, "Unsupported hash version"); - assert(Reader.bytesRemaining() == 0); - return Error::success(); -} - -Error PDBStringTable::readStrings(BinaryStreamReader &Reader) { - if (auto EC = Strings.initialize(Reader)) { + Signature = H->Signature; + HashVersion = H->HashVersion; + if (auto EC = Stream.readStreamRef(NamesBuffer, H->ByteSize)) 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 = Reader.readObject(HashCount)) + if (auto EC = Stream.readObject(HashCount)) return EC; - if (auto EC = Reader.readArray(IDs, *HashCount)) { + if (auto EC = Stream.readArray(IDs, *HashCount)) return joinErrors(std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Could not read bucket array")); - } - return Error::success(); -} - -Error PDBStringTable::readEpilogue(BinaryStreamReader &Reader) { - if (auto EC = Reader.readInteger(NameCount)) - return EC; - - assert(Reader.bytesRemaining() == 0); - return Error::success(); -} - -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; + if (Stream.bytesRemaining() < sizeof(support::ulittle32_t)) + return make_error<RawError>(raw_error_code::corrupt_file, + "Missing name count"); - // 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)) + if (auto EC = Stream.readInteger(NameCount)) return EC; - std::tie(SectionReader, Reader) = Reader.split(sizeof(uint32_t)); - if (auto EC = readEpilogue(SectionReader)) - 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; } + StringRef PDBStringTable::getStringForID(uint32_t ID) const { - return Strings.getString(ID); + 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; } uint32_t PDBStringTable::getIDForString(StringRef Str) const { - uint32_t Hash = - (Header->HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); + uint32_t Hash = (HashVersion == 1) ? hashStringV1(Str) : hashStringV2(Str); size_t Count = IDs.size(); uint32_t Start = Hash % Count; for (size_t I = 0; I < Count; ++I) { diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp index a472181a489..4add6ead212 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp @@ -8,23 +8,31 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" - #include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/Hash.h" -#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/BinaryStreamWriter.h" #include "llvm/Support/Endian.h" using namespace llvm; -using namespace llvm::msf; using namespace llvm::support; using namespace llvm::support::endian; using namespace llvm::pdb; uint32_t PDBStringTableBuilder::insert(StringRef S) { - return Strings.insert(S); + auto P = Strings.insert({S, StringSize}); + + // If a given string didn't exist in the string table, we want to increment + // the string table size. + if (P.second) + StringSize += S.size() + 1; // +1 for '\0' + return P.first->second; +} + +uint32_t PDBStringTableBuilder::getStringIndex(StringRef S) { + auto Iter = Strings.find(S); + assert(Iter != Strings.end()); + return Iter->second; } static uint32_t computeBucketCount(uint32_t NumStrings) { @@ -36,52 +44,49 @@ static uint32_t computeBucketCount(uint32_t NumStrings) { return (NumStrings + 1) * 1.25; } -uint32_t PDBStringTableBuilder::calculateHashTableSize() const { - uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field. - Size += sizeof(uint32_t) * computeBucketCount(Strings.size()); - - return Size; -} - -uint32_t PDBStringTableBuilder::calculateSerializedSize() const { +uint32_t PDBStringTableBuilder::finalize() { uint32_t Size = 0; Size += sizeof(PDBStringTableHeader); - Size += Strings.calculateSerializedSize(); - Size += calculateHashTableSize(); - Size += sizeof(uint32_t); // The /names stream ends with the string count. + Size += StringSize; + Size += sizeof(uint32_t); // Hash table begins with 4-byte size field. + + uint32_t BucketCount = computeBucketCount(Strings.size()); + Size += BucketCount * sizeof(uint32_t); + + Size += + sizeof(uint32_t); // The /names stream ends with the number of strings. return Size; } -Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const { +Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const { // Write a header PDBStringTableHeader H; H.Signature = PDBStringTableSignature; H.HashVersion = 1; - H.ByteSize = Strings.calculateSerializedSize(); + H.ByteSize = StringSize; if (auto EC = Writer.writeObject(H)) return EC; - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} -Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const { - if (auto EC = Strings.commit(Writer)) - return EC; - - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} + // Write a string table. + uint32_t StringStart = Writer.getOffset(); + for (auto Pair : Strings) { + StringRef S = Pair.first; + uint32_t Offset = Pair.second; + Writer.setOffset(StringStart + Offset); + if (auto EC = Writer.writeCString(S)) + return EC; + } + Writer.setOffset(StringStart + StringSize); -Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const { // Write a hash table. uint32_t BucketCount = computeBucketCount(Strings.size()); if (auto EC = Writer.writeInteger(BucketCount)) return EC; std::vector<ulittle32_t> Buckets(BucketCount); - for (auto &Pair : Strings) { - StringRef S = Pair.getKey(); - uint32_t Offset = Pair.getValue(); + for (auto Pair : Strings) { + StringRef S = Pair.first; + uint32_t Offset = Pair.second; uint32_t Hash = hashStringV1(S); for (uint32_t I = 0; I != BucketCount; ++I) { @@ -97,37 +102,7 @@ Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const { if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets))) return EC; - - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} - -Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const { - if (auto EC = Writer.writeInteger<uint32_t>(Strings.size())) - return EC; - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} - -Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const { - BinaryStreamWriter SectionWriter; - - std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader)); - if (auto EC = writeHeader(SectionWriter)) - return EC; - - std::tie(SectionWriter, Writer) = - Writer.split(Strings.calculateSerializedSize()); - if (auto EC = writeStrings(SectionWriter)) + if (auto EC = Writer.writeInteger(static_cast<uint32_t>(Strings.size()))) return EC; - - std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize()); - if (auto EC = writeHashTable(SectionWriter)) - return EC; - - std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t)); - if (auto EC = writeEpilogue(SectionWriter)) - return EC; - return Error::success(); } diff --git a/llvm/lib/DebugInfo/PDB/Native/StringTableStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/StringTableStreamBuilder.cpp deleted file mode 100644 index b19440961bc..00000000000 --- a/llvm/lib/DebugInfo/PDB/Native/StringTableStreamBuilder.cpp +++ /dev/null @@ -1,123 +0,0 @@ -//===- StringTableStreamBuilder.cpp - PDB String Table ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/PDB/Native/StringTableStreamBuilder.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/DebugInfo/PDB/Native/Hash.h" -#include "llvm/DebugInfo/PDB/Native/RawTypes.h" -#include "llvm/Support/BinaryStreamWriter.h" -#include "llvm/Support/Endian.h" - -using namespace llvm; -using namespace llvm::support; -using namespace llvm::support::endian; -using namespace llvm::pdb; - -uint32_t StringTableStreamBuilder::insert(StringRef S) { - return Strings.insert(S); -} - -static uint32_t computeBucketCount(uint32_t NumStrings) { - // The /names stream is basically an on-disk open-addressing hash table. - // Hash collisions are resolved by linear probing. We cannot make - // utilization 100% because it will make the linear probing extremely - // slow. But lower utilization wastes disk space. As a reasonable - // load factor, we choose 80%. We need +1 because slot 0 is reserved. - return (NumStrings + 1) * 1.25; -} - -uint32_t StringTableStreamBuilder::hashTableSize() const { - uint32_t Size = sizeof(uint32_t); // Hash table begins with 4-byte size field. - - Size += computeBucketCount(Strings.size()) * sizeof(uint32_t); - return Size; -} - -uint32_t StringTableStreamBuilder::calculateSerializedSize() const { - uint32_t Size = 0; - Size += sizeof(StringTableHeader); - Size += Strings.calculateSerializedSize(); - Size += hashTableSize(); - Size += sizeof(uint32_t); // The table ends with the number of strings. - return Size; -} - -Error StringTableStreamBuilder::writeHeader(BinaryStreamWriter &Writer) const { - // Write a header - StringTableHeader H; - H.Signature = StringTableSignature; - H.HashVersion = 1; - H.ByteSize = Strings.calculateSerializedSize(); - if (auto EC = Writer.writeObject(H)) - return EC; - - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} - -Error StringTableStreamBuilder::writeStrings(BinaryStreamWriter &Writer) const { - if (auto EC = Strings.commit(Writer)) - return EC; - - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} - -Error StringTableStreamBuilder::writeHashTable( - BinaryStreamWriter &Writer) const { - // Write a hash table. - uint32_t BucketCount = computeBucketCount(Strings.size()); - if (auto EC = Writer.writeInteger(BucketCount)) - return EC; - - std::vector<ulittle32_t> Buckets(BucketCount); - - for (auto &Pair : Strings) { - StringRef S = Pair.getKey(); - uint32_t Offset = Pair.getValue(); - uint32_t Hash = hashStringV1(S); - - for (uint32_t I = 0; I != BucketCount; ++I) { - uint32_t Slot = (Hash + I) % BucketCount; - if (Slot == 0) - continue; // Skip reserved slot - if (Buckets[Slot] != 0) - continue; - Buckets[Slot] = Offset; - break; - } - } - - if (auto EC = Writer.writeArray(makeArrayRef(Buckets))) - return EC; - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} - -Error StringTableStreamBuilder::commit(BinaryStreamWriter &Writer) const { - BinaryStreamWriter Section; - - std::tie(Section, Writer) = Writer.split(sizeof(StringTableHeader)); - if (auto EC = writeHeader(Section)) - return EC; - - std::tie(Section, Writer) = Writer.split(Strings.calculateSerializedSize()); - if (auto EC = writeStrings(Section)) - return EC; - - std::tie(Section, Writer) = Writer.split(hashTableSize()); - if (auto EC = writeHashTable(Section)) - return EC; - - if (auto EC = Writer.writeInteger<uint32_t>(Strings.size())) - return EC; - - assert(Writer.bytesRemaining() == 0); - return Error::success(); -} diff --git a/llvm/lib/Support/BinaryStreamReader.cpp b/llvm/lib/Support/BinaryStreamReader.cpp index 702d98770e0..c7a2e0ddb17 100644 --- a/llvm/lib/Support/BinaryStreamReader.cpp +++ b/llvm/lib/Support/BinaryStreamReader.cpp @@ -93,16 +93,3 @@ uint8_t BinaryStreamReader::peek() const { llvm::consumeError(std::move(EC)); return Buffer[0]; } - -std::pair<BinaryStreamReader, BinaryStreamReader> -BinaryStreamReader::split(uint32_t Off) const { - assert(getLength() >= Off); - - BinaryStreamRef First = Stream.drop_front(Offset); - - BinaryStreamRef Second = First.drop_front(Off); - First = First.keep_front(Off); - BinaryStreamReader W1{First}; - BinaryStreamReader W2{Second}; - return std::make_pair(W1, W2); -}
\ No newline at end of file diff --git a/llvm/lib/Support/BinaryStreamWriter.cpp b/llvm/lib/Support/BinaryStreamWriter.cpp index d78dbc68f59..d60b75642d0 100644 --- a/llvm/lib/Support/BinaryStreamWriter.cpp +++ b/llvm/lib/Support/BinaryStreamWriter.cpp @@ -59,19 +59,6 @@ Error BinaryStreamWriter::writeStreamRef(BinaryStreamRef Ref, uint32_t Length) { return Error::success(); } -std::pair<BinaryStreamWriter, BinaryStreamWriter> -BinaryStreamWriter::split(uint32_t Off) const { - assert(getLength() >= Off); - - WritableBinaryStreamRef First = Stream.drop_front(Offset); - - WritableBinaryStreamRef Second = First.drop_front(Off); - First = First.keep_front(Off); - BinaryStreamWriter W1{First}; - BinaryStreamWriter W2{Second}; - return std::make_pair(W1, W2); -} - Error BinaryStreamWriter::padToAlignment(uint32_t Align) { uint32_t NewOffset = alignTo(Offset, Align); if (NewOffset > getLength()) diff --git a/llvm/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp b/llvm/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp index 44cc85d9e44..514cdc8d578 100644 --- a/llvm/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp +++ b/llvm/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp @@ -33,7 +33,7 @@ TEST_F(StringTableBuilderTest, Simple) { EXPECT_EQ(1U, Builder.insert("foo")); EXPECT_EQ(9U, Builder.insert("baz")); - std::vector<uint8_t> Buffer(Builder.calculateSerializedSize()); + std::vector<uint8_t> Buffer(Builder.finalize()); MutableBinaryByteStream OutStream(Buffer, little); BinaryStreamWriter Writer(OutStream); EXPECT_NO_ERROR(Builder.commit(Writer)); @@ -42,7 +42,7 @@ TEST_F(StringTableBuilderTest, Simple) { BinaryByteStream InStream(Buffer, little); BinaryStreamReader Reader(InStream); PDBStringTable Table; - EXPECT_NO_ERROR(Table.reload(Reader)); + EXPECT_NO_ERROR(Table.load(Reader)); EXPECT_EQ(3U, Table.getNameCount()); EXPECT_EQ(1U, Table.getHashVersion()); |