[llvm] 242a9cf - [LLD][COFF] Survive empty and invalid PCH signature
Alexandre Ganea via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 20 07:40:58 PST 2022
Author: Alexandre Ganea
Date: 2022-11-20T10:40:50-05:00
New Revision: 242a9cf7e6759bdd6c4af524d544f562b7385d27
URL: https://github.com/llvm/llvm-project/commit/242a9cf7e6759bdd6c4af524d544f562b7385d27
DIFF: https://github.com/llvm/llvm-project/commit/242a9cf7e6759bdd6c4af524d544f562b7385d27.diff
LOG: [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
Added:
Modified:
lld/COFF/DebugTypes.cpp
lld/COFF/DebugTypes.h
lld/COFF/InputFiles.cpp
lld/docs/ReleaseNotes.rst
lld/test/COFF/precomp-link.test
llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
llvm/tools/llvm-readobj/COFFDumper.cpp
Removed:
################################################################################
diff --git a/lld/COFF/DebugTypes.cpp b/lld/COFF/DebugTypes.cpp
index 6786d064ca8df..2b35b68032d02 100644
--- a/lld/COFF/DebugTypes.cpp
+++ b/lld/COFF/DebugTypes.cpp
@@ -125,18 +125,23 @@ class UseTypeServerSource : public TpiSource {
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
diff --git a/lld/COFF/DebugTypes.h b/lld/COFF/DebugTypes.h
index c3f2c58012005..a7d477695af83 100644
--- a/lld/COFF/DebugTypes.h
+++ b/lld/COFF/DebugTypes.h
@@ -106,18 +106,18 @@ class TpiSource {
/// 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;
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 9c1b2696fb787..ea95648f7e618 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -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());
diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index 0e9029bdcc097..31eb116c383a1 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -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
------------------
diff --git a/lld/test/COFF/precomp-link.test b/lld/test/COFF/precomp-link.test
index ee496c9bc946f..53d981c4e6228 100644
--- a/lld/test/COFF/precomp-link.test
+++ b/lld/test/COFF/precomp-link.test
@@ -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)
diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index 04a1e44dd8093..6abf67a27bd1f 100644
--- a/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/llvm/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -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,
diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 7ddfb7ab2f8d0..5eb1cb1c254c4 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -77,7 +77,8 @@ class TypeStreamMerger {
// 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 @@ class TypeStreamMerger {
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 @@ class TypeStreamMerger {
/// 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;
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index 4ae9d13153569..fdfb5de658dd4 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -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());
}
}
More information about the llvm-commits
mailing list