8080#include " SymbolTable.h"
8181#include " Symbols.h"
8282#include " SyntheticSections.h"
83+ #include " llvm/ADT/EquivalenceClasses.h"
8384#include " llvm/BinaryFormat/ELF.h"
8485#include " llvm/Object/ELF.h"
8586#include " llvm/Support/Parallel.h"
@@ -333,6 +334,28 @@ bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
333334 : constantEq (a, ra.relas , b, rb.relas );
334335}
335336
337+ template <class RelTy >
338+ static SmallVector<Symbol *> getReloc (const InputSection *sec,
339+ Relocs<RelTy> relocs) {
340+ SmallVector<Symbol *> syms;
341+ for (auto ri = relocs.begin (), re = relocs.end (); ri != re; ++ri) {
342+ Symbol &sym = sec->file ->getRelocTargetSym (*ri);
343+ syms.push_back (&sym);
344+ }
345+ return syms;
346+ }
347+
348+ template <class ELFT >
349+ static SmallVector<Symbol *> getRelocTargetSyms (const InputSection *sec) {
350+ const RelsOrRelas<ELFT> rel = sec->template relsOrRelas <ELFT>();
351+ if (rel.areRelocsCrel ())
352+ return getReloc (sec, rel.crels );
353+ if (rel.areRelocsRel ())
354+ return getReloc (sec, rel.rels );
355+
356+ return getReloc (sec, rel.relas );
357+ }
358+
336359// Compare two lists of relocations. Returns true if all pairs of
337360// relocations point to the same section in terms of ICF.
338361template <class ELFT >
@@ -537,14 +560,28 @@ template <class ELFT> void ICF<ELFT>::run() {
537560 auto print = [&ctx = ctx]() -> ELFSyncStream {
538561 return {ctx, ctx.arg .printIcfSections ? DiagLevel::Msg : DiagLevel::None};
539562 };
563+
564+ EquivalenceClasses<Symbol *> symbolEquivalence;
540565 // Merge sections by the equivalence class.
566+ // Merge symbols identified as equivalent during ICF.
541567 forEachClassRange (0 , sections.size (), [&](size_t begin, size_t end) {
542568 if (end - begin == 1 )
543569 return ;
544570 print () << " selected section " << sections[begin];
571+ SmallVector<Symbol *> syms = getRelocTargetSyms<ELFT>(sections[begin]);
545572 for (size_t i = begin + 1 ; i < end; ++i) {
546573 print () << " removing identical section " << sections[i];
547574 sections[begin]->replace (sections[i]);
575+ SmallVector<Symbol *> replacedSyms =
576+ getRelocTargetSyms<ELFT>(sections[i]);
577+ assert (syms.size () == replacedSyms.size () &&
578+ " Should have same number of syms!" );
579+ for (size_t i = 0 ; i < syms.size (); i++) {
580+ if (syms[i] == replacedSyms[i] || !syms[i]->isGlobal () ||
581+ !replacedSyms[i]->isGlobal ())
582+ continue ;
583+ symbolEquivalence.unionSets (syms[i], replacedSyms[i]);
584+ }
548585
549586 // At this point we know sections merged are fully identical and hence
550587 // we want to remove duplicate implicit dependencies such as link order
@@ -563,11 +600,26 @@ template <class ELFT> void ICF<ELFT>::run() {
563600 d->folded = true ;
564601 }
565602 };
566- for (Symbol *sym : ctx.symtab ->getSymbols ())
603+ for (Symbol *sym : ctx.symtab ->getSymbols ()) {
567604 fold (sym);
605+ auto it = symbolEquivalence.findLeader (sym);
606+ if (it != symbolEquivalence.member_end () && *it != sym) {
607+ print () << " redirecting '" << sym->getName () << " ' in symtab to '"
608+ << (*it)->getName () << " '" ;
609+ ctx.symtab ->redirect (sym, *it);
610+ }
611+ }
568612 parallelForEach (ctx.objectFiles , [&](ELFFileBase *file) {
569613 for (Symbol *sym : file->getLocalSymbols ())
570614 fold (sym);
615+ for (Symbol *&sym : file->getMutableGlobalSymbols ()) {
616+ auto it = symbolEquivalence.findLeader (sym);
617+ if (it != symbolEquivalence.member_end () && *it != sym) {
618+ print () << " redirecting '" << sym->getName () << " ' to '"
619+ << (*it)->getName () << " '" ;
620+ sym = *it;
621+ }
622+ }
571623 });
572624
573625 // InputSectionDescription::sections is populated by processSectionCommands().
0 commit comments