aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2017-12-11 17:23:28 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2017-12-11 17:23:28 +0000
commit63fcc5cccc8aa124858a9a79e275bdc5955bf5c0 (patch)
tree4bfa8092c5c021652cfeeaee994cbe899df548a6
parent6d89f407db60a17ba723fba2ec2d72864b7a0177 (diff)
downloadllvm-63fcc5cccc8aa124858a9a79e275bdc5955bf5c0.zip
llvm-63fcc5cccc8aa124858a9a79e275bdc5955bf5c0.tar.gz
llvm-63fcc5cccc8aa124858a9a79e275bdc5955bf5c0.tar.bz2
Create reserved symbols early so they can be versioned.
This fixes pr35570. We were creating these symbols after parsing version scripts, so they could not be versioned. We cannot move the version script parsing later because we need it for lto. One option is to move both addReservedSymbols and createSyntheticSections earlier. The disadvantage is that some sections created by createSyntheticSections replace other input sections. For example, gdb index replaces .debug_gnu_pubnames, so it wants to run after gc sections so that it can set S->Live to false. What this patch does instead is to move just the ElfHeader creation early. llvm-svn: 320390
-rw-r--r--lld/ELF/Driver.cpp9
-rw-r--r--lld/ELF/Writer.cpp29
-rw-r--r--lld/ELF/Writer.h1
-rw-r--r--lld/test/ELF/linkerscript/version-linker-symbol.s28
4 files changed, 54 insertions, 13 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 12466e0..0e7d02e 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1046,6 +1046,15 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
if (Args.hasArg(OPT_exclude_libs))
excludeLibs<ELFT>(Args, Files);
+ // Create ElfHeader early. We need a dummy section in
+ // addReservedSymbols to mark the created symbols as not absolute.
+ Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC);
+ Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr);
+
+ // We need to create some reserved symbols such as _end. Create them.
+ if (!Config->Relocatable)
+ addReservedSymbols<ELFT>();
+
// Apply version scripts.
Symtab->scanVersionScript();
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index de826412..531071a4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -171,7 +171,7 @@ static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec,
// The linker is expected to define some symbols depending on
// the linking result. This function defines such symbols.
-template <class ELFT> static void addReservedSymbols() {
+template <class ELFT> void elf::addReservedSymbols() {
if (Config->EMachine == EM_MIPS) {
// Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
// so that it points to an absolute address which by default is relative
@@ -195,13 +195,8 @@ template <class ELFT> static void addReservedSymbols() {
Symtab->addAbsolute<ELFT>("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
}
- // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to
- // be at some offset from the base of the .got section, usually 0 or the end
- // of the .got
- InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot)
- : cast<InputSection>(InX::Got);
ElfSym::GlobalOffsetTable = addOptionalRegular<ELFT>(
- "_GLOBAL_OFFSET_TABLE_", GotSection, Target->GotBaseSymOff);
+ "_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff);
// __ehdr_start is the location of ELF file headers. Note that we define
// this symbol unconditionally even when using a linker script, which
@@ -260,8 +255,6 @@ template <class ELFT> static void createSyntheticSections() {
}
InX::ShStrTab = make<StringTableSection>(".shstrtab", false);
- Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC);
- Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr);
Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC);
Out::ProgramHeaders->Alignment = Config->Wordsize;
@@ -407,10 +400,6 @@ template <class ELFT> void Writer<ELFT>::run() {
if (!Config->Relocatable)
combineEhFrameSections<ELFT>();
- // We need to create some reserved symbols such as _end. Create them.
- if (!Config->Relocatable)
- addReservedSymbols<ELFT>();
-
// We want to process linker script commands. When SECTIONS command
// is given we let it create sections.
Script->processSectionCommands();
@@ -869,6 +858,15 @@ void Writer<ELFT>::forEachRelSec(std::function<void(InputSectionBase &)> Fn) {
// time any references to these symbols are processed and is equivalent to
// defining these symbols explicitly in the linker script.
template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
+ if (ElfSym::GlobalOffsetTable) {
+ // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to
+ // be at some offset from the base of the .got section, usually 0 or the end
+ // of the .got
+ InputSection *GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot)
+ : cast<InputSection>(InX::Got);
+ ElfSym::GlobalOffsetTable->Section = GotSection;
+ }
+
PhdrEntry *Last = nullptr;
PhdrEntry *LastRO = nullptr;
@@ -1935,3 +1933,8 @@ template void elf::writeResult<ELF32LE>();
template void elf::writeResult<ELF32BE>();
template void elf::writeResult<ELF64LE>();
template void elf::writeResult<ELF64BE>();
+
+template void elf::addReservedSymbols<ELF32LE>();
+template void elf::addReservedSymbols<ELF32BE>();
+template void elf::addReservedSymbols<ELF64LE>();
+template void elf::addReservedSymbols<ELF64BE>();
diff --git a/lld/ELF/Writer.h b/lld/ELF/Writer.h
index 49490ba..32d3c23 100644
--- a/lld/ELF/Writer.h
+++ b/lld/ELF/Writer.h
@@ -46,6 +46,7 @@ struct PhdrEntry {
bool HasLMA = false;
};
+template <class ELFT> void addReservedSymbols();
llvm::StringRef getOutputSectionName(InputSectionBase *S);
template <class ELFT> uint32_t calcMipsEFlags();
diff --git a/lld/test/ELF/linkerscript/version-linker-symbol.s b/lld/test/ELF/linkerscript/version-linker-symbol.s
new file mode 100644
index 0000000..de30cf5
--- /dev/null
+++ b/lld/test/ELF/linkerscript/version-linker-symbol.s
@@ -0,0 +1,28 @@
+# REQUIRES: x86
+
+# RUN: echo "VER1 { global: _end; foo ; local: * ; } ;" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# CHECK: Name: _end@@VER1
+# CHECK-NEXT: Value: 0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .dynamic
+
+# CHECK: Name: foo@@VER1
+# CHECK-NEXT: Value: 0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+
+.global foo
+foo:
+ .data
+ .quad _end
+ .quad foo