Skip to content

Commit 5ba75f3

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

File tree

2 files changed

+48
-14
lines changed

2 files changed

+48
-14
lines changed

lld/ELF/ICF.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -334,26 +334,27 @@ 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,
337+
template <class ELFT, class RelTy>
338+
static SmallVector<std::pair<Symbol *, uint64_t>> getReloc(const InputSection *sec,
339339
Relocs<RelTy> relocs) {
340-
SmallVector<Symbol *> syms;
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>> getRelocTargets(const InputSection *sec) {
350351
const RelsOrRelas<ELFT> rel = sec->template relsOrRelas<ELFT>();
351352
if (rel.areRelocsCrel())
352-
return getReloc(sec, rel.crels);
353+
return getReloc<ELFT>(sec, rel.crels);
353354
if (rel.areRelocsRel())
354-
return getReloc(sec, rel.rels);
355+
return getReloc<ELFT>(sec, rel.rels);
355356

356-
return getReloc(sec, rel.relas);
357+
return getReloc<ELFT>(sec, rel.relas);
357358
}
358359

359360
// Compare two lists of relocations. Returns true if all pairs of
@@ -568,19 +569,19 @@ template <class ELFT> void ICF<ELFT>::run() {
568569
if (end - begin == 1)
569570
return;
570571
print() << "selected section " << sections[begin];
571-
SmallVector<Symbol *> syms = getRelocTargetSyms<ELFT>(sections[begin]);
572+
SmallVector<std::pair<Symbol *, uint64_t>> syms = getRelocTargets<ELFT>(sections[begin]);
572573
for (size_t i = begin + 1; i < end; ++i) {
573574
print() << " removing identical section " << sections[i];
574575
sections[begin]->replace(sections[i]);
575-
SmallVector<Symbol *> replacedSyms =
576-
getRelocTargetSyms<ELFT>(sections[i]);
576+
SmallVector<std::pair<Symbol *, uint64_t>> replacedSyms =
577+
getRelocTargets<ELFT>(sections[i]);
577578
assert(syms.size() == replacedSyms.size() &&
578579
"Should have same number of syms!");
579580
for (size_t i = 0; i < syms.size(); i++) {
580-
if (syms[i] == replacedSyms[i] || !syms[i]->isGlobal() ||
581-
!replacedSyms[i]->isGlobal())
581+
if (syms[i].first == replacedSyms[i].first || !syms[i].first->isGlobal() ||
582+
!replacedSyms[i].first->isGlobal() || syms[i].second != replacedSyms[i].second)
582583
continue;
583-
symbolEquivalence.unionSets(syms[i], replacedSyms[i]);
584+
symbolEquivalence.unionSets(syms[i].first, replacedSyms[i].first);
584585
}
585586

586587
// 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)