diff --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp --- a/lld/COFF/DebugTypes.cpp +++ b/lld/COFF/DebugTypes.cpp @@ -125,18 +125,21 @@ class PrecompSource : public TpiSource { public: PrecompSource(COFFLinkerContext &ctx, ObjFile *f) : TpiSource(ctx, PCH, f) { - if (!f->pchSignature || !*f->pchSignature) - fatal(toString(f) + - " claims to be a PCH object, but does not have a valid signature"); - auto it = ctx.precompSourceMappings.emplace(*f->pchSignature, this); - if (!it.second) - fatal("a PCH object with the same signature has already been provided (" + - toString(it.first->second->file) + " and " + toString(file) + ")"); + // If the S_OBJNAME record contains the PCH signature, we'll register this + // source file right away. + registerMapping(); } + Error mergeDebugT(TypeMerger *m) override; + void loadGHashes() override; bool isDependency() const override { return true; } + +private: + void registerMapping(); + + bool registered = false; }; // This class represents the debug type stream of an OBJ file that depends on a @@ -541,6 +544,30 @@ return TpiSource::mergeDebugT(m); } +Error PrecompSource::mergeDebugT(TypeMerger *m) { + if (Error e = TpiSource::mergeDebugT(m)) + return e; + + // In some cases, the S_OBJNAME record doesn't contain the PCH signature. + // The signature comes later with the LF_ENDPRECOMP record, so we first need + // to merge in all the .PCH.OBJ file type records. + registerMapping(); + + return Error::success(); +} + +void PrecompSource::registerMapping() { + if (registered) + return; + if (file->pchSignature && *file->pchSignature) { + auto it = ctx.precompSourceMappings.emplace(*file->pchSignature, this); + if (!it.second) + fatal("a PCH object with the same signature has already been provided (" + + toString(it.first->second->file) + " and " + toString(file) + ")"); + registered = true; + } +} + //===----------------------------------------------------------------------===// // Parellel GHash type merging implementation. //===----------------------------------------------------------------------===// @@ -808,8 +835,15 @@ // Remember the index of the LF_ENDPRECOMP record so it can be excluded from // the PDB. There must be an entry in the list of ghashes so that the type // indexes of the following records in the /Yc PCH object line up. - if (ty.kind() == LF_ENDPRECOMP) + if (ty.kind() == LF_ENDPRECOMP) { + if (!registered) { + EndPrecompRecord endPrecomp = cantFail( + TypeDeserializer::deserializeAs(ty.data())); + file->pchSignature.emplace(endPrecomp.getSignature()); + registerMapping(); + } endPrecompGHashIdx = ghashIdx; + } hashVec.push_back(GloballyHashedType::hashType(ty, hashVec, hashVec)); isItemIndex.push_back(isIdRecord(ty.kind())); diff --git a/lld/test/COFF/precomp-link.test b/lld/test/COFF/precomp-link.test --- a/lld/test/COFF/precomp-link.test +++ b/lld/test/COFF/precomp-link.test @@ -29,15 +29,13 @@ RUN: obj2yaml %S/Inputs/precomp.obj | grep -v 'SectionData: *04000000' > %t.precomp.yaml RUN: sed '/S_OBJNAME/,/ObjectName:/d' < %t.precomp.yaml > precomp-no-objname.yaml -RUN: sed 's/Signature: *545589255/Signature: 0/' < %t.precomp.yaml > precomp-zero-sig.yaml +RUN: sed '16,19s/Signature: *545589255/Signature: 0/' < %t.precomp.yaml > precomp-zero-sig.yaml RUN: yaml2obj precomp-no-objname.yaml -o %t.precomp-no-objname.obj RUN: yaml2obj precomp-zero-sig.yaml -o %t.precomp-zero-sig.obj -RUN: env LLD_IN_TEST=1 not lld-link %t.precomp-no-objname.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-NO-SIGNATURE +RUN: env LLD_IN_TEST=1 lld-link %t.precomp-no-objname.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 -RUN: env LLD_IN_TEST=1 not lld-link %t.precomp-zero-sig.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix FAILURE-NO-SIGNATURE - -FAILURE-NO-SIGNATURE: error: {{.*}}.obj claims to be a PCH object, but does not have a valid signature +RUN: env LLD_IN_TEST=1 lld-link %t.precomp-zero-sig.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe 2>&1 Check that two PCH objs with duplicate signatures are an error.