Alias->setBinding(Symbol.getBinding());
Alias->setOther(Symbol.getOther());
- if (!Symbol.isUndefined() && !Rest.startswith("@@@"))
+ // Record the rename. This serves two purposes: 1) detect multiple symbol
+ // version definitions, 2) consistently suppress the original symbol in the
+ // symbol table. GNU as keeps the original symbol for defined @ and @@, but
+ // suppresses in for other cases (@@@ or undefined). The original symbol is
+ // usually undesired and difficult to remove in an archive. Moreoever, it
+ // can cause linker issues like binutils PR/18703. If the user wants other
+ // aliases to the versioned symbol, they can copy the original symbol to
+ // other symbol names with .set directive.
+ auto R = Renames.try_emplace(&Symbol, Alias);
+ if (!R.second && R.first->second != Alias) {
+ Asm.getContext().reportError(
+ SMLoc(), llvm::Twine("multiple symbol versions defined for ") +
+ Symbol.getName());
continue;
+ }
// FIXME: Get source locations for these errors or diagnose them earlier.
if (Symbol.isUndefined() && Rest.startswith("@@") &&
" must be defined");
continue;
}
-
- if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) {
- Asm.getContext().reportError(
- SMLoc(), llvm::Twine("multiple symbol versions defined for ") +
- Symbol.getName());
- continue;
- }
-
- Renames.insert(std::make_pair(&Symbol, Alias));
}
for (const MCSymbol *&Sym : AddrsigSyms) {
-// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -r --symbols | FileCheck %s
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o
+# RUN: llvm-readelf -s %t.o | FileCheck --check-prefix=SYM %s
+# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=REL %s
-defined1:
-defined2:
-defined3:
- .symver defined1, bar1@zed
- .symver undefined1, bar2@zed
+.globl global1_impl, global2_impl, global3_impl
+local1_impl:
+local2_impl:
+local3_impl:
+global1_impl:
+global2_impl:
+global3_impl:
- .symver defined2, bar3@@zed
+# SYM: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+# SYM-NEXT: 0000000000000000 0 NOTYPE LOCAL DEFAULT 2 local1@zed
+# SYM-NEXT: 0000000000000000 0 NOTYPE LOCAL DEFAULT 2 local2@@zed
+# SYM-NEXT: 0000000000000000 0 NOTYPE LOCAL DEFAULT 2 local3@@zed
+# SYM-NEXT: 0000000000000000 0 SECTION LOCAL DEFAULT 2
+.symver local1_impl, local1@zed
+.symver local2_impl, local2@@zed
+.symver local3_impl, local3@@@zed
- .symver defined3, bar5@@@zed
- .symver undefined3, bar6@@@zed
+# SYM-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 2 global1@zed
+# SYM-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 2 global2@@zed
+# SYM-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 2 global3@@zed
+.symver global1_impl, global1@zed
+.symver global2_impl, global2@@zed
+.symver global3_impl, global3@@@zed
- .long defined1
- .long undefined1
- .long defined2
- .long defined3
- .long undefined3
+## undef3_impl@@@zed emits a non-default versioned undef3_impl@zed.
+# SYM-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND undef1@zed
+# SYM-NEXT: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND undef3@zed
+.symver undef1_impl, undef1@zed
+.symver undef3_impl, undef3@@@zed
- .global global1
- .symver global1, g1@@zed
-global1:
+## GNU as emits {local,global}{1,2}_impl (.symver acted as a copy) but not
+## {local,global}3_impl or undef{1,2,3}_impl (.symver acted as a rename).
+## We consistently treat .symver as a rename and suppress the original symbols.
+## This is advantageous because the original symbols are usually undesired
+## and can easily cause issues like binutils PR/18703.
+## If they want to retain the original symbol,
+# SYM-NOT: {{.}}
-// CHECK: Relocations [
-// CHECK-NEXT: Section {{.*}} .rela.text {
-// CHECK-NEXT: 0x0 R_X86_64_32 .text 0x0
-// CHECK-NEXT: 0x4 R_X86_64_32 bar2@zed 0x0
-// CHECK-NEXT: 0x8 R_X86_64_32 .text 0x0
-// CHECK-NEXT: 0xC R_X86_64_32 .text 0x0
-// CHECK-NEXT: 0x10 R_X86_64_32 bar6@zed 0x0
-// CHECK-NEXT: }
-// CHECK-NEXT: ]
-
-// CHECK: Symbol {
-// CHECK: Name: bar1@zed
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Local
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: bar3@@zed
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Local
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: bar5@@zed
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Local
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: defined1
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Local
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: defined2
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Local
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: .text (0)
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Local
-// CHECK-NEXT: Type: Section
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: bar2@zed
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Global
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Undefined
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: bar6@zed
-// CHECK-NEXT: Value: 0x0
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Global
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: Undefined
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: g1@@zed
-// CHECK-NEXT: Value: 0x14
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Global
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: Symbol {
-// CHECK-NEXT: Name: global1
-// CHECK-NEXT: Value: 0x14
-// CHECK-NEXT: Size: 0
-// CHECK-NEXT: Binding: Global
-// CHECK-NEXT: Type: None
-// CHECK-NEXT: Other: 0
-// CHECK-NEXT: Section: .text
-// CHECK-NEXT: }
-// CHECK-NEXT: ]
+# REL: Relocations [
+# REL-NEXT: Section {{.*}} .rela.text {
+# REL-NEXT: 0x0 R_X86_64_32 .text 0x0
+# REL-NEXT: 0x4 R_X86_64_32 .text 0x0
+# REL-NEXT: 0x8 R_X86_64_32 .text 0x0
+# REL-NEXT: 0xC R_X86_64_32 global1@zed 0x0
+# REL-NEXT: 0x10 R_X86_64_32 global2@@zed 0x0
+# REL-NEXT: 0x14 R_X86_64_32 global3@@zed 0x0
+# REL-NEXT: 0x18 R_X86_64_32 undef1@zed 0x0
+# REL-NEXT: 0x1C R_X86_64_32 undef3@zed 0x0
+# REL-NEXT: }
+# REL-NEXT: ]
+.long local1_impl
+.long local2_impl
+.long local3_impl
+.long global1_impl
+.long global2_impl
+.long global3_impl
+.long undef1_impl
+.long undef3_impl