diff options
-rw-r--r-- | lld/ELF/Driver.cpp | 9 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 29 | ||||
-rw-r--r-- | lld/ELF/Writer.h | 1 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/version-linker-symbol.s | 28 |
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 |