[lld] Fix type server merging with PDBs without IPI stream

PDBs may not necessarily contain an IPI stream. Handle this case
gracefully.

The test case was verified to work with MS link.exe.

Patch by Vladimir Panteleev, with a small simplification

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D63178

llvm-svn: 363213
This commit is contained in:
Reid Kleckner 2019-06-12 22:33:16 +00:00
parent efc01eac17
commit 5584ab89a8
4 changed files with 39 additions and 13 deletions

View File

@ -434,9 +434,13 @@ Expected<const CVIndexMap &> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File) {
Expected<pdb::TpiStream &> ExpectedTpi = PDBFile.getPDBTpiStream();
if (auto E = ExpectedTpi.takeError())
fatal("Type server does not have TPI stream: " + toString(std::move(E)));
Expected<pdb::TpiStream &> ExpectedIpi = PDBFile.getPDBIpiStream();
if (auto E = ExpectedIpi.takeError())
fatal("Type server does not have TPI stream: " + toString(std::move(E)));
pdb::TpiStream *MaybeIpi = nullptr;
if (PDBFile.hasPDBIpiStream()) {
Expected<pdb::TpiStream &> ExpectedIpi = PDBFile.getPDBIpiStream();
if (auto E = ExpectedIpi.takeError())
fatal("Error getting type server IPI stream: " + toString(std::move(E)));
MaybeIpi = &*ExpectedIpi;
}
if (Config->DebugGHashes) {
// PDBs do not actually store global hashes, so when merging a type server
@ -445,9 +449,6 @@ Expected<const CVIndexMap &> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File) {
// synthesize hashes for the IPI stream, using the hashes for the TPI stream
// as inputs.
auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray());
auto IpiHashes =
GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes);
Optional<uint32_t> EndPrecomp;
// Merge TPI first, because the IPI stream will reference type indices.
if (auto Err =
@ -456,10 +457,14 @@ Expected<const CVIndexMap &> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File) {
fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
// Merge IPI.
if (auto Err = mergeIdRecords(TMerger.GlobalIDTable, IndexMap.TPIMap,
IndexMap.IPIMap, ExpectedIpi->typeArray(),
IpiHashes))
fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
if (MaybeIpi) {
auto IpiHashes =
GloballyHashedType::hashIds(MaybeIpi->typeArray(), TpiHashes);
if (auto Err =
mergeIdRecords(TMerger.GlobalIDTable, IndexMap.TPIMap,
IndexMap.IPIMap, MaybeIpi->typeArray(), IpiHashes))
fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
}
} else {
// Merge TPI first, because the IPI stream will reference type indices.
if (auto Err = mergeTypeRecords(TMerger.TypeTable, IndexMap.TPIMap,
@ -467,9 +472,11 @@ Expected<const CVIndexMap &> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File) {
fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
// Merge IPI.
if (auto Err = mergeIdRecords(TMerger.IDTable, IndexMap.TPIMap,
IndexMap.IPIMap, ExpectedIpi->typeArray()))
fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
if (MaybeIpi) {
if (auto Err = mergeIdRecords(TMerger.IDTable, IndexMap.TPIMap,
IndexMap.IPIMap, MaybeIpi->typeArray()))
fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
}
}
return IndexMap;

View File

@ -0,0 +1,13 @@
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_I386
sections:
- Name: '.debug$T'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
Types:
- Kind: LF_TYPESERVER2
TypeServer2:
Guid: '{01234567-0123-0123-0123-0123456789AB}'
Age: 1
Name: 'no-ipi-stream-pdb.pdb'
symbols:

View File

@ -0,0 +1,2 @@
PdbStream:
Guid: '{01234567-0123-0123-0123-0123456789AB}'

View File

@ -0,0 +1,4 @@
# RUN: rm -rf %t && mkdir %t
# RUN: yaml2obj < %p/Inputs/no-ipi-stream-obj.obj.yaml > %t/no-ipi-stream-obj.obj
# RUN: llvm-pdbutil yaml2pdb %p/Inputs/no-ipi-stream-pdb.pdb.yaml -pdb=%t/no-ipi-stream-pdb.pdb
# RUN: lld-link /dll /noentry /debug %t/no-ipi-stream-obj.obj