@@ -125,18 +125,23 @@ class UseTypeServerSource : public TpiSource {
125
125
class PrecompSource : public TpiSource {
126
126
public:
127
127
PrecompSource (COFFLinkerContext &ctx, ObjFile *f) : TpiSource(ctx, PCH, f) {
128
- if (!f->pchSignature || !*f->pchSignature )
129
- fatal (toString (f) +
130
- " claims to be a PCH object, but does not have a valid signature" );
131
- auto it = ctx.precompSourceMappings .emplace (*f->pchSignature , this );
132
- if (!it.second )
133
- fatal (" a PCH object with the same signature has already been provided (" +
134
- toString (it.first ->second ->file ) + " and " + toString (file) + " )" );
128
+ // If the S_OBJNAME record contains the PCH signature, we'll register this
129
+ // source file right away.
130
+ registerMapping ();
135
131
}
136
132
133
+ Error mergeDebugT (TypeMerger *m) override ;
134
+
137
135
void loadGHashes () override ;
138
136
139
137
bool isDependency () const override { return true ; }
138
+
139
+ private:
140
+ void registerMapping ();
141
+
142
+ // Whether this precomp OBJ was recorded in the precompSourceMappings map.
143
+ // Only happens if the file->pchSignature is valid.
144
+ bool registered = false ;
140
145
};
141
146
142
147
// This class represents the debug type stream of an OBJ file that depends on a
@@ -310,10 +315,15 @@ Error TpiSource::mergeDebugT(TypeMerger *m) {
310
315
// When dealing with PCH.OBJ, some indices were already merged.
311
316
unsigned nbHeadIndices = indexMapStorage.size ();
312
317
313
- if (auto err = mergeTypeAndIdRecords (
314
- m->idTable , m->typeTable , indexMapStorage, types, file->pchSignature ))
318
+ Optional<PCHMergerInfo> pchInfo;
319
+ if (auto err = mergeTypeAndIdRecords (m->idTable , m->typeTable ,
320
+ indexMapStorage, types, pchInfo))
315
321
fatal (" codeview::mergeTypeAndIdRecords failed: " +
316
322
toString (std::move (err)));
323
+ if (pchInfo) {
324
+ file->pchSignature = pchInfo->PCHSignature ;
325
+ endPrecompIdx = pchInfo->EndPrecompIndex ;
326
+ }
317
327
318
328
// In an object, there is only one mapping for both types and items.
319
329
tpiMap = indexMapStorage;
@@ -494,16 +504,15 @@ Expected<PrecompSource *> UsePrecompSource::findPrecompMap(ObjFile *file,
494
504
pr.getPrecompFilePath (),
495
505
make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
496
506
497
- if (pr.getSignature () != file->pchSignature )
507
+ // Don't rely on the PCH signature to validate the concordance between the PCH
508
+ // and the OBJ that uses it. However we do validate here that the
509
+ // LF_ENDPRECOMP record index lines up with the number of type records
510
+ // LF_PRECOMP is expecting.
511
+ if (precomp->endPrecompIdx != pr.getTypesCount ())
498
512
return createFileError (
499
513
toString (file),
500
514
make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
501
515
502
- if (pr.getSignature () != *precomp->file ->pchSignature )
503
- return createFileError (
504
- toString (precomp->file ),
505
- make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
506
-
507
516
return precomp;
508
517
}
509
518
@@ -541,6 +550,30 @@ Error UsePrecompSource::mergeDebugT(TypeMerger *m) {
541
550
return TpiSource::mergeDebugT (m);
542
551
}
543
552
553
+ Error PrecompSource::mergeDebugT (TypeMerger *m) {
554
+ // In some cases, the S_OBJNAME record doesn't contain the PCH signature.
555
+ // The signature comes later with the LF_ENDPRECOMP record, so we first need
556
+ // to merge in all the .PCH.OBJ file type records, before registering below.
557
+ if (Error e = TpiSource::mergeDebugT (m))
558
+ return e;
559
+
560
+ registerMapping ();
561
+
562
+ return Error::success ();
563
+ }
564
+
565
+ void PrecompSource::registerMapping () {
566
+ if (registered)
567
+ return ;
568
+ if (file->pchSignature && *file->pchSignature ) {
569
+ auto it = ctx.precompSourceMappings .emplace (*file->pchSignature , this );
570
+ if (!it.second )
571
+ fatal (" a PCH object with the same signature has already been provided (" +
572
+ toString (it.first ->second ->file ) + " and " + toString (file) + " )" );
573
+ registered = true ;
574
+ }
575
+ }
576
+
544
577
// ===----------------------------------------------------------------------===//
545
578
// Parellel GHash type merging implementation.
546
579
// ===----------------------------------------------------------------------===//
@@ -808,8 +841,14 @@ void PrecompSource::loadGHashes() {
808
841
// Remember the index of the LF_ENDPRECOMP record so it can be excluded from
809
842
// the PDB. There must be an entry in the list of ghashes so that the type
810
843
// indexes of the following records in the /Yc PCH object line up.
811
- if (ty.kind () == LF_ENDPRECOMP)
812
- endPrecompGHashIdx = ghashIdx;
844
+ if (ty.kind () == LF_ENDPRECOMP) {
845
+ EndPrecompRecord endPrecomp;
846
+ cantFail (TypeDeserializer::deserializeAs<EndPrecompRecord>(
847
+ const_cast <CVType &>(ty), endPrecomp));
848
+ file->pchSignature = endPrecomp.getSignature ();
849
+ registerMapping ();
850
+ endPrecompIdx = ghashIdx;
851
+ }
813
852
814
853
hashVec.push_back (GloballyHashedType::hashType (ty, hashVec, hashVec));
815
854
isItemIndex.push_back (isIdRecord (ty.kind ()));
@@ -819,9 +858,13 @@ void PrecompSource::loadGHashes() {
819
858
}
820
859
821
860
void UsePrecompSource::loadGHashes () {
822
- PrecompSource *pchSrc = findPrecompSource (file, precompDependency);
823
- if (!pchSrc)
861
+ auto e = findPrecompMap (file, precompDependency);
862
+ if (!e) {
863
+ warn (toString (e.takeError ()));
824
864
return ;
865
+ }
866
+
867
+ PrecompSource *pchSrc = *e;
825
868
826
869
// To compute ghashes of a /Yu object file, we need to build on the ghashes of
827
870
// the /Yc PCH object. After we are done hashing, discard the ghashes from the
0 commit comments