Skip to content

Commit 9c00cc1

Browse files
committed
[lld][ICF] Don't merge symbols with different addends
1 parent 2403865 commit 9c00cc1

File tree

2 files changed

+52
-15
lines changed

2 files changed

+52
-15
lines changed

lld/ELF/ICF.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -334,26 +334,28 @@ bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
334334
: constantEq(a, ra.relas, b, rb.relas);
335335
}
336336

337-
template <class RelTy>
338-
static SmallVector<Symbol *> getReloc(const InputSection *sec,
339-
Relocs<RelTy> relocs) {
340-
SmallVector<Symbol *> syms;
337+
template <class ELFT, class RelTy>
338+
static SmallVector<std::pair<Symbol *, uint64_t>>
339+
getReloc(const InputSection *sec, Relocs<RelTy> relocs) {
340+
SmallVector<std::pair<Symbol *, uint64_t>> syms;
341341
for (auto ri = relocs.begin(), re = relocs.end(); ri != re; ++ri) {
342342
Symbol &sym = sec->file->getRelocTargetSym(*ri);
343-
syms.push_back(&sym);
343+
uint64_t addend = getAddend<ELFT>(*ri);
344+
syms.push_back(std::make_pair(&sym, addend));
344345
}
345346
return syms;
346347
}
347348

348349
template <class ELFT>
349-
static SmallVector<Symbol *> getRelocTargetSyms(const InputSection *sec) {
350+
static SmallVector<std::pair<Symbol *, uint64_t>>
351+
getRelocTargets(const InputSection *sec) {
350352
const RelsOrRelas<ELFT> rel = sec->template relsOrRelas<ELFT>();
351353
if (rel.areRelocsCrel())
352-
return getReloc(sec, rel.crels);
354+
return getReloc<ELFT>(sec, rel.crels);
353355
if (rel.areRelocsRel())
354-
return getReloc(sec, rel.rels);
356+
return getReloc<ELFT>(sec, rel.rels);
355357

356-
return getReloc(sec, rel.relas);
358+
return getReloc<ELFT>(sec, rel.relas);
357359
}
358360

359361
// Compare two lists of relocations. Returns true if all pairs of
@@ -568,19 +570,21 @@ template <class ELFT> void ICF<ELFT>::run() {
568570
if (end - begin == 1)
569571
return;
570572
print() << "selected section " << sections[begin];
571-
SmallVector<Symbol *> syms = getRelocTargetSyms<ELFT>(sections[begin]);
573+
SmallVector<std::pair<Symbol *, uint64_t>> syms =
574+
getRelocTargets<ELFT>(sections[begin]);
572575
for (size_t i = begin + 1; i < end; ++i) {
573576
print() << " removing identical section " << sections[i];
574577
sections[begin]->replace(sections[i]);
575-
SmallVector<Symbol *> replacedSyms =
576-
getRelocTargetSyms<ELFT>(sections[i]);
578+
SmallVector<std::pair<Symbol *, uint64_t>> replacedSyms =
579+
getRelocTargets<ELFT>(sections[i]);
577580
assert(syms.size() == replacedSyms.size() &&
578581
"Should have same number of syms!");
579582
for (size_t i = 0; i < syms.size(); i++) {
580-
if (syms[i] == replacedSyms[i] || !syms[i]->isGlobal() ||
581-
!replacedSyms[i]->isGlobal())
583+
if (syms[i].first == replacedSyms[i].first ||
584+
!syms[i].first->isGlobal() || !replacedSyms[i].first->isGlobal() ||
585+
syms[i].second != replacedSyms[i].second)
582586
continue;
583-
symbolEquivalence.unionSets(syms[i], replacedSyms[i]);
587+
symbolEquivalence.unionSets(syms[i].first, replacedSyms[i].first);
584588
}
585589

586590
// At this point we know sections merged are fully identical and hence

lld/test/ELF/icf-addend.s

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# REQUIRES: x86
2+
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3+
# RUN: ld.lld %t.o -o /dev/null --icf=all --print-icf-sections | FileCheck %s
4+
5+
# Check that ICF doesn't fold different symbols when functions referencing them
6+
# can be folded because they are pointing to the same address.
7+
8+
# CHECK: selected section {{.*}}:(.text.f1)
9+
# CHECK: removing identical section {{.*}}:(.text.f2)
10+
# CHECK-NOT: redirecting 'y' in symtab to 'x'
11+
# CHECK-NOT: redirecting 'y' to 'x'
12+
13+
.globl x, y
14+
15+
.section .rodata,"a",@progbits
16+
x:
17+
.long 11
18+
y:
19+
.long 12
20+
21+
.section .text.f1,"ax",@progbits
22+
f1:
23+
movq x+4(%rip), %rax
24+
25+
.section .text.f2,"ax",@progbits
26+
f2:
27+
movq y(%rip), %rax
28+
29+
.section .text._start,"ax",@progbits
30+
.globl _start
31+
_start:
32+
call f1
33+
call f2

0 commit comments

Comments
 (0)