Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -34,6 +34,16 @@ return std::min(VA, VB); } +// We want to export all symbols that exist both in the executable and in DSOs. +template +static void checkDynamicSymbolOverride(SymbolBody *L, SymbolBody *R) { + SymbolBody *O = L->isShared() ? R : L; + if (!isa>(O)) + return; + L->setUsedInDynamicReloc(); + R->setUsedInDynamicReloc(); +} + // Returns 1, 0 or -1 if this symbol should take precedence // over the Other, tie or lose, respectively. template int SymbolBody::compare(SymbolBody *Other) { @@ -50,8 +60,11 @@ Visibility = Other->Visibility = getMinVisibility(Visibility, Other->Visibility); - if (IsUsedInRegularObj || Other->IsUsedInRegularObj) + if (IsUsedInRegularObj || Other->IsUsedInRegularObj) { IsUsedInRegularObj = Other->IsUsedInRegularObj = true; + if (isShared() != Other->isShared()) + checkDynamicSymbolOverride(this, Other); + } if (L != R) return -1; Index: test/ELF/Inputs/symbol-override.s =================================================================== --- test/ELF/Inputs/symbol-override.s +++ test/ELF/Inputs/symbol-override.s @@ -0,0 +1,16 @@ +.text +.globl foo +.type foo,@function +foo: +nop + +.globl bar +.type bar,@function +bar: +nop + +.globl do +.type do,@function +do: +callq foo@PLT +callq bar@PLT Index: test/ELF/symbol-override.s =================================================================== --- test/ELF/symbol-override.s +++ test/ELF/symbol-override.s @@ -0,0 +1,46 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/symbol-override.s -o %t2.o +// RUN: ld.lld -shared %t2.o -o %t2.so +// RUN: ld.lld %t1.o %t2.so -o %t +// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s + +// CHECK: DynamicSymbols [ +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Undefined +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: do +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Function +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Undefined +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: foo +// CHECK-NEXT: Value: 0x11000 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: Function +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .text +// CHECK-NEXT: } +// CHECK-NEXT: ] + +.text +.globl foo +.type foo,@function +foo: +nop + +.text +.globl _start +_start: +callq do