[llvm] r328002 - Resubmit "Support embedding natvis files in PDBs."

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 20 10:06:39 PDT 2018


Author: zturner
Date: Tue Mar 20 10:06:39 2018
New Revision: 328002

URL: http://llvm.org/viewvc/llvm-project?rev=328002&view=rev
Log:
Resubmit "Support embedding natvis files in PDBs."

The issue causing this to fail in certain configurations
should be fixed.

It was due to the fact that DIA apparently expects there to be
a null string at ID 1 in the string table.  I'm not sure why this
is important but it seems to make a difference, so set it.

Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
    llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/HashTable.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawConstants.h
    llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h
    llvm/trunk/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp
    llvm/trunk/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp
    llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
    llvm/trunk/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp
    llvm/trunk/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
    llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
    llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h Tue Mar 20 10:06:39 2018
@@ -10,6 +10,7 @@
 #ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H
 #define LLVM_DEBUGINFO_CODEVIEW_DEBUGSTRINGTABLESUBSECTION_H
 
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
@@ -66,19 +67,24 @@ public:
   uint32_t insert(StringRef S);
 
   // Return the ID for string S.  Assumes S exists in the table.
-  uint32_t getStringId(StringRef S) const;
+  uint32_t getIdForString(StringRef S) const;
+
+  StringRef getStringForId(uint32_t Id) const;
 
   uint32_t calculateSerializedSize() const override;
   Error commit(BinaryStreamWriter &Writer) const override;
 
   uint32_t size() const;
 
-  StringMap<uint32_t>::const_iterator begin() const { return Strings.begin(); }
+  StringMap<uint32_t>::const_iterator begin() const {
+    return StringToId.begin();
+  }
 
-  StringMap<uint32_t>::const_iterator end() const { return Strings.end(); }
+  StringMap<uint32_t>::const_iterator end() const { return StringToId.end(); }
 
 private:
-  StringMap<uint32_t> Strings;
+  DenseMap<uint32_t, StringRef> IdToString;
+  StringMap<uint32_t> StringToId;
   uint32_t StringSize = 1;
 };
 

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h Tue Mar 20 10:06:39 2018
@@ -19,8 +19,7 @@ class DIASession;
 
 class DIAInjectedSource : public IPDBInjectedSource {
 public:
-  explicit DIAInjectedSource(const DIASession &Session,
-                             CComPtr<IDiaInjectedSource> DiaSourceFile);
+  explicit DIAInjectedSource(CComPtr<IDiaInjectedSource> DiaSourceFile);
 
   uint32_t getCrc32() const override;
   uint64_t getCodeByteSize() const override;
@@ -31,7 +30,6 @@ public:
   std::string getCode() const override;
 
 private:
-  const DIASession &Session;
   CComPtr<IDiaInjectedSource> SourceFile;
 };
 } // namespace pdb

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/HashTable.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/HashTable.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/HashTable.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/HashTable.h Tue Mar 20 10:06:39 2018
@@ -213,6 +213,7 @@ public:
     Deleted.clear();
   }
 
+  bool empty() const { return size() == 0; }
   uint32_t capacity() const { return Buckets.size(); }
   uint32_t size() const { return Present.count(); }
 
