[llvm-branch-commits] [llvm] [PDB][llvm-pdbutil] Add DXContainer support for yaml2pdb (PR #198365)

Ilia Kuklin via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue May 19 06:04:52 PDT 2026


https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/198365

>From cbd7709d009bd3dca262da8a88b5dea845420049 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Mon, 18 May 2026 21:21:04 +0500
Subject: [PATCH 1/3] [PDB][llvm-pdbutil] Add DXContainer support for yaml2pdb

---
 .../DebugInfo/PDB/Native/PDBFileBuilder.h     |  4 +-
 .../DebugInfo/PDB/Native/PDBFileBuilder.cpp   | 68 +++++++++++++------
 llvm/test/tools/llvm-pdbutil/dxcontainer.test |  2 -
 llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp      | 45 +++++++++---
 4 files changed, 85 insertions(+), 34 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
index abb1b623c5a8a..6093a63dddfc6 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
@@ -53,6 +53,7 @@ class PDBFileBuilder {
   LLVM_ABI TpiStreamBuilder &getIpiBuilder();
   LLVM_ABI PDBStringTableBuilder &getStringTableBuilder();
   LLVM_ABI GSIStreamBuilder &getGsiBuilder();
+  LLVM_ABI std::unique_ptr<SmallVector<char>> &getDXContainerData();
 
   // If HashPDBContentsToGUID is true on the InfoStreamBuilder, Guid is filled
   // with the computed PDB GUID on return.
@@ -96,8 +97,9 @@ class PDBFileBuilder {
   std::unique_ptr<GSIStreamBuilder> Gsi;
   std::unique_ptr<TpiStreamBuilder> Tpi;
   std::unique_ptr<TpiStreamBuilder> Ipi;
+  std::unique_ptr<SmallVector<char>> Dxc;
 
-  PDBStringTableBuilder Strings;
+  std::unique_ptr<PDBStringTableBuilder> Strings;
   StringTableHashTraits InjectedSourceHashTraits;
   HashTable<SrcHeaderBlockEntry> InjectedSourceTable;
 
diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index 77fa9d38822ae..ed6725aa64739 100644
--- a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -40,7 +40,7 @@ class WritableBinaryStream;
 }
 
 PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
-    : Allocator(Allocator), InjectedSourceHashTraits(Strings),
+    : Allocator(Allocator), InjectedSourceHashTraits(*Strings),
       InjectedSourceTable(2) {}
 
 PDBFileBuilder::~PDBFileBuilder() = default;
@@ -80,7 +80,9 @@ TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
 }
 
 PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
-  return Strings;
+  if (!Strings)
+    Strings = std::make_unique<PDBStringTableBuilder>();
+  return *Strings;
 }
 
 GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
@@ -89,6 +91,12 @@ GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
   return *Gsi;
 }
 
