]> granicus.if.org Git - llvm/commitdiff
Resubmit r301986 and r301987 "Add codeview::StringTable"
authorZachary Turner <zturner@google.com>
Wed, 3 May 2017 15:58:37 +0000 (15:58 +0000)
committerZachary Turner <zturner@google.com>
Wed, 3 May 2017 15:58:37 +0000 (15:58 +0000)
This was reverted due to a "missing" file, but in reality
what happened was that I renamed a file, and then due to
a merge conflict both the old file and the new file got
added to the repository.  This led to an unused cpp file
being in the repo and not referenced by any CMakeLists.txt
but #including a .h file that wasn't in the repo.  In an
even more unfortunate coincidence, CMake didn't report the
unused cpp file because it was in a subdirectory of the
folder with the CMakeLists.txt, and not in the same directory
as any CMakeLists.txt.

The presence of the unused file was then breaking certain
tools that determine file lists by globbing rather than
by what's specified in CMakeLists.txt

In any case, the fix is to just remove the unused file from
the patch set.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@302042 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
include/llvm/DebugInfo/CodeView/StringTable.h [new file with mode: 0644]
include/llvm/DebugInfo/PDB/Native/PDBFile.h
include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
include/llvm/DebugInfo/PDB/Native/PDBStringTable.h
include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
include/llvm/DebugInfo/PDB/Native/RawTypes.h
include/llvm/Support/BinaryStreamReader.h
include/llvm/Support/BinaryStreamWriter.h
lib/DebugInfo/CodeView/CMakeLists.txt
lib/DebugInfo/CodeView/StringTable.cpp [new file with mode: 0644]
lib/DebugInfo/PDB/Native/DbiStream.cpp
lib/DebugInfo/PDB/Native/PDBFile.cpp
lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
lib/DebugInfo/PDB/Native/PDBStringTable.cpp
lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
lib/Support/BinaryStreamReader.cpp
lib/Support/BinaryStreamWriter.cpp
unittests/DebugInfo/PDB/StringTableBuilderTest.cpp

diff --git a/include/llvm/DebugInfo/CodeView/StringTable.h b/include/llvm/DebugInfo/CodeView/StringTable.h
new file mode 100644 (file)
index 0000000..35f1a57
--- /dev/null
@@ -0,0 +1,70 @@
+//===- 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
index 5510360ff0f696b6a215e9d55f5097be45d43107..3bed67141c56a8ec72815552f6c8a15d39fe57ae 100644 (file)
@@ -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> PDBStringTableStream;
+  std::unique_ptr<msf::MappedBlockStream> StringTableStream;
   std::unique_ptr<PDBStringTable> Strings;
 };
 }
index 941d3119f60ea38c06502c3248e3b8753d30fb4e..cd7d3b0637933656f461f1732357b4570b185d3a 100644 (file)
@@ -50,8 +50,10 @@ public:
 
   Error commit(StringRef Filename);
 
-private:
+  Expected<uint32_t> getNamedStreamIndex(StringRef Name) const;
   Error addNamedStream(StringRef Name, uint32_t Size);
+
+private:
   Expected<msf::MSFLayout> finalizeMsfLayout();
 
   BumpPtrAllocator &Allocator;
index a0c9bf6f2fbd9522ab1c349f01425d8ae1e95692..7d5db065cd5ad1aace5b9b6d2356ed985de15e7b 100644 (file)
@@ -13,6 +13,7 @@
 
 #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"
 namespace llvm {
 class BinaryStreamReader;
 
+namespace msf {
+class MappedBlockStream;
+}
+
 namespace pdb {
 
+struct PDBStringTableHeader;
+
 class PDBStringTable {
 public:
-  PDBStringTable();
-
-  Error load(BinaryStreamReader &Stream);
+  Error reload(BinaryStreamReader &Reader);
 
   uint32_t getByteSize() const;
-
-  uint32_t getNameCount() const { return NameCount; }
-  uint32_t getHashVersion() const { return HashVersion; }
-  uint32_t getSignature() const { return Signature; }
+  uint32_t getNameCount() const;
+  uint32_t getHashVersion() const;
+  uint32_t getSignature() const;
 
   StringRef getStringForID(uint32_t ID) const;
   uint32_t getIDForString(StringRef Str) const;
@@ -43,11 +47,15 @@ public:
   FixedStreamArray<support::ulittle32_t> name_ids() const;
 
 private:
-  BinaryStreamRef NamesBuffer;
+  Error readHeader(BinaryStreamReader &Reader);
+  Error readStrings(BinaryStreamReader &Reader);
+  Error readHashTable(BinaryStreamReader &Reader);
+  Error readEpilogue(BinaryStreamReader &Reader);
+
+  const PDBStringTableHeader *Header = nullptr;
+  codeview::StringTableRef Strings;
   FixedStreamArray<support::ulittle32_t> IDs;
   uint32_t ByteSize = 0;
-  uint32_t Signature = 0;
-  uint32_t HashVersion = 0;
   uint32_t NameCount = 0;
 };
 
index 71ed5b403f4eb20bdc129e75ea29ea6b40e168df..198c35c1aa4200e4dccea0e914124810b04ccee7 100644 (file)
 
 #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 finalize();
+  uint32_t calculateSerializedSize() const;
   Error commit(BinaryStreamWriter &Writer) const;
 
 private:
-  DenseMap<StringRef, uint32_t> Strings;
-  uint32_t StringSize = 1;
+  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;
 };
 
 } // end namespace pdb