@@ -303,12 +304,12 @@ private:
 
   void grow() {
     uint32_t S = size();
+    uint32_t MaxLoad = maxLoad(capacity());
     if (S < maxLoad(capacity()))
       return;
     assert(capacity() != UINT32_MAX && "Can't grow Hash table!");
 
-    uint32_t NewCapacity =
-        (capacity() <= INT32_MAX) ? capacity() * 2 : UINT32_MAX;
+    uint32_t NewCapacity = (capacity() <= INT32_MAX) ? MaxLoad * 2 : UINT32_MAX;
 
     // Growing requires rebuilding the table and re-hashing every item.  Make a
     // copy with a larger capacity, insert everything into the copy, then swap

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h Tue Mar 20 10:06:39 2018
@@ -17,9 +17,11 @@
 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
 #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
 
 #include <memory>
 #include <vector>
@@ -54,12 +56,34 @@ public:
   Error commit(StringRef Filename);
 
   Expected<uint32_t> getNamedStreamIndex(StringRef Name) const;
-  Error addNamedStream(StringRef Name, uint32_t Size);
+  Error addNamedStream(StringRef Name, StringRef Data);
+  void addInjectedSource(StringRef Name, std::unique_ptr<MemoryBuffer> Buffer);
 
 private:
+  struct InjectedSourceDescriptor {
+    // The full name of the stream that contains the contents of this injected
+    // source.  This is built as a concatenation of the literal "/src/files"
+    // plus the "vname".
+    std::string StreamName;
+
+    // The exact name of the file name as specified by the user.
+    uint32_t NameIndex;
+
+    // The string table index of the "vname" of the file.  As far as we
+    // understand, this is the same as the name, except it is lowercased and
+    // forward slashes are converted to backslashes.
+    uint32_t VNameIndex;
+    std::unique_ptr<MemoryBuffer> Content;
+  };
+
   Expected<msf::MSFLayout> finalizeMsfLayout();
+  Expected<uint32_t> allocateNamedStream(StringRef Name, uint32_t Size);
 
   void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout);
+  void commitInjectedSources(WritableBinaryStream &MsfBuffer,
+                             const msf::MSFLayout &Layout);
+  void commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
+                            const msf::MSFLayout &Layout);
 
   BumpPtrAllocator &Allocator;
 
@@ -71,7 +95,13 @@ private:
   std::unique_ptr<TpiStreamBuilder> Ipi;
 
   PDBStringTableBuilder Strings;
+  StringTableHashTraits InjectedSourceHashTraits;
+  HashTable<SrcHeaderBlockEntry, StringTableHashTraits> InjectedSourceTable;
+
+  SmallVector<InjectedSourceDescriptor, 2> InjectedSources;
+
   NamedStreamMap NamedStreams;
