From 24a01c341e5bcbe9389c3a482b08a58063b06115 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 13 Oct 2016 22:20:18 +0000 Subject: [PATCH] ELF: Override DSO definitions when creating __start_* and __stop_* symbols. Previously we would fail to synthesise a __start_ or __stop_ symbol if there existed a definition in a DSO. Instead, we would try to link against the DSO definition. This became possible after D23552 when linking against lld-produced DSOs but could in principle also occur when linking against DSOs produced by other linkers. Not only does it seem more likely that a user would expect the resolved definition to be local to the executable, but if a __start_ or __stop_ symbol was synthesised by the linker, it is effectively impossible to link against correctly from a non-PIC executable in a read-only section. Neither a PLT nor a copy relocation would give us the right semantics here. The only way the link could succeed is if the executable provided its own synthetic definition of the symbol. The fix is to also synthesise the definition if the only definition comes from a DSO. Since this is what the addOptionalSynthetic function does, switch to using that function. Fixes PR30680. Differential Revision: https://reviews.llvm.org/D25544 llvm-svn: 284168 --- lld/ELF/Writer.cpp | 20 +++++++------------- lld/test/ELF/Inputs/startstop-shared2.s | 2 ++ lld/test/ELF/startstop-shared2.s | 14 ++++++++++++++ 3 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 lld/test/ELF/Inputs/startstop-shared2.s create mode 100644 lld/test/ELF/startstop-shared2.s diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ade3ead7..5688cc2 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -546,15 +546,15 @@ void PhdrEntry::add(OutputSectionBase *Sec) { } template -static Symbol *addOptionalSynthetic(StringRef Name, - OutputSectionBase *Sec, - typename ELFT::uint Val) { +static Symbol * +addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec, + typename ELFT::uint Val, uint8_t StOther = STV_HIDDEN) { SymbolBody *S = Symtab::X->find(Name); if (!S) return nullptr; if (!S->isUndefined() && !S->isShared()) return S->symbol(); - return Symtab::X->addSynthetic(Name, Sec, Val, STV_HIDDEN); + return Symtab::X->addSynthetic(Name, Sec, Val, StOther); } template @@ -974,15 +974,9 @@ void Writer::addStartStopSymbols(OutputSectionBase *Sec) { if (!isValidCIdentifier(S)) return; StringSaver Saver(Alloc); - StringRef Start = Saver.save("__start_" + S); - StringRef Stop = Saver.save("__stop_" + S); - if (SymbolBody *B = Symtab::X->find(Start)) - if (B->isUndefined()) - Symtab::X->addSynthetic(Start, Sec, 0, B->getVisibility()); - if (SymbolBody *B = Symtab::X->find(Stop)) - if (B->isUndefined()) - Symtab::X->addSynthetic( - Stop, Sec, DefinedSynthetic::SectionEnd, B->getVisibility()); + addOptionalSynthetic(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT); + addOptionalSynthetic(Saver.save("__stop_" + S), Sec, + DefinedSynthetic::SectionEnd, STV_DEFAULT); } template diff --git a/lld/test/ELF/Inputs/startstop-shared2.s b/lld/test/ELF/Inputs/startstop-shared2.s new file mode 100644 index 0000000..414bf6d --- /dev/null +++ b/lld/test/ELF/Inputs/startstop-shared2.s @@ -0,0 +1,2 @@ +.globl __start_foo +__start_foo: diff --git a/lld/test/ELF/startstop-shared2.s b/lld/test/ELF/startstop-shared2.s new file mode 100644 index 0000000..0ba35ec --- /dev/null +++ b/lld/test/ELF/startstop-shared2.s @@ -0,0 +1,14 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/startstop-shared2.s -o %t.o +// RUN: ld.lld -o %t.so %t.o -shared +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o +// RUN: ld.lld -o %t %t2.o %t.so +// RUN: llvm-objdump -s -h %t | FileCheck %s + +// CHECK: foo 00000000 0000000000011008 + +// CHECK: Contents of section .text: +// CHECK-NEXT: 11000 08100100 00000000 + +.quad __start_foo +.section foo,"ax" -- 2.7.4