From 06f4743a48f8908d094bbb51eec6ce14df6f84c6 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 6 Feb 2017 22:21:46 +0000 Subject: [PATCH] Handle symbol assignments before the first section switch. We now create a dummy section with index 1 before processing the linker script. Thanks to George Rimar for finding the bug and providing the initial testcase. llvm-svn: 294252 --- lld/ELF/LinkerScript.cpp | 24 +++++++++++++++-------- lld/test/ELF/linkerscript/non-absolute2.s | 12 ++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 lld/test/ELF/linkerscript/non-absolute2.s diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 3a9dc9fde331..2e707e7a2134 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -776,6 +776,19 @@ void LinkerScript::assignAddresses(std::vector &Phdrs) { // Assign addresses as instructed by linker script SECTIONS sub-commands. Dot = 0; + // A symbol can be assigned before any section is mentioned in the linker + // script. In an DSO, the symbol values are addresses, so the only important + // section values are: + // * SHN_UNDEF + // * SHN_ABS + // * Any value meaning a regular section. + // To handle that, create a dummy aether section that fills the void before + // the linker scripts switches to another section. It has an index of one + // which will map to whatever the first actual section is. + auto *Aether = make("", 0, SHF_ALLOC); + Aether->SectionIndex = 1; + switchTo(Aether); + for (const std::unique_ptr &Base : Opt.Commands) { if (auto *Cmd = dyn_cast(Base.get())) { if (Cmd->Name == ".") { @@ -973,14 +986,9 @@ template bool LinkerScript::isAbsolute(StringRef S) { // to find suitable section for it as well. template const OutputSectionBase *LinkerScript::getSymbolSection(StringRef S) { - SymbolBody *Sym = Symtab::X->find(S); - if (!Sym) { - if (OutputSections->empty()) - return nullptr; - return CurOutSec ? CurOutSec : (*OutputSections)[0]; - } - - return SymbolTableSection::getOutputSection(Sym); + if (SymbolBody *Sym = Symtab::X->find(S)) + return SymbolTableSection::getOutputSection(Sym); + return CurOutSec; } // Returns indices of ELF headers containing specific section, identified diff --git a/lld/test/ELF/linkerscript/non-absolute2.s b/lld/test/ELF/linkerscript/non-absolute2.s new file mode 100644 index 000000000000..97c34d31a912 --- /dev/null +++ b/lld/test/ELF/linkerscript/non-absolute2.s @@ -0,0 +1,12 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o +# RUN: echo "SECTIONS { A = . + 0x1; . += 0x1000; }" > %t.script +# RUN: ld.lld -shared %t1.o --script %t.script -o %t +# RUN: llvm-objdump -section-headers -t %t | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000000 0000000000001000 + +# CHECK: 0000000000000001 .text 00000000 A