[LLD][COFF] Survive empty and invalid PCH signature
Solve two issues that showed up when using LLD with Unreal Engine & FASTBuild: 1. It seems the S_OBJNAME record doesn't always record the "precomp signature". We were relying on that to match the PCH.OBJ with their dependent-OBJ. 2. MSVC link.exe is able to link a PCH.OBJ when the "precomp signatureÈ doesn't match, but LLD was failing. This was occuring since the Unreal Engine Build Tool was compiling the PCH.OBJ, but the dependent-OBJ were compiled & cached through FASTBuild. Upon a clean rebuild, the PCH.OBJs were recompiled by the Unreal Build Tool, thus the "precomp signatures" were changing; however the OBJs were already cached by FASTBuild, thus having an old "precomp signatures". We now ignore "precomp signatures" and properly fallback to cmd-line name lookup, like MSVC link.exe does, and only fail if the PCH.OBJ type stream doesn't match the count expected by the dependent-OBJ. Differential Revision: https://reviews.llvm.org/D136762
This commit is contained in:
parent
e2bff1e489
commit
242a9cf7e6
|
@ -125,18 +125,23 @@ public:
|
|||
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();
|
||||
|
||||
// Whether this precomp OBJ was recorded in the precompSourceMappings map.
|
||||
// Only happens if the file->pchSignature is valid.
|
||||
bool registered = false;
|
||||
};
|
||||
|
||||
// This class represents the debug type stream of an OBJ file that depends on a
|
||||
|
@ -310,10 +315,15 @@ Error TpiSource::mergeDebugT(TypeMerger *m) {
|
|||
// When dealing with PCH.OBJ, some indices were already merged.
|
||||
unsigned nbHeadIndices = indexMapStorage.size();
|
||||
|
||||
if (auto err = mergeTypeAndIdRecords(
|
||||
m->idTable, m->typeTable, indexMapStorage, types, file->pchSignature))
|
||||
Optional<PCHMergerInfo> pchInfo;
|
||||
if (auto err = mergeTypeAndIdRecords(m->idTable, m->typeTable,
|
||||
indexMapStorage, types, pchInfo))
|
||||
fatal("codeview::mergeTypeAndIdRecords failed: " +
|
||||
toString(std::move(err)));
|
||||
if (pchInfo) {
|
||||
file->pchSignature = pchInfo->PCHSignature;
|
||||
endPrecompIdx = pchInfo->EndPrecompIndex;
|
||||
}
|
||||
|
||||
// In an object, there is only one mapping for both types and items.
|
||||
tpiMap = indexMapStorage;
|
||||
|
@ -494,16 +504,15 @@ Expected<PrecompSource *> UsePrecompSource::findPrecompMap(ObjFile *file,
|
|||
pr.getPrecompFilePath(),
|
||||
make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
|
||||
|
||||
if (pr.getSignature() != file->pchSignature)
|
||||
// Don't rely on the PCH signature to validate the concordance between the PCH
|
||||
// and the OBJ that uses it. However we do validate here that the
|
||||
// LF_ENDPRECOMP record index lines up with the number of type records
|
||||
// LF_PRECOMP is expecting.
|
||||
if (precomp->endPrecompIdx != pr.getTypesCount())
|
||||
return createFileError(
|
||||
toString(file),
|
||||
make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
|
||||
|
||||
if (pr.getSignature() != *precomp->file->pchSignature)
|
||||
return createFileError(
|
||||
toString(precomp->file),
|
||||
make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
|
||||
|
||||
return precomp;
|
||||
}
|
||||
|
||||
|
@ -541,6 +550,30 @@ Error UsePrecompSource::mergeDebugT(TypeMerger *m) {
|
|||
return TpiSource::mergeDebugT(m);
|
||||
}
|
||||
|
||||
Error PrecompSource::mergeDebugT(TypeMerger *m) {
|
||||
// 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, before registering below.
|
||||
if (Error e = TpiSource::mergeDebugT(m))
|
||||
return e;
|
||||
|
||||
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 +841,14 @@ void PrecompSource::loadGHashes() {
|
|||
// 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)
|
||||
endPrecompGHashIdx = ghashIdx;
|
||||
if (ty.kind() == LF_ENDPRECOMP) {
|
||||
EndPrecompRecord endPrecomp;
|
||||
cantFail(TypeDeserializer::deserializeAs<EndPrecompRecord>(
|
||||
const_cast<CVType &>(ty), endPrecomp));
|
||||
file->pchSignature = endPrecomp.getSignature();
|
||||
registerMapping();
|
||||
endPrecompIdx = ghashIdx;
|
||||
}
|
||||
|
||||
hashVec.push_back(GloballyHashedType::hashType(ty, hashVec, hashVec));
|
||||
isItemIndex.push_back(isIdRecord(ty.kind()));
|
||||
|
@ -819,9 +858,13 @@ void PrecompSource::loadGHashes() {
|
|||
}
|
||||
|
||||
void UsePrecompSource::loadGHashes() {
|
||||
PrecompSource *pchSrc = findPrecompSource(file, precompDependency);
|
||||
if (!pchSrc)
|
||||
auto e = findPrecompMap(file, precompDependency);
|
||||
if (!e) {
|
||||
warn(toString(e.takeError()));
|
||||
return;
|
||||
}
|
||||
|
||||
PrecompSource *pchSrc = *e;
|
||||
|
||||
// To compute ghashes of a /Yu object file, we need to build on the ghashes of
|
||||
// the /Yc PCH object. After we are done hashing, discard the ghashes from the
|
||||
|
|
|
@ -106,18 +106,18 @@ public:
|
|||
/// it is unique. This prevents a record from being added to the input ghash
|
||||
/// table.
|
||||
bool shouldOmitFromPdb(uint32_t ghashIdx) {
|
||||
return ghashIdx == endPrecompGHashIdx;
|
||||
return ghashIdx == endPrecompIdx;
|
||||
}
|
||||
|
||||
const TpiKind kind;
|
||||
bool ownedGHashes = true;
|
||||
uint32_t tpiSrcIdx = 0;
|
||||
|
||||
protected:
|
||||
/// The ghash index (zero based, not 0x1000-based) of the LF_ENDPRECOMP record
|
||||
/// in this object, if one exists. This is the all ones value otherwise. It is
|
||||
/// recorded here so that it can be omitted from the final ghash table.
|
||||
uint32_t endPrecompGHashIdx = ~0U;
|
||||
/// The index (zero based, not 0x1000-based) of the LF_ENDPRECOMP record in
|
||||
/// this object, if one exists. This is the all ones value otherwise. It is
|
||||
/// recorded here for validation, and so that it can be omitted from the final
|
||||
/// ghash table.
|
||||
uint32_t endPrecompIdx = ~0U;
|
||||
|
||||
public:
|
||||
ObjFile *file;
|
||||
|
|
|
@ -734,7 +734,8 @@ void ObjFile::initializeFlags() {
|
|||
if (sym->kind() == SymbolKind::S_OBJNAME) {
|
||||
auto objName = cantFail(SymbolDeserializer::deserializeAs<ObjNameSym>(
|
||||
sym.get()));
|
||||
pchSignature = objName.Signature;
|
||||
if (objName.Signature)
|
||||
pchSignature = objName.Signature;
|
||||
}
|
||||
offset += sym->length();
|
||||
}
|
||||
|
@ -800,6 +801,10 @@ void ObjFile::initializeDependencies() {
|
|||
if (firstType->kind() == LF_PRECOMP) {
|
||||
PrecompRecord precomp = cantFail(
|
||||
TypeDeserializer::deserializeAs<PrecompRecord>(firstType->data()));
|
||||
// We're better off trusting the LF_PRECOMP signature. In some cases the
|
||||
// S_OBJNAME record doesn't contain a valid PCH signature.
|
||||
if (precomp.Signature)
|
||||
pchSignature = precomp.Signature;
|
||||
debugTypesObj = makeUsePrecompSource(ctx, this, precomp);
|
||||
// Drop the LF_PRECOMP record from the input stream.
|
||||
debugTypes = debugTypes.drop_front(firstType->RecordData.size());
|
||||
|
|
|
@ -45,6 +45,9 @@ COFF Improvements
|
|||
(`D137723 <https://reviews.llvm.org/D137723>`_)
|
||||
* Switched from SHA1 to BLAKE3 for PDB type hashing / ``-gcodeview-ghash``
|
||||
(`D137101 <https://reviews.llvm.org/D137101>`_)
|
||||
* Improvements to the PCH.OBJ files handling. Now LLD behaves the same as MSVC
|
||||
link.exe when merging PCH.OBJ files that don't have the same signature.
|
||||
(`D136762 <https://reviews.llvm.org/D136762>`_)
|
||||
|
||||
MinGW Improvements
|
||||
------------------
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug:noghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY
|
||||
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug:ghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY
|
||||
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
|
||||
|
||||
RUN: lld-link %S/Inputs/precomp.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf
|
||||
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
|
||||
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-invalid.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1 | FileCheck %s -check-prefix FAILURE
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-invalid.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug:ghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1 | FileCheck %s -check-prefix FAILURE
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-invalid.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug:noghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-invalid.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug:ghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1
|
||||
|
||||
FIXME: The following RUN line should fail, regardless of whether debug info is
|
||||
enabled or not. Normally this would result in an error due to missing _PchSym_
|
||||
|
@ -14,14 +16,11 @@ special case for those symbols and it emits the LNK2011 error.
|
|||
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1 | FileCheck %s -check-prefix FAILURE-MISSING-PRECOMPOBJ
|
||||
|
||||
FAILURE: warning: Cannot use debug info for '{{.*}}precomp-invalid.obj' [LNK4099]
|
||||
FAILURE-NEXT: failed to load reference '{{.*}}precomp.obj': No matching precompiled header could be located.
|
||||
|
||||
FAILURE-MISSING-PRECOMPOBJ: warning: Cannot use debug info for '{{.*}}precomp-a.obj' [LNK4099]
|
||||
FAILURE-MISSING-PRECOMPOBJ-NEXT: failed to load reference '{{.*}}precomp.obj': No matching precompiled header could be located.
|
||||
|
||||
Check that a PCH object file with a missing S_OBJNAME record results in an
|
||||
error. Edit out this record from the yaml-ified object:
|
||||
Check that a PCH object file with an empty S_OBJNAME record works fine.
|
||||
Edit out this record from the yaml-ified object:
|
||||
- Kind: S_OBJNAME
|
||||
ObjNameSym:
|
||||
Signature: 545589255
|
||||
|
@ -29,22 +28,27 @@ error. Edit out this record from the yaml-ified object:
|
|||
|
||||
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 lld-link %t.precomp-no-objname.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug:noghash /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix WARNING --allow-empty
|
||||
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:ghash /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix WARNING --allow-empty
|
||||
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:noghash /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix WARNING --allow-empty
|
||||
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:ghash /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix WARNING --allow-empty
|
||||
|
||||
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
|
||||
WARNING-NOT: warning
|
||||
|
||||
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
|
||||
Check that a PCH with wrong signature, but with right LF_PRECOMP records count, works.
|
||||
|
||||
FAILURE-NO-SIGNATURE: error: {{.*}}.obj claims to be a PCH object, but does not have a valid signature
|
||||
RUN: sed '16,19s/Signature: *545589255/Signature: 123456789/' < %t.precomp.yaml > precomp-wrong-sig.yaml
|
||||
RUN: yaml2obj precomp-wrong-sig.yaml -o %T/precomp.obj
|
||||
RUN: env LLD_IN_TEST=1 lld-link %T/precomp.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug:noghash /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix WARNING --allow-empty
|
||||
RUN: env LLD_IN_TEST=1 lld-link %T/precomp.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug:ghash /pdb:%t.pdb /out:%t.exe 2>&1 | FileCheck %s -check-prefix WARNING --allow-empty
|
||||
|
||||
Check that two PCH objs with duplicate signatures are an error.
|
||||
|
||||
RUN: cp %S/Inputs/precomp.obj %t.precomp-dup.obj
|
||||
|
||||
RUN: env LLD_IN_TEST=1 not lld-link %S/Inputs/precomp.obj %t.precomp-dup.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-DUP-SIGNATURE
|
||||
|
||||
FAILURE-DUP-SIGNATURE: error: a PCH object with the same signature has already been provided ({{.*precomp.obj and .*precomp-dup.obj.*}})
|
||||
|
||||
|
||||
|
@ -52,13 +56,6 @@ CHECK: Types (TPI Stream)
|
|||
CHECK-NOT: LF_PRECOMP
|
||||
CHECK-NOT: LF_ENDPRECOMP
|
||||
|
||||
|
||||
Re-run with ghash. Eventually, perhaps this will be the default.
|
||||
|
||||
RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug /debug:ghash /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf /summary | FileCheck %s -check-prefix SUMMARY
|
||||
RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
|
||||
|
||||
|
||||
SUMMARY: Summary
|
||||
SUMMARY-NEXT: --------------------------------------------------------------------------------
|
||||
SUMMARY-NEXT: 3 Input OBJ files (expanded from all cmd-line inputs)
|
||||
|
|
|
@ -23,6 +23,13 @@ struct GloballyHashedType;
|
|||
class GlobalTypeTableBuilder;
|
||||
class MergingTypeTableBuilder;
|
||||
|
||||
/// Used to forward information about PCH.OBJ (precompiled) files, when
|
||||
/// applicable.
|
||||
struct PCHMergerInfo {
|
||||
uint32_t PCHSignature{};
|
||||
uint32_t EndPrecompIndex = ~0U;
|
||||
};
|
||||
|
||||
/// Merge one set of type records into another. This method assumes
|
||||
/// that all records are type records, and there are no Id records present.
|
||||
///
|
||||
|
@ -84,20 +91,20 @@ Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds,
|
|||
MergingTypeTableBuilder &DestTypes,
|
||||
SmallVectorImpl<TypeIndex> &SourceToDest,
|
||||
const CVTypeArray &IdsAndTypes,
|
||||
Optional<uint32_t> &PCHSignature);
|
||||
Optional<PCHMergerInfo> &PCHInfo);
|
||||
|
||||
Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds,
|
||||
GlobalTypeTableBuilder &DestTypes,
|
||||
SmallVectorImpl<TypeIndex> &SourceToDest,
|
||||
const CVTypeArray &IdsAndTypes,
|
||||
ArrayRef<GloballyHashedType> Hashes,
|
||||
Optional<uint32_t> &PCHSignature);
|
||||
Optional<PCHMergerInfo> &PCHInfo);
|
||||
|
||||
Error mergeTypeRecords(GlobalTypeTableBuilder &Dest,
|
||||
SmallVectorImpl<TypeIndex> &SourceToDest,
|
||||
const CVTypeArray &Types,
|
||||
ArrayRef<GloballyHashedType> Hashes,
|
||||
Optional<uint32_t> &PCHSignature);
|
||||
Optional<PCHMergerInfo> &PCHInfo);
|
||||
|
||||
Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
|
||||
SmallVectorImpl<TypeIndex> &SourceToDest,
|
||||
|
|
|
@ -77,7 +77,8 @@ public:
|
|||
// Local hashing entry points
|
||||
Error mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
|
||||
MergingTypeTableBuilder &DestTypes,
|
||||
const CVTypeArray &IdsAndTypes, Optional<uint32_t> &S);
|
||||
const CVTypeArray &IdsAndTypes,
|
||||
Optional<PCHMergerInfo> &PCHInfo);
|
||||
Error mergeIdRecords(MergingTypeTableBuilder &Dest,
|
||||
ArrayRef<TypeIndex> TypeSourceToDest,
|
||||
const CVTypeArray &Ids);
|
||||
|
@ -89,14 +90,14 @@ public:
|
|||
GlobalTypeTableBuilder &DestTypes,
|
||||
const CVTypeArray &IdsAndTypes,
|
||||
ArrayRef<GloballyHashedType> Hashes,
|
||||
Optional<uint32_t> &S);
|
||||
Optional<PCHMergerInfo> &PCHInfo);
|
||||
Error mergeIdRecords(GlobalTypeTableBuilder &Dest,
|
||||
ArrayRef<TypeIndex> TypeSourceToDest,
|
||||
const CVTypeArray &Ids,
|
||||
ArrayRef<GloballyHashedType> Hashes);
|
||||
Error mergeTypeRecords(GlobalTypeTableBuilder &Dest, const CVTypeArray &Types,
|
||||
ArrayRef<GloballyHashedType> Hashes,
|
||||
Optional<uint32_t> &S);
|
||||
Optional<PCHMergerInfo> &PCHInfo);
|
||||
|
||||
private:
|
||||
Error doit(const CVTypeArray &Types);
|
||||
|
@ -196,7 +197,7 @@ private:
|
|||
/// its type indices.
|
||||
SmallVector<uint8_t, 256> RemapStorage;
|
||||
|
||||
Optional<uint32_t> PCHSignature;
|
||||
Optional<PCHMergerInfo> PCHInfo;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
@ -259,12 +260,12 @@ Error TypeStreamMerger::mergeIdRecords(MergingTypeTableBuilder &Dest,
|
|||
Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
|
||||
MergingTypeTableBuilder &DestTypes,
|
||||
const CVTypeArray &IdsAndTypes,
|
||||
Optional<uint32_t> &S) {
|
||||
Optional<PCHMergerInfo> &PCHInfo) {
|
||||
DestIdStream = &DestIds;
|
||||
DestTypeStream = &DestTypes;
|
||||
UseGlobalHashes = false;
|
||||
auto Err = doit(IdsAndTypes);
|
||||
S = PCHSignature;
|
||||
PCHInfo = this->PCHInfo;
|
||||
return Err;
|
||||
}
|
||||
|
||||
|
@ -272,12 +273,12 @@ Error TypeStreamMerger::mergeTypesAndIds(MergingTypeTableBuilder &DestIds,
|
|||
Error TypeStreamMerger::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
|
||||
const CVTypeArray &Types,
|
||||
ArrayRef<GloballyHashedType> Hashes,
|
||||
Optional<uint32_t> &S) {
|
||||
Optional<PCHMergerInfo> &PCHInfo) {
|
||||
DestGlobalTypeStream = &Dest;
|
||||
UseGlobalHashes = true;
|
||||
GlobalHashes = Hashes;
|
||||
auto Err = doit(Types);
|
||||
S = PCHSignature;
|
||||
PCHInfo = this->PCHInfo;
|
||||
return Err;
|
||||
}
|
||||
|
||||
|
@ -297,13 +298,13 @@ Error TypeStreamMerger::mergeTypesAndIds(GlobalTypeTableBuilder &DestIds,
|
|||
GlobalTypeTableBuilder &DestTypes,
|
||||
const CVTypeArray &IdsAndTypes,
|
||||
ArrayRef<GloballyHashedType> Hashes,
|
||||
Optional<uint32_t> &S) {
|
||||
Optional<PCHMergerInfo> &PCHInfo) {
|
||||
DestGlobalIdStream = &DestIds;
|
||||
DestGlobalTypeStream = &DestTypes;
|
||||
UseGlobalHashes = true;
|
||||
GlobalHashes = Hashes;
|
||||
auto Err = doit(IdsAndTypes);
|
||||
S = PCHSignature;
|
||||
PCHInfo = this->PCHInfo;
|
||||
return Err;
|
||||
}
|
||||
|
||||
|
@ -446,27 +447,26 @@ Error llvm::codeview::mergeIdRecords(MergingTypeTableBuilder &Dest,
|
|||
Error llvm::codeview::mergeTypeAndIdRecords(
|
||||
MergingTypeTableBuilder &DestIds, MergingTypeTableBuilder &DestTypes,
|
||||
SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
|
||||
Optional<uint32_t> &PCHSignature) {
|
||||
Optional<PCHMergerInfo> &PCHInfo) {
|
||||
TypeStreamMerger M(SourceToDest);
|
||||
return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHSignature);
|
||||
return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, PCHInfo);
|
||||
}
|
||||
|
||||
Error llvm::codeview::mergeTypeAndIdRecords(
|
||||
GlobalTypeTableBuilder &DestIds, GlobalTypeTableBuilder &DestTypes,
|
||||
SmallVectorImpl<TypeIndex> &SourceToDest, const CVTypeArray &IdsAndTypes,
|
||||
ArrayRef<GloballyHashedType> Hashes, Optional<uint32_t> &PCHSignature) {
|
||||
ArrayRef<GloballyHashedType> Hashes, Optional<PCHMergerInfo> &PCHInfo) {
|
||||
TypeStreamMerger M(SourceToDest);
|
||||
return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes,
|
||||
PCHSignature);
|
||||
return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes, Hashes, PCHInfo);
|
||||
}
|
||||
|
||||
Error llvm::codeview::mergeTypeRecords(GlobalTypeTableBuilder &Dest,
|
||||
SmallVectorImpl<TypeIndex> &SourceToDest,
|
||||
const CVTypeArray &Types,
|
||||
ArrayRef<GloballyHashedType> Hashes,
|
||||
Optional<uint32_t> &PCHSignature) {
|
||||
Optional<PCHMergerInfo> &PCHInfo) {
|
||||
TypeStreamMerger M(SourceToDest);
|
||||
return M.mergeTypeRecords(Dest, Types, Hashes, PCHSignature);
|
||||
return M.mergeTypeRecords(Dest, Types, Hashes, PCHInfo);
|
||||
}
|
||||
|
||||
Error llvm::codeview::mergeIdRecords(GlobalTypeTableBuilder &Dest,
|
||||
|
@ -487,9 +487,10 @@ Expected<bool> TypeStreamMerger::shouldRemapType(const CVType &Type) {
|
|||
if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type),
|
||||
EP))
|
||||
return joinErrors(std::move(EC), errorCorruptRecord());
|
||||
if (PCHSignature)
|
||||
// Only one record of this kind can appear in a OBJ.
|
||||
if (PCHInfo)
|
||||
return errorCorruptRecord();
|
||||
PCHSignature.emplace(EP.getSignature());
|
||||
PCHInfo.emplace(PCHMergerInfo{EP.getSignature(), CurIndex.toArrayIndex()});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1371,17 +1371,17 @@ void COFFDumper::mergeCodeViewTypes(MergingTypeTableBuilder &CVIDs,
|
|||
Obj->getFileName());
|
||||
}
|
||||
SmallVector<TypeIndex, 128> SourceToDest;
|
||||
Optional<uint32_t> PCHSignature;
|
||||
Optional<PCHMergerInfo> PCHInfo;
|
||||
if (GHash) {
|
||||
std::vector<GloballyHashedType> Hashes =
|
||||
GloballyHashedType::hashTypes(Types);
|
||||
if (Error E =
|
||||
mergeTypeAndIdRecords(GlobalCVIDs, GlobalCVTypes, SourceToDest,
|
||||
Types, Hashes, PCHSignature))
|
||||
Types, Hashes, PCHInfo))
|
||||
return reportError(std::move(E), Obj->getFileName());
|
||||
} else {
|
||||
if (Error E = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types,
|
||||
PCHSignature))
|
||||
PCHInfo))
|
||||
return reportError(std::move(E), Obj->getFileName());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user