index ba0c75b7f23fe943997256f042ac5b7d3f87236f..93622d0a4394946b6cfe3d985611f8dcc17c7400 100644 (file)
@@ -308,9 +308,9 @@ struct InfoStreamHeader {
 
 /// The header preceeding the /names stream.
 struct PDBStringTableHeader {
-  support::ulittle32_t Signature;
-  support::ulittle32_t HashVersion;
-  support::ulittle32_t ByteSize;
+  support::ulittle32_t Signature;   // PDBStringTableSignature
+  support::ulittle32_t HashVersion; // 1 or 2
+  support::ulittle32_t ByteSize;    // Number of bytes of names buffer.
 };
 
 const uint32_t PDBStringTableSignature = 0xEFFEEFFE;
index ef153e24452c016d72f25710e04f786ba876b634..77738077f5ffebc0471d35a60749e2c7dd4efb9c 100644 (file)
@@ -31,6 +31,7 @@ namespace llvm {
 /// are overridable.
 class BinaryStreamReader {
 public:
+  BinaryStreamReader() = default;
   explicit BinaryStreamReader(BinaryStreamRef Stream);
   virtual ~BinaryStreamReader() {}
 
@@ -243,6 +244,9 @@ 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;
index 6734a797ccc4408a07db8212bb8f92de7da72920..1b61c32a2541864e08aa33adbe66f5fa1192f945 100644 (file)
@@ -20,6 +20,7 @@
 #include "llvm/Support/Error.h"
 #include <cstdint>
 #include <type_traits>
+#include <utility>
 
 namespace llvm {
 
@@ -30,8 +31,6 @@ 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() {}
@@ -152,6 +151,9 @@ 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(); }
index 421f22ca5d8d7aff766cb2ae3a6425a2e0d10fea..410d5a3777d475365dd9dd576b8d7be917c9f4d7 100644 (file)
@@ -15,6 +15,7 @@ add_llvm_library(LLVMDebugInfoCodeView
   ModuleDebugLineFragment.cpp
   ModuleDebugUnknownFragment.cpp
   RecordSerialization.cpp
+  StringTable.cpp
   SymbolRecordMapping.cpp
   SymbolDumper.cpp
   SymbolSerializer.cpp
diff --git a/lib/DebugInfo/CodeView/StringTable.cpp b/lib/DebugInfo/CodeView/StringTable.cpp
new file mode 100644 (file)
index 0000000..5d3a0dd
--- /dev/null
@@ -0,0 +1,65 @@
+//===- 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(); }
index 4802cc6e8197ec33dc20fae7e23547caad2f6d5d..db703809f7c9c076ab94f8f5ea99a62733133d94 100644 (file)
@@ -146,7 +146,7 @@ Error DbiStream::reload() {
 
   if (ECSubstream.getLength() > 0) {
     BinaryStreamReader ECReader(ECSubstream);
-    if (auto EC = ECNames.load(ECReader))
+    if (auto EC = ECNames.reload(ECReader))
       return EC;
   }
 
index f158c5c538695d2875aac391915f1df75d6a2e44..859295d2c7d3373be2b5bf94a3f002683b190e5a 100644 (file)
@@ -338,7 +338,7 @@ Expected<SymbolStream &> PDBFile::getPDBSymbolStream() {
 }
 
 Expected<PDBStringTable &> PDBFile::getStringTable() {
-  if (!Strings || !PDBStringTableStream) {
+  if (!Strings) {
     auto IS = getPDBInfoStream();
     if (!IS)
       return IS.takeError();
@@ -350,12 +350,13 @@ Expected<PDBStringTable &> PDBFile::getStringTable() {
     if (!NS)
       return NS.takeError();
 
-    BinaryStreamReader Reader(**NS);
     auto N = llvm::make_unique<PDBStringTable>();
-    if (auto EC = N->load(Reader))
+    BinaryStreamReader Reader(**NS);
+    if (auto EC = N->reload(Reader))
       return std::move(EC);
+    assert(Reader.bytesRemaining() == 0);
+    StringTableStream = std::move(*NS);
     Strings = std::move(N);
-    PDBStringTableStream = std::move(*NS);
   }
   return *Strings;
 }
index 972c995bf4bdcd0bdc8bb8b60bebc11e4c1946c4..4dd965c69071e4f851ebc303d4882ece4c159ef4 100644 (file)
@@ -80,9 +80,9 @@ Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
 }
 
 Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
-  uint32_t PDBStringTableSize = Strings.finalize();
+  uint32_t StringsLen = Strings.calculateSerializedSize();
 
-  if (auto EC = addNamedStream("/names", PDBStringTableSize))
+  if (auto EC = addNamedStream("/names", StringsLen))
     return std::move(EC);
   if (auto EC = addNamedStream("/LinkInfo", 0))
     return std::move(EC);
@@ -109,6 +109,13 @@ 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)
@@ -146,12 +153,12 @@ Error PDBFileBuilder::commit(StringRef Filename) {
       return EC;
   }
 
-  uint32_t PDBStringTableStreamNo = 0;
-  if (!NamedStreams.get("/names", PDBStringTableStreamNo))
-    return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
+  auto ExpectedSN = getNamedStreamIndex("/names");
+  if (!ExpectedSN)
+    return ExpectedSN.takeError();
 
-  auto NS = WritableMappedBlockStream::createIndexedStream(
-      Layout, Buffer, PDBStringTableStreamNo);
+  auto NS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
+                                                           *ExpectedSN);
   BinaryStreamWriter NSWriter(*NS);
   if (auto EC = Strings.commit(NSWriter))
     return EC;
index fd3e69db86fbb930d06785ed05e624f4dc9043fa..ee32f61f16fa322fcab1e44042a6b01fb62a35ea 100644 (file)
@@ -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) {
index 4add6ead2126f4e5fe84a351ab8a4c5c8ffe7e8f..a472181a4895ce3c5488890a13f43ab59884942a 100644 (file)
@@ -8,31 +8,23 @@
 //===----------------------------------------------------------------------===//
 
 #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) {
-  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;
+  return Strings.insert(S);
 }
 
 static uint32_t computeBucketCount(uint32_t NumStrings) {
@@ -44,49 +36,52 @@ static uint32_t computeBucketCount(uint32_t NumStrings) {
   return (NumStrings + 1) * 1.25;
 }
 
-uint32_t PDBStringTableBuilder::finalize() {
-  uint32_t Size = 0;
-  Size += sizeof(PDBStringTableHeader);
-  Size += StringSize;
-  Size += sizeof(uint32_t); // Hash table begins with 4-byte size field.
+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());
 
-  uint32_t BucketCount = computeBucketCount(Strings.size());
-  Size += BucketCount * sizeof(uint32_t);
+  return Size;
+}
 
-  Size +=
-      sizeof(uint32_t); // The /names stream ends with the number of strings.
+uint32_t PDBStringTableBuilder::calculateSerializedSize() const {
+  uint32_t Size = 0;
+  Size += sizeof(PDBStringTableHeader);
+  Size += Strings.calculateSerializedSize();
+  Size += calculateHashTableSize();
+  Size += sizeof(uint32_t); // The /names stream ends with the string count.
   return Size;
 }
 
-Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
+Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
   // Write a header
   PDBStringTableHeader H;
   H.Signature = PDBStringTableSignature;
   H.HashVersion = 1;
-  H.ByteSize = StringSize;
+  H.ByteSize = Strings.calculateSerializedSize();
   if (auto EC = Writer.writeObject(H))
     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::writeStrings(BinaryStreamWriter &Writer) const {
+  if (auto EC = Strings.commit(Writer))
+    return EC;
+
+  assert(Writer.bytesRemaining() == 0);
+  return Error::success();
+}
 
+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.first;
-    uint32_t Offset = Pair.second;
+  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) {
@@ -102,7 +97,37 @@ Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const {
 
   if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets)))
     return EC;
-  if (auto EC = Writer.writeInteger(static_cast<uint32_t>(Strings.size())))
+
+  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))
     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();
 }
index c7a2e0ddb179b8519cd5407384efa9df13ec8c96..702d98770e0525ab6000e41b1196e7ae894441bd 100644 (file)
@@ -93,3 +93,16 @@ 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
index d60b75642d0f148cd59a21f09333beb2da087943..d78dbc68f5936aae7c9c14d64adb9093fe2538d5 100644 (file)
@@ -59,6 +59,19 @@ 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())
index 514cdc8d578684065454208201fbfe04bf338412..44cc85d9e4483af0d38054c04fd8db56aff1303a 100644 (file)
@@ -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.finalize());
+  std::vector<uint8_t> Buffer(Builder.calculateSerializedSize());
   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.load(Reader));
+  EXPECT_NO_ERROR(Table.reload(Reader));
 
   EXPECT_EQ(3U, Table.getNameCount());
   EXPECT_EQ(1U, Table.getHashVersion());