+  DenseMap<uint32_t, std::string> NamedStreamData;
 };
 }
 }

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h Tue Mar 20 10:06:39 2018
@@ -31,6 +31,16 @@ struct MSFLayout;
 namespace pdb {
 
 class PDBFileBuilder;
+class PDBStringTableBuilder;
+
+struct StringTableHashTraits {
+  PDBStringTableBuilder *Table;
+
+  explicit StringTableHashTraits(PDBStringTableBuilder &Table);
+  uint32_t hashLookupKey(StringRef S) const;
+  StringRef storageKeyToLookupKey(uint32_t Offset) const;
+  uint32_t lookupKeyToStorageKey(StringRef S);
+};
 
 class PDBStringTableBuilder {
 public:
@@ -38,6 +48,9 @@ public:
   // Returns the ID for S.
   uint32_t insert(StringRef S);
 
+  uint32_t getIdForString(StringRef S) const;
+  StringRef getStringForId(uint32_t Id) const;
+
   uint32_t calculateSerializedSize() const;
   Error commit(BinaryStreamWriter &Writer) const;
 

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawConstants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawConstants.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawConstants.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawConstants.h Tue Mar 20 10:06:39 2018
@@ -32,6 +32,8 @@ enum PdbRaw_ImplVer : uint32_t {
   PdbImplVC140 = 20140508,
 };
 
+enum class PdbRaw_SrcHeaderBlockVer : uint32_t { SrcVerOne = 19980827 };
+
 enum class PdbRaw_FeatureSig : uint32_t {
   VC110 = PdbImplVC110,
   VC140 = PdbImplVC140,

Modified: llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawTypes.h Tue Mar 20 10:06:39 2018
@@ -328,6 +328,34 @@ struct PDBStringTableHeader {
 
 const uint32_t PDBStringTableSignature = 0xEFFEEFFE;
 
+/// The header preceding the /src/headerblock stream.
+struct SrcHeaderBlockHeader {
+  support::ulittle32_t Version; // PdbRaw_SrcHeaderBlockVer enumeration.
+  support::ulittle32_t Size;    // Size of entire stream.
+  uint64_t FileTime;            // Time stamp (Windows FILETIME format).
+  support::ulittle32_t Age;     // Age
+  uint8_t Padding[44];          // Pad to 64 bytes.
+};
+static_assert(sizeof(SrcHeaderBlockHeader) == 64, "Incorrect struct size!");
+
+/// A single file record entry within the /src/headerblock stream.
+struct SrcHeaderBlockEntry {
+  support::ulittle32_t Size;     // Record Length.
+  support::ulittle32_t Version;  // PdbRaw_SrcHeaderBlockVer enumeration.
+  support::ulittle32_t CRC;      // CRC of the original file contents.
+  support::ulittle32_t FileSize; // Size of original source file.
+  support::ulittle32_t FileNI;   // String table index of file name.
+  support::ulittle32_t ObjNI;    // String table index of object name.
+  support::ulittle32_t VFileNI;  // String table index of virtual file name.
+  uint8_t Compression;           // PDB_SourceCompression enumeration.
+  uint8_t IsVirtual;             // Is this a virtual file (injected)?
+  short Padding;                 // Pad to 4 bytes.
+  char Reserved[8];
+};
+
+constexpr int I = sizeof(SrcHeaderBlockEntry);
+static_assert(sizeof(SrcHeaderBlockEntry) == 40, "Incorrect struct size!");
+
 } // namespace pdb
 } // namespace llvm
 

Modified: llvm/trunk/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/DebugChecksumsSubsection.cpp Tue Mar 20 10:06:39 2018
@@ -109,7 +109,7 @@ Error DebugChecksumsSubsection::commit(B
 }
 
 uint32_t DebugChecksumsSubsection::mapChecksumOffset(StringRef FileName) const {
-  uint32_t Offset = Strings.getStringId(FileName);
+  uint32_t Offset = Strings.getIdForString(FileName);
   auto Iter = OffsetMap.find(Offset);
   assert(Iter != OffsetMap.end());
   return Iter->second;

Modified: llvm/trunk/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/DebugCrossImpSubsection.cpp Tue Mar 20 10:06:39 2018
@@ -80,13 +80,13 @@ Error DebugCrossModuleImportsSubsection:
     Ids.push_back(&M);
 
   std::sort(Ids.begin(), Ids.end(), [this](const T &L1, const T &L2) {
-    return Strings.getStringId(L1->getKey()) <
-           Strings.getStringId(L2->getKey());
+    return Strings.getIdForString(L1->getKey()) <
+           Strings.getIdForString(L2->getKey());
   });
 
   for (const auto &Item : Ids) {
     CrossModuleImport Imp;
-    Imp.ModuleNameOffset = Strings.getStringId(Item->getKey());
+    Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey());
     Imp.Count = Item->getValue().size();
     if (auto EC = Writer.writeObject(Imp))
       return EC;

Modified: llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp Tue Mar 20 10:06:39 2018
@@ -46,12 +46,15 @@ DebugStringTableSubsection::DebugStringT
     : DebugSubsection(DebugSubsectionKind::StringTable) {}
 
 uint32_t DebugStringTableSubsection::insert(StringRef S) {
-  auto P = Strings.insert({S, StringSize});
+  auto P = StringToId.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)
+  // the string table size and insert it into the reverse lookup.
+  if (P.second) {
+    IdToString.insert({P.first->getValue(), P.first->getKey()});
     StringSize += S.size() + 1; // +1 for '\0'
+  }
+
   return P.first->second;
 }
 
@@ -67,7 +70,7 @@ Error DebugStringTableSubsection::commit
   if (auto EC = Writer.writeCString(StringRef()))
     return EC;
 
-  for (auto &Pair : Strings) {
+  for (auto &Pair : StringToId) {
     StringRef S = Pair.getKey();
     uint32_t Offset = Begin + Pair.getValue();
     Writer.setOffset(Offset);
@@ -81,10 +84,16 @@ Error DebugStringTableSubsection::commit
   return Error::success();
 }
 
-uint32_t DebugStringTableSubsection::size() const { return Strings.size(); }
+uint32_t DebugStringTableSubsection::size() const { return StringToId.size(); }
+
+uint32_t DebugStringTableSubsection::getIdForString(StringRef S) const {
+  auto Iter = StringToId.find(S);
+  assert(Iter != StringToId.end());
+  return Iter->second;
+}
 
-uint32_t DebugStringTableSubsection::getStringId(StringRef S) const {
-  auto Iter = Strings.find(S);
-  assert(Iter != Strings.end());
+StringRef DebugStringTableSubsection::getStringForId(uint32_t Id) const {
+  auto Iter = IdToString.find(Id);
+  assert(Iter != IdToString.end());
   return Iter->second;
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/DIA/DIAEnumInjectedSources.cpp Tue Mar 20 10:06:39 2018
@@ -30,8 +30,7 @@ DIAEnumInjectedSources::getChildAtIndex(
   if (S_OK != Enumerator->Item(Index, &Item))
     return nullptr;
 
-  return std::unique_ptr<IPDBInjectedSource>(
-      new DIAInjectedSource(Session, Item));
+  return std::unique_ptr<IPDBInjectedSource>(new DIAInjectedSource(Item));
 }
 
 std::unique_ptr<IPDBInjectedSource> DIAEnumInjectedSources::getNext() {
@@ -40,8 +39,7 @@ std::unique_ptr<IPDBInjectedSource> DIAE
   if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
     return nullptr;
 
-  return std::unique_ptr<IPDBInjectedSource>(
-      new DIAInjectedSource(Session, Item));
+  return std::unique_ptr<IPDBInjectedSource>(new DIAInjectedSource(Item));
 }
 
 void DIAEnumInjectedSources::reset() { Enumerator->Reset(); }

Modified: llvm/trunk/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/DIA/DIAInjectedSource.cpp Tue Mar 20 10:06:39 2018
@@ -16,9 +16,8 @@
 using namespace llvm;
 using namespace llvm::pdb;
 
-DIAInjectedSource::DIAInjectedSource(const DIASession &Session,
-                                     CComPtr<IDiaInjectedSource> DiaSourceFile)
-    : Session(Session), SourceFile(DiaSourceFile) {}
+DIAInjectedSource::DIAInjectedSource(CComPtr<IDiaInjectedSource> DiaSourceFile)
+    : SourceFile(DiaSourceFile) {}
 
 uint32_t DIAInjectedSource::getCrc32() const {
   DWORD Crc;

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/InfoStreamBuilder.cpp Tue Mar 20 10:06:39 2018
@@ -73,5 +73,6 @@ Error InfoStreamBuilder::commit(const ms
     if (auto EC = Writer.writeEnum(E))
       return EC;
   }
+  assert(Writer.bytesRemaining() == 0);
   return Error::success();
 }

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp Tue Mar 20 10:06:39 2018
@@ -24,6 +24,8 @@
 #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
 #include "llvm/Support/BinaryStream.h"
 #include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/JamCRC.h"
+#include "llvm/Support/Path.h"
 
 using namespace llvm;
 using namespace llvm::codeview;
@@ -32,7 +34,8 @@ using namespace llvm::pdb;
 using namespace llvm::support;
 
 PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
-    : Allocator(Allocator) {}
+    : Allocator(Allocator), InjectedSourceHashTraits(Strings),
+      InjectedSourceTable(2, InjectedSourceHashTraits) {}
 
 PDBFileBuilder::~PDBFileBuilder() {}
 
@@ -80,14 +83,45 @@ GSIStreamBuilder &PDBFileBuilder::getGsi
   return *Gsi;
 }
 
-Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
+Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name,
+                                                       uint32_t Size) {
   auto ExpectedStream = Msf->addStream(Size);
-  if (!ExpectedStream)
-    return ExpectedStream.takeError();
-  NamedStreams.set(Name, *ExpectedStream);
+  if (ExpectedStream)
+    NamedStreams.set(Name, *ExpectedStream);
+  return ExpectedStream;
+}
+
+Error PDBFileBuilder::addNamedStream(StringRef Name, StringRef Data) {
+  Expected<uint32_t> ExpectedIndex = allocateNamedStream(Name, Data.size());
+  if (!ExpectedIndex)
+    return ExpectedIndex.takeError();
+  assert(NamedStreamData.count(*ExpectedIndex) == 0);
+  NamedStreamData[*ExpectedIndex] = Data;
   return Error::success();
 }
 
+void PDBFileBuilder::addInjectedSource(StringRef Name,
+                                       std::unique_ptr<MemoryBuffer> Buffer) {
+  // Stream names must be exact matches, since they get looked up in a hash
+  // table and the hash value is dependent on the exact contents of the string.
+  // link.exe lowercases a path and converts / to \, so we must do the same.
+  SmallString<64> VName;
+  sys::path::native(Name.lower(), VName);
+
+  uint32_t NI = getStringTableBuilder().insert(Name);
+  uint32_t VNI = getStringTableBuilder().insert(VName);
+
+  InjectedSourceDescriptor Desc;
+  Desc.Content = std::move(Buffer);
+  Desc.NameIndex = NI;
+  Desc.VNameIndex = VNI;
+  Desc.StreamName = "/src/files/";
+
+  Desc.StreamName += VName;
+
+  InjectedSources.push_back(std::move(Desc));
+}
+
 Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
 
   if (Ipi && Ipi->getRecordCount() > 0) {
@@ -101,15 +135,13 @@ Expected<msf::MSFLayout> PDBFileBuilder:
 
   uint32_t StringsLen = Strings.calculateSerializedSize();
 
-  if (auto EC = addNamedStream("/names", StringsLen))
-    return std::move(EC);
-  if (auto EC = addNamedStream("/LinkInfo", 0))
-    return std::move(EC);
+  Expected<uint32_t> SN = allocateNamedStream("/names", StringsLen);
+  if (!SN)
+    return SN.takeError();
+  SN = allocateNamedStream("/LinkInfo", 0);
+  if (!SN)
+    return SN.takeError();
 
-  if (Info) {
-    if (auto EC = Info->finalizeMsfLayout())
-      return std::move(EC);
-  }
   if (Dbi) {
     if (auto EC = Dbi->finalizeMsfLayout())
       return std::move(EC);
@@ -132,6 +164,46 @@ Expected<msf::MSFLayout> PDBFileBuilder:
     }
   }
 
+  if (!InjectedSources.empty()) {
+    for (const auto &IS : InjectedSources) {
+      JamCRC CRC(0);
+      CRC.update(makeArrayRef(IS.Content->getBufferStart(),
+                              IS.Content->getBufferSize()));
+
+      SrcHeaderBlockEntry Entry;
+      ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry));
+      Entry.Size = sizeof(SrcHeaderBlockEntry);
+      Entry.FileSize = IS.Content->getBufferSize();
+      Entry.FileNI = IS.NameIndex;
+      Entry.VFileNI = IS.VNameIndex;
+      Entry.IsVirtual = 0;
+      Entry.Version =
+          static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+      Entry.CRC = CRC.getCRC();
+      StringRef VName = getStringTableBuilder().getStringForId(IS.VNameIndex);
+      InjectedSourceTable.set_as(VName, std::move(Entry));
+    }
+
+    uint32_t SrcHeaderBlockSize =
+        sizeof(SrcHeaderBlockHeader) +
+        InjectedSourceTable.calculateSerializedLength();
+    SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
+    if (!SN)
+      return SN.takeError();
+    for (const auto &IS : InjectedSources) {
+      SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize());
+      if (!SN)
+        return SN.takeError();
+    }
+  }
+
+  // Do this last, since it relies on the named stream map being complete, and
+  // that can be updated by previous steps in the finalization.
+  if (Info) {
+    if (auto EC = Info->finalizeMsfLayout())
+      return std::move(EC);
+  }
+
   return Msf->build();
 }
 