+std::unique_ptr<SmallVector<char>> &PDBFileBuilder::getDXContainerData() {
+  if (!Dxc)
+    Dxc = std::make_unique<SmallVector<char>>();
+  return Dxc;
+}
+
 Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name,
                                                        uint32_t Size) {
   auto ExpectedStream = Msf->addStream(Size);
@@ -140,11 +148,14 @@ Error PDBFileBuilder::finalizeMsfLayout() {
     Info.addFeature(PdbRaw_FeatureSig::VC140);
   }
 
-  uint32_t StringsLen = Strings.calculateSerializedSize();
-
-  Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0);
-  if (!SN)
-    return SN.takeError();
+  if (Dxc) {
+    if (auto EC = Msf->setStreamSize(StreamDXContainer, Dxc->size()))
+      return EC;
+  } else {
+    Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0);
+    if (!SN)
+      return SN.takeError();
+  }
 
   if (Gsi) {
     if (auto EC = Gsi->finalizeMsfLayout())
@@ -163,10 +174,12 @@ Error PDBFileBuilder::finalizeMsfLayout() {
     if (auto EC = Dbi->finalizeMsfLayout())
       return EC;
   }
-  SN = allocateNamedStream("/names", StringsLen);
-  if (!SN)
-    return SN.takeError();
-
+  if (Strings) {
+    uint32_t StringsLen = Strings->calculateSerializedSize();
+    Expected<uint32_t> SN = allocateNamedStream("/names", StringsLen);
+    if (!SN)
+      return SN.takeError();
+  }
   if (Ipi) {
     if (auto EC = Ipi->finalizeMsfLayout())
       return EC;
@@ -203,7 +216,8 @@ Error PDBFileBuilder::finalizeMsfLayout() {
     uint32_t SrcHeaderBlockSize =
         sizeof(SrcHeaderBlockHeader) +
         InjectedSourceTable.calculateSerializedLength();
-    SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
+    Expected<uint32_t> SN =
+        allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
     if (!SN)
       return SN.takeError();
     for (const auto &IS : InjectedSources) {
@@ -282,16 +296,17 @@ Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
     return ExpectedMsfBuffer.takeError();
   FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
 
-  auto ExpectedSN = getNamedStreamIndex("/names");
-  if (!ExpectedSN)
-    return ExpectedSN.takeError();
-
-  auto NS = WritableMappedBlockStream::createIndexedStream(
-      Layout, Buffer, *ExpectedSN, Allocator);
-  BinaryStreamWriter NSWriter(*NS);
-  if (auto EC = Strings.commit(NSWriter))
-    return EC;
+  if (Strings) {
+    auto ExpectedSN = getNamedStreamIndex("/names");
+    if (!ExpectedSN)
+      return ExpectedSN.takeError();
 
+    auto NS = WritableMappedBlockStream::createIndexedStream(
+        Layout, Buffer, *ExpectedSN, Allocator);
+    BinaryStreamWriter NSWriter(*NS);
+    if (auto EC = Strings->commit(NSWriter))
+      return EC;
+  }
   {
     llvm::TimeTraceScope timeScope("Named stream data");
     for (const auto &NSE : NamedStreamData) {
@@ -331,6 +346,17 @@ Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
       return EC;
   }
 
+  if (Dxc) {
+    llvm::TimeTraceScope timeScope("DXContainer stream");
+    auto DxcS = WritableMappedBlockStream::createIndexedStream(
+        Layout, Buffer, StreamDXContainer, Allocator);
+    BinaryStreamWriter Writer(*DxcS);
+    llvm::ArrayRef<uint8_t> DataRef(reinterpret_cast<uint8_t *>(Dxc->data()),
+                                    Dxc->size());
+    if (auto EC = Writer.writeBytes(DataRef))
+      return EC;
+  }
+
   auto InfoStreamBlocks = Layout.StreamMap[StreamPDB];
   assert(!InfoStreamBlocks.empty());
   uint64_t InfoStreamFileOffset =
diff --git a/llvm/test/tools/llvm-pdbutil/dxcontainer.test b/llvm/test/tools/llvm-pdbutil/dxcontainer.test
index 721f7261a10f8..0be2637a1707f 100644
--- a/llvm/test/tools/llvm-pdbutil/dxcontainer.test
+++ b/llvm/test/tools/llvm-pdbutil/dxcontainer.test
@@ -1,6 +1,4 @@
 ## Check DXContainer support within a PDB file.
-## Disable the test until yaml2pdb and pdb2yaml are implemented.
-# UNSUPPORTED: target={{.*}}
 
 # RUN: llvm-pdbutil yaml2pdb %s --pdb=%t.pdb
 # RUN: llvm-pdbutil pdb2yaml --all %t.pdb > %t.yaml
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index 3de59b411988a..b9267fb496c53 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -76,6 +76,7 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/ObjectYAML/yaml2obj.h"
 #include "llvm/Support/BinaryByteStream.h"
 #include "llvm/Support/COM.h"
 #include "llvm/Support/CommandLine.h"
@@ -817,19 +818,13 @@ static void yamlToPdb(StringRef Path) {
   for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
     ExitOnErr(Builder.getMsfBuilder().addStream(0));
 
-  StringsAndChecksums Strings;
-  Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
-
-  if (YamlObj.StringTable) {
-    for (auto S : *YamlObj.StringTable)
-      Strings.strings()->insert(S);
+  auto &Dxc = YamlObj.DXContainerStream;
+  if (Dxc) {
+    // If there is a DXContainer, add add it as a stream #5.
+    ExitOnErr(Builder.getMsfBuilder().addStream(0));
   }
 
   pdb::yaml::PdbInfoStream DefaultInfoStream;
-  pdb::yaml::PdbDbiStream DefaultDbiStream;
-  pdb::yaml::PdbTpiStream DefaultTpiStream;
-  pdb::yaml::PdbTpiStream DefaultIpiStream;
-
   const auto &Info = YamlObj.PdbStream.value_or(DefaultInfoStream);
 
   auto &InfoBuilder = Builder.getInfoBuilder();
@@ -840,6 +835,36 @@ static void yamlToPdb(StringRef Path) {
   for (auto F : Info.Features)
     InfoBuilder.addFeature(F);
 
+  if (Dxc) {
+    auto &Data = Builder.getDXContainerData();
+    llvm::raw_svector_ostream DataStream(*Data);
+    std::string ErrorMsg;
+    llvm::yaml::yaml2dxcontainer(
+        Dxc->DXC, DataStream, [&ErrorMsg](const Twine &Msg) {
+          ErrorMsg = (Twine("DXContainer error: ") + Msg).str();
+        });
+    if (!ErrorMsg.empty())
+      ExitOnErr(createStringError(ErrorMsg));
+
+    codeview::GUID IgnoredOutGuid;
+    ExitOnErr(
+        Builder.commit(opts::yaml2pdb::YamlPdbOutputFile, &IgnoredOutGuid));
+    // Leave all other streams empty if there is a DXContainer.
+    return;
+  }
+
+  StringsAndChecksums Strings;
+  Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
+
+  if (YamlObj.StringTable) {
+    for (auto S : *YamlObj.StringTable)
+      Strings.strings()->insert(S);
+  }
+
+  pdb::yaml::PdbDbiStream DefaultDbiStream;
+  pdb::yaml::PdbTpiStream DefaultTpiStream;
+  pdb::yaml::PdbTpiStream DefaultIpiStream;
+
   const auto &Dbi = YamlObj.DbiStream.value_or(DefaultDbiStream);
   auto &DbiBuilder = Builder.getDbiBuilder();
   DbiBuilder.setAge(Dbi.Age);

>From 0c18098815ab4ba8c79d3a9ece95ba49f3d2c5dc Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 19 May 2026 00:10:42 +0500
Subject: [PATCH 2/3] Initialize PDBFileBuilder::Strings

---
 llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index ed6725aa64739..9bd23f5def326 100644
--- a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -40,8 +40,8 @@ class WritableBinaryStream;
 }
 
 PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
-    : Allocator(Allocator), InjectedSourceHashTraits(*Strings),
-      InjectedSourceTable(2) {}
+    : Allocator(Allocator), Strings(std::make_unique<PDBStringTableBuilder>()),
+      InjectedSourceHashTraits(*Strings), InjectedSourceTable(2) {}
 
 PDBFileBuilder::~PDBFileBuilder() = default;
 

>From 4a4155ee4238d9c4856ba351810fce42b6498112 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 19 May 2026 18:02:45 +0500
Subject: [PATCH 3/3] Initialize InjectedSourceHashTraits along with Strings

---
 .../llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h      | 1 +
 llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp           | 7 ++++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
index 4ef583a227c0c..8deb065c4ef71 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
@@ -35,6 +35,7 @@ class PDBStringTableBuilder;
 struct StringTableHashTraits {
   PDBStringTableBuilder *Table;
 
+  LLVM_ABI StringTableHashTraits() = default;
   LLVM_ABI explicit StringTableHashTraits(PDBStringTableBuilder &Table);
   LLVM_ABI uint32_t hashLookupKey(StringRef S) const;
   LLVM_ABI StringRef storageKeyToLookupKey(uint32_t Offset) const;
diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index 9bd23f5def326..14c5e22115415 100644
--- a/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -40,8 +40,7 @@ class WritableBinaryStream;
 }
 
 PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
-    : Allocator(Allocator), Strings(std::make_unique<PDBStringTableBuilder>()),
-      InjectedSourceHashTraits(*Strings), InjectedSourceTable(2) {}
+    : Allocator(Allocator), InjectedSourceTable(2) {}
 
 PDBFileBuilder::~PDBFileBuilder() = default;
 
@@ -80,8 +79,10 @@ TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
 }
 
 PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
-  if (!Strings)
+  if (!Strings) {
     Strings = std::make_unique<PDBStringTableBuilder>();
+    InjectedSourceHashTraits = StringTableHashTraits(*Strings);
+  }
   return *Strings;
 }
 



More information about the llvm-branch-commits mailing list