diff options
Diffstat (limited to 'ELF/ICF.cpp')
| -rw-r--r-- | ELF/ICF.cpp | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp index 075938bd16b91..e917ae76a689e 100644 --- a/ELF/ICF.cpp +++ b/ELF/ICF.cpp @@ -252,7 +252,10 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA, auto *DA = dyn_cast<Defined>(&SA); auto *DB = dyn_cast<Defined>(&SB); - if (!DA || !DB) + + // Placeholder symbols generated by linker scripts look the same now but + // may have different values later. + if (!DA || !DB || DA->ScriptDefined || DB->ScriptDefined) return false; // Relocations referring to absolute symbols are constant-equal if their @@ -298,7 +301,7 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA, template <class ELFT> bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) { if (A->NumRelocations != B->NumRelocations || A->Flags != B->Flags || - A->getSize() != B->getSize() || A->Data != B->Data) + A->getSize() != B->getSize() || A->data() != B->data()) return false; // If two sections have different output sections, we cannot merge them. @@ -420,6 +423,21 @@ void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> Fn) { ++Cnt; } +// Combine the hashes of the sections referenced by the given section into its +// hash. +template <class ELFT, class RelTy> +static void combineRelocHashes(InputSection *IS, ArrayRef<RelTy> Rels) { + uint32_t Hash = IS->Class[1]; + for (RelTy Rel : Rels) { + Symbol &S = IS->template getFile<ELFT>()->getRelocTargetSym(Rel); + if (auto *D = dyn_cast<Defined>(&S)) + if (auto *RelSec = dyn_cast_or_null<InputSection>(D->Section)) + Hash ^= RelSec->Class[1]; + } + // Set MSB to 1 to avoid collisions with non-hash IDs. + IS->Class[0] = Hash | (1U << 31); +} + static void print(const Twine &S) { if (Config->PrintIcfSections) message(S); @@ -435,8 +453,14 @@ template <class ELFT> void ICF<ELFT>::run() { // Initially, we use hash values to partition sections. parallelForEach(Sections, [&](InputSection *S) { - // Set MSB to 1 to avoid collisions with non-hash IDs. - S->Class[0] = xxHash64(S->Data) | (1U << 31); + S->Class[1] = xxHash64(S->data()); + }); + + parallelForEach(Sections, [&](InputSection *S) { + if (S->AreRelocsRela) + combineRelocHashes<ELFT>(S, S->template relas<ELFT>()); + else + combineRelocHashes<ELFT>(S, S->template rels<ELFT>()); }); // From now on, sections in Sections vector are ordered so that sections |
