[llvm] 93d256b - [llvm-pdbutil] Hash type records in yaml2pdb (#187593)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Mar 21 09:38:58 PDT 2026
Author: Nerixyz
Date: 2026-03-21T17:38:52+01:00
New Revision: 93d256b076b12bf30e546910d9ae473ec93146c0
URL: https://github.com/llvm/llvm-project/commit/93d256b076b12bf30e546910d9ae473ec93146c0
DIFF: https://github.com/llvm/llvm-project/commit/93d256b076b12bf30e546910d9ae473ec93146c0.diff
LOG: [llvm-pdbutil] Hash type records in yaml2pdb (#187593)
The TPI and IPI streams didn't include a hash map for the generated
types, because the types never got hashes. A hash map is necessary to
resolve forward references when dumping the PDB (checks for
`TpiStream::supportsTypeLookup` which checks the hash map).
With this PR, the hashes are generated. There's no good test that we do
this for the IPI stream as well, because it doesn't have forward
references.
Added:
llvm/test/tools/llvm-pdbutil/Inputs/forward-refs1.yaml
llvm/test/tools/llvm-pdbutil/Inputs/forward-refs2.yaml
llvm/test/tools/llvm-pdbutil/merged-forward-refs.test
Modified:
llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
llvm/test/DebugInfo/PDB/pdbdump-mergetypes.test
llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
index 255abb0e3e8d4..85d47a9229d3a 100644
--- a/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
+++ b/llvm/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
@@ -46,8 +46,7 @@ class TpiStreamBuilder {
TpiStreamBuilder &operator=(const TpiStreamBuilder &) = delete;
LLVM_ABI void setVersionHeader(PdbRaw_TpiVer Version);
- LLVM_ABI void addTypeRecord(ArrayRef<uint8_t> Type,
- std::optional<uint32_t> Hash);
+ LLVM_ABI void addTypeRecord(ArrayRef<uint8_t> Type, uint32_t Hash);
LLVM_ABI void addTypeRecords(ArrayRef<uint8_t> Types,
ArrayRef<uint16_t> Sizes,
ArrayRef<uint32_t> Hashes);
diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
index a33f147ffd051..9e95a75257396 100644
--- a/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp
@@ -54,8 +54,7 @@ void TpiStreamBuilder::updateTypeIndexOffsets(ArrayRef<uint16_t> Sizes) {
}
}
-void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record,
- std::optional<uint32_t> Hash) {
+void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record, uint32_t Hash) {
assert(((Record.size() & 3) == 0) &&
"The type record's size is not a multiple of 4 bytes which will "
"cause misalignment in the output TPI stream!");
@@ -64,9 +63,7 @@ void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record,
updateTypeIndexOffsets(ArrayRef(&OneSize, 1));
TypeRecBuffers.push_back(Record);
- // FIXME: Require it.
- if (Hash)
- TypeHashes.push_back(*Hash);
+ TypeHashes.push_back(Hash);
}
void TpiStreamBuilder::addTypeRecords(ArrayRef<uint8_t> Types,
diff --git a/llvm/test/DebugInfo/PDB/pdbdump-mergetypes.test b/llvm/test/DebugInfo/PDB/pdbdump-mergetypes.test
index 60cf4a172aa2a..04ae0755566b7 100644
--- a/llvm/test/DebugInfo/PDB/pdbdump-mergetypes.test
+++ b/llvm/test/DebugInfo/PDB/pdbdump-mergetypes.test
@@ -14,7 +14,7 @@ MERGED-NEXT: referent = 0x0076 (__int64), mode = pointer, opts = None
MERGED-NEXT: 0x1002 | LF_STRUCTURE [size = 48] `OnlyInMerge1`
MERGED-NEXT: unique name: `OnlyInMerge1`
MERGED-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
-MERGED-NEXT: options: forward ref | has unique name
+MERGED-NEXT: options: forward ref (= 0x1002) | has unique name
MERGED-NEXT: 0x1003 | LF_POINTER [size = 12]
MERGED-NEXT: referent = 0x1000, mode = pointer, opts = None, kind = ptr32
MERGED-NEXT: 0x1004 | LF_POINTER [size = 12]
@@ -31,4 +31,4 @@ MERGED-NEXT: calling conv = cdecl, options = None
MERGED-NEXT: 0x1008 | LF_STRUCTURE [size = 48] `OnlyInMerge2`
MERGED-NEXT: unique name: `OnlyInMerge2`
MERGED-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
-MERGED-NEXT: options: forward ref | has unique name
+MERGED-NEXT: options: forward ref (= 0x1008) | has unique name
diff --git a/llvm/test/tools/llvm-pdbutil/Inputs/forward-refs1.yaml b/llvm/test/tools/llvm-pdbutil/Inputs/forward-refs1.yaml
new file mode 100644
index 0000000000000..f403485d529bf
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbutil/Inputs/forward-refs1.yaml
@@ -0,0 +1,63 @@
+---
+TpiStream:
+ Version: VC80
+ Records:
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ ]
+ - Kind: LF_PROCEDURE
+ Procedure:
+ ReturnType: 116
+ CallConv: NearC
+ Options: [ None ]
+ ParameterCount: 0
+ ArgumentList: 4096
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 0
+ Options: [ None, ForwardReference, HasUniqueName ]
+ FieldList: 0
+ Name: Foo
+ UniqueName: '.?AUFoo@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 0
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4098
+ Attrs: 65548
+ - Kind: LF_MFUNCTION
+ MemberFunction:
+ ReturnType: 3
+ ClassType: 4098
+ ThisType: 4099
+ CallConv: NearC
+ Options: [ None, Constructor ]
+ ParameterCount: 0
+ ArgumentList: 4096
+ ThisPointerAdjustment: 0
+ - Kind: LF_FIELDLIST
+ FieldList:
+ - Kind: LF_MEMBER
+ DataMember:
+ Attrs: 3
+ Type: 116
+ FieldOffset: 0
+ Name: a
+ - Kind: LF_ONEMETHOD
+ OneMethod:
+ Type: 4100
+ Attrs: 259
+ VFTableOffset: -1
+ Name: Foo
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 2
+ Options: [ None, HasConstructorOrDestructor, HasUniqueName ]
+ FieldList: 4101
+ Name: Foo
+ UniqueName: '.?AUFoo@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 4
+...
diff --git a/llvm/test/tools/llvm-pdbutil/Inputs/forward-refs2.yaml b/llvm/test/tools/llvm-pdbutil/Inputs/forward-refs2.yaml
new file mode 100644
index 0000000000000..23f0a70c433b3
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbutil/Inputs/forward-refs2.yaml
@@ -0,0 +1,64 @@
+---
+# Essentially the same as forward-refs1.yaml but with struct Bar { int b; };
+TpiStream:
+ Version: VC80
+ Records:
+ - Kind: LF_ARGLIST
+ ArgList:
+ ArgIndices: [ ]
+ - Kind: LF_PROCEDURE
+ Procedure:
+ ReturnType: 116
+ CallConv: NearC
+ Options: [ None ]
+ ParameterCount: 0
+ ArgumentList: 4096
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 0
+ Options: [ None, ForwardReference, HasUniqueName ]
+ FieldList: 0
+ Name: Bar
+ UniqueName: '.?AUBar@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 0
+ - Kind: LF_POINTER
+ Pointer:
+ ReferentType: 4098
+ Attrs: 65548
+ - Kind: LF_MFUNCTION
+ MemberFunction:
+ ReturnType: 3
+ ClassType: 4098
+ ThisType: 4099
+ CallConv: NearC
+ Options: [ None, Constructor ]
+ ParameterCount: 0
+ ArgumentList: 4096
+ ThisPointerAdjustment: 0
+ - Kind: LF_FIELDLIST
+ FieldList:
+ - Kind: LF_MEMBER
+ DataMember:
+ Attrs: 3
+ Type: 116
+ FieldOffset: 0
+ Name: b
+ - Kind: LF_ONEMETHOD
+ OneMethod:
+ Type: 4100
+ Attrs: 259
+ VFTableOffset: -1
+ Name: Bar
+ - Kind: LF_STRUCTURE
+ Class:
+ MemberCount: 2
+ Options: [ None, HasConstructorOrDestructor, HasUniqueName ]
+ FieldList: 4101
+ Name: Bar
+ UniqueName: '.?AUBar@@'
+ DerivationList: 0
+ VTableShape: 0
+ Size: 4
+...
diff --git a/llvm/test/tools/llvm-pdbutil/merged-forward-refs.test b/llvm/test/tools/llvm-pdbutil/merged-forward-refs.test
new file mode 100644
index 0000000000000..425d7f6edd0b6
--- /dev/null
+++ b/llvm/test/tools/llvm-pdbutil/merged-forward-refs.test
@@ -0,0 +1,35 @@
+# RUN: llvm-pdbutil yaml2pdb %p/Inputs/forward-refs1.yaml --pdb=%t.1.pdb
+# RUN: llvm-pdbutil yaml2pdb %p/Inputs/forward-refs2.yaml --pdb=%t.2.pdb
+# RUN: llvm-pdbutil merge %t.1.pdb %t.2.pdb --pdb=%t.pdb
+# RUN: llvm-pdbutil dump --types %t.1.pdb | FileCheck %s --check-prefix=ONE
+# RUN: llvm-pdbutil dump --types %t.2.pdb | FileCheck %s --check-prefix=TWO
+# RUN: llvm-pdbutil dump --types %t.pdb | FileCheck %s --check-prefix=MERGED
+
+# Test that forward references can be found after merging (requires type hashes).
+
+# ONE: 0x1002 | LF_STRUCTURE [size = 36] `Foo`
+# ONE-NEXT: unique name: `.?AUFoo@@`
+# ONE-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+# ONE-NEXT: options: forward ref (-> 0x1006) | has unique name, sizeof 0
+# ONE: 0x1006 | LF_STRUCTURE [size = 36] `Foo`
+# ONE-NEXT: unique name: `.?AUFoo@@`
+
+# TWO: 0x1002 | LF_STRUCTURE [size = 36] `Bar`
+# TWO-NEXT: unique name: `.?AUBar@@`
+# TWO-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+# TWO-NEXT: options: forward ref (-> 0x1006) | has unique name, sizeof 0
+# TWO: 0x1006 | LF_STRUCTURE [size = 36] `Bar`
+# TWO-NEXT: unique name: `.?AUBar@@`
+
+# MERGED: 0x1002 | LF_STRUCTURE [size = 36] `Foo`
+# MERGED-NEXT: unique name: `.?AUFoo@@`
+# MERGED-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+# MERGED-NEXT: options: forward ref (-> 0x1006) | has unique name, sizeof 0
+# MERGED: 0x1006 | LF_STRUCTURE [size = 36] `Foo`
+# MERGED-NEXT: unique name: `.?AUFoo@@`
+# MERGED: 0x1007 | LF_STRUCTURE [size = 36] `Bar`
+# MERGED-NEXT: unique name: `.?AUBar@@`
+# MERGED-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+# MERGED-NEXT: options: forward ref (-> 0x100B) | has unique name, sizeof 0
+# MERGED: 0x100B | LF_STRUCTURE [size = 36] `Bar`
+# MERGED-NEXT: unique name: `.?AUBar@@`
diff --git a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index befd33171ed0a..16ecc59b0db87 100644
--- a/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -60,6 +60,7 @@
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/PDB.h"
@@ -889,7 +890,8 @@ static void yamlToPdb(StringRef Path) {
AppendingTypeTableBuilder TS(Allocator);
for (const auto &R : Tpi.Records) {
CVType Type = R.toCodeViewRecord(TS);
- TpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);
+ uint32_t Hash = ExitOnErr(llvm::pdb::hashTypeRecord(Type));
+ TpiBuilder.addTypeRecord(Type.RecordData, Hash);
}
const auto &Ipi = YamlObj.IpiStream.value_or(DefaultIpiStream);
@@ -897,7 +899,8 @@ static void yamlToPdb(StringRef Path) {
IpiBuilder.setVersionHeader(Ipi.Version);
for (const auto &R : Ipi.Records) {
CVType Type = R.toCodeViewRecord(TS);
- IpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);
+ uint32_t Hash = ExitOnErr(llvm::pdb::hashTypeRecord(Type));
+ IpiBuilder.addTypeRecord(Type.RecordData, Hash);
}
if (YamlObj.PublicsStream) {
@@ -1395,10 +1398,12 @@ static void mergePdbs() {
auto &DestTpi = Builder.getTpiBuilder();
auto &DestIpi = Builder.getIpiBuilder();
MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {
- DestTpi.addTypeRecord(Type.RecordData, std::nullopt);
+ uint32_t Hash = ExitOnErr(llvm::pdb::hashTypeRecord(Type));
+ DestTpi.addTypeRecord(Type.RecordData, Hash);
});
MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {
- DestIpi.addTypeRecord(Type.RecordData, std::nullopt);
+ uint32_t Hash = ExitOnErr(llvm::pdb::hashTypeRecord(Type));
+ DestIpi.addTypeRecord(Type.RecordData, Hash);
});
Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
More information about the llvm-commits
mailing list