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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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; } _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
