Skip to content

Commit c7cf960

Browse files
committed
[ELF] Set the priority of STB_GNU_UNIQUE the same as STB_WEAK
In GCC -fgnu-unique output, STB_GNU_UNIQUE symbols are always defined relative to a section in a COMDAT group. Currently `other` cannot be STB_GNU_UNIQUE for valid input, so this patch is NFC. If we switch to the model that ignores COMDAT resolution when performing symbol resolution (D120626), this will fix bogus `relocation refers to a symbol in a discarded section` errors when mixing -fno-gnu-unique objects with -fgnu-unique objects. Differential Revision: https://reviews.llvm.org/D120640
1 parent 3466b8e commit c7cf960

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

lld/ELF/Symbols.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,13 @@ bool Symbol::shouldReplace(const Defined &other) const {
528528
return false;
529529
}
530530

531-
return isWeak() && !other.isWeak();
531+
// Incoming STB_GLOBAL overrides STB_WEAK/STB_GNU_UNIQUE. -fgnu-unique changes
532+
// some vague linkage data in COMDAT from STB_WEAK to STB_GNU_UNIQUE. Treat
533+
// STB_GNU_UNIQUE like STB_WEAK so that we prefer the first among all
534+
// STB_WEAK/STB_GNU_UNIQUE copies. If we prefer an incoming STB_GNU_UNIQUE to
535+
// an existing STB_WEAK, there may be discarded section errors because the
536+
// selected copy may be in a non-prevailing COMDAT.
537+
return !isGlobal() && other.isGlobal();
532538
}
533539

534540
void elf::reportDuplicate(const Symbol &sym, InputFile *newFile,

lld/ELF/Symbols.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ class Symbol {
141141

142142
bool includeInDynsym() const;
143143
uint8_t computeBinding() const;
144+
bool isGlobal() const { return binding == llvm::ELF::STB_GLOBAL; }
144145
bool isWeak() const { return binding == llvm::ELF::STB_WEAK; }
145146

146147
bool isUndefined() const { return symbolKind == UndefinedKind; }

lld/test/ELF/comdat-binding.s

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# REQUIRES: x86
2+
# RUN: rm -rf %t && split-file %s %t
3+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/g.s -o %t/g.o
4+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/w.s -o %t/w.o
5+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %t/u.s -o %t/u.o
6+
# RUN: ld.lld -e 0 %t/w.o %t/u.o -o %t/w
7+
# RUN: llvm-readelf -s %t/w | FileCheck %s --check-prefix=WEAK
8+
# RUN: ld.lld -e 0 %t/u.o %t/w.o -o %t/u
9+
# RUN: llvm-readelf -s %t/u | FileCheck %s --check-prefix=UNIQUE
10+
11+
# RUN: ld.lld -e 0 %t/w.o %t/g.o -o %t/w
12+
# RUN: llvm-readelf -s %t/w | FileCheck %s --check-prefix=WEAK
13+
14+
# WEAK: NOTYPE WEAK DEFAULT [[#]] _ZZ1fvE1x
15+
# UNIQUE: OBJECT UNIQUE DEFAULT [[#]] _ZZ1fvE1x
16+
17+
#--- g.s
18+
movq _ZZ1fvE1x@gotpcrel(%rip), %rax
19+
20+
.section .bss._ZZ1fvE1x,"awG",@nobits,_ZZ1fvE1x,comdat
21+
.globl _ZZ1fvE1x
22+
_ZZ1fvE1x:
23+
24+
#--- w.s
25+
.section .bss._ZZ1fvE1x,"awG",@nobits,_ZZ1fvE1x,comdat
26+
.weak _ZZ1fvE1x
27+
_ZZ1fvE1x:
28+
29+
#--- u.s
30+
.section .bss._ZZ1fvE1x,"awG",@nobits,_ZZ1fvE1x,comdat
31+
.type _ZZ1fvE1x, @gnu_unique_object
32+
_ZZ1fvE1x:

0 commit comments

Comments
 (0)