summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 12466e00b46..0e7d02e349e 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 de826412301..531071a4909 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 49490baa518..32d3c23047d 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 00000000000..de30cf5c2ed
--- /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
OpenPOWER on IntegriCloud