@@ -167,6 +239,45 @@ void PDBFileBuilder::commitFpm(WritableB
   assert(FpmWriter.bytesRemaining() == 0);
 }
 
+void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
+                                          const msf::MSFLayout &Layout) {
+  assert(!InjectedSourceTable.empty());
+
+  uint32_t SN = cantFail(getNamedStreamIndex("/src/headerblock"));
+  auto Stream = WritableMappedBlockStream::createIndexedStream(
+      Layout, MsfBuffer, SN, Allocator);
+  BinaryStreamWriter Writer(*Stream);
+
+  SrcHeaderBlockHeader Header;
+  ::memset(&Header, 0, sizeof(Header));
+  Header.Version = static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
+  Header.Size = Writer.bytesRemaining();
+
+  cantFail(Writer.writeObject(Header));
+  cantFail(InjectedSourceTable.commit(Writer));
+
+  assert(Writer.bytesRemaining() == 0);
+}
+
+void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
+                                           const msf::MSFLayout &Layout) {
+  if (InjectedSourceTable.empty())
+    return;
+
+  commitSrcHeaderBlock(MsfBuffer, Layout);
+
+  for (const auto &IS : InjectedSources) {
+    uint32_t SN = cantFail(getNamedStreamIndex(IS.StreamName));
+
+    auto SourceStream = WritableMappedBlockStream::createIndexedStream(
+        Layout, MsfBuffer, SN, Allocator);
+    BinaryStreamWriter SourceWriter(*SourceStream);
+    assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize());
+    cantFail(SourceWriter.writeBytes(
+        arrayRefFromStringRef(IS.Content->getBuffer())));
+  }
+}
+
 Error PDBFileBuilder::commit(StringRef Filename) {
   assert(!Filename.empty());
   auto ExpectedLayout = finalizeMsfLayout();
@@ -219,6 +330,17 @@ Error PDBFileBuilder::commit(StringRef F
   if (auto EC = Strings.commit(NSWriter))
     return EC;
 
+  for (const auto &NSE : NamedStreamData) {
+    if (NSE.second.empty())
+      continue;
+
+    auto NS = WritableMappedBlockStream::createIndexedStream(
+        Layout, Buffer, NSE.first, Allocator);
+    BinaryStreamWriter NSW(*NS);
+    if (auto EC = NSW.writeBytes(arrayRefFromStringRef(NSE.second)))
+      return EC;
+  }
+
   if (Info) {
     if (auto EC = Info->commit(Layout, Buffer))
       return EC;
@@ -251,6 +373,8 @@ Error PDBFileBuilder::commit(StringRef F
   InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>(
       FOB->getBufferStart() + InfoStreamFileOffset);
 
+  commitInjectedSources(Buffer, Layout);
+
   // Set the build id at the very end, after every other byte of the PDB
   // has been written.
   // FIXME: Use a hash of the PDB rather than time(nullptr) for the signature.

Modified: llvm/trunk/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp Tue Mar 20 10:06:39 2018
@@ -21,10 +21,33 @@ using namespace llvm::support;
 using namespace llvm::support::endian;
 using namespace llvm::pdb;
 
+StringTableHashTraits::StringTableHashTraits(PDBStringTableBuilder &Table)
+    : Table(&Table) {}
+
+uint32_t StringTableHashTraits::hashLookupKey(StringRef S) const {
+  return Table->getIdForString(S);
+}
+
+StringRef StringTableHashTraits::storageKeyToLookupKey(uint32_t Offset) const {
+  return Table->getStringForId(Offset);
+}
+
+uint32_t StringTableHashTraits::lookupKeyToStorageKey(StringRef S) {
+  return Table->insert(S);
+}
+
 uint32_t PDBStringTableBuilder::insert(StringRef S) {
   return Strings.insert(S);
 }
 
+uint32_t PDBStringTableBuilder::getIdForString(StringRef S) const {
+  return Strings.getIdForString(S);
+}
+
+StringRef PDBStringTableBuilder::getStringForId(uint32_t Id) const {
+  return Strings.getStringForId(Id);
+}
+
 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

Modified: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp Tue Mar 20 10:06:39 2018
@@ -90,6 +90,12 @@ Error DumpOutputStyle::dump() {
     P.NewLine();
   }
 
+  if (opts::dump::DumpNamedStreams) {
+    if (auto EC = dumpNamedStreams())
+      return EC;
+    P.NewLine();
+  }
+
   if (opts::dump::DumpStringTable) {
     if (auto EC = dumpStringTable())
       return EC;
@@ -909,6 +915,29 @@ Error DumpOutputStyle::dumpStringTableFr
   return Error::success();
 }
 
+Error DumpOutputStyle::dumpNamedStreams() {
+  printHeader(P, "Named Streams");
+  AutoIndent Indent(P, 2);
+
+  if (File.isObj()) {
+    P.formatLine("Dumping Named Streams is only supported for PDB files.");
+    return Error::success();
+  }
+  ExitOnError Err("Invalid PDB File: ");
+
+  auto &IS = Err(File.pdb().getPDBInfoStream());
+  const NamedStreamMap &NS = IS.getNamedStreams();
+  for (const auto &Entry : NS.entries()) {
+    P.printLine(Entry.getKey());
+    AutoIndent Indent2(P, 2);
+    P.formatLine("Index: {0}", Entry.getValue());
+    P.formatLine("Size in bytes: {0}",
+                 File.pdb().getStreamByteSize(Entry.getValue()));
+  }
+
+  return Error::success();
+}
+
 Error DumpOutputStyle::dumpStringTable() {
   printHeader(P, "String Table");
 

Modified: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h (original)
+++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h Tue Mar 20 10:06:39 2018
@@ -74,6 +74,7 @@ private:
   Error dumpStreamSummary();
   Error dumpSymbolStats();
   Error dumpUdtStats();
+  Error dumpNamedStreams();
   Error dumpStringTable();
   Error dumpStringTableFromPdb();
   Error dumpStringTableFromObj();

Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp (original)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp Tue Mar 20 10:06:39 2018
@@ -534,6 +534,10 @@ cl::opt<bool> JustMyCode("jmc", cl::Opti
                          cl::cat(FileOptions), cl::sub(DumpSubcommand));
 
 // MISCELLANEOUS OPTIONS
+cl::opt<bool> DumpNamedStreams("named-streams",
+                               cl::desc("dump PDB named stream table"),
+                               cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+
 cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
                               cl::cat(MiscOptions), cl::sub(DumpSubcommand));
 

Modified: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h?rev=328002&r1=328001&r2=328002&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h (original)
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h Tue Mar 20 10:06:39 2018
@@ -142,6 +142,7 @@ extern llvm::cl::opt<bool> DumpLines;
 extern llvm::cl::opt<bool> DumpInlineeLines;
 extern llvm::cl::opt<bool> DumpXmi;
 extern llvm::cl::opt<bool> DumpXme;
+extern llvm::cl::opt<bool> DumpNamedStreams;
 extern llvm::cl::opt<bool> DumpStringTable;
 extern llvm::cl::opt<bool> DumpTypes;
 extern llvm::cl::opt<bool> DumpTypeData;




More information about the llvm-commits mailing list