From e5d3ca50318f2449a5dc9820a1012903ffb03824 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 31 Aug 2016 15:31:17 +0000 Subject: [PATCH] [ELF] Linkerscript: define symbols outside SECTIONS Symbol assignments outside of SECTIONS command need to be created even when SECTIONS command is not used. Differential Revision: https://reviews.llvm.org/D23751 llvm-svn: 280252 --- lld/ELF/LinkerScript.cpp | 22 +++++++++++++++---- lld/ELF/LinkerScript.h | 3 +++ lld/ELF/Writer.cpp | 2 ++ .../ELF/linkerscript/linkerscript-symbols.s | 9 ++++++++ 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index e1a99b10a95d..940323301856 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -258,6 +258,16 @@ LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) { return Ret; } +template +void LinkerScript::createAssignments() { + for (const std::unique_ptr &Cmd : Opt.Assignments) { + if (shouldDefine(Cmd.get())) + addRegular(Cmd.get()); + if (Cmd->Sym) + cast>(Cmd->Sym)->Value = Cmd->Expression(0); + } +} + template void LinkerScript::createSections(OutputSectionFactory &Factory) { for (const std::unique_ptr &Base1 : Opt.Commands) { @@ -714,12 +724,16 @@ void ScriptParser::readVersionScript() { void ScriptParser::readLinkerScript() { while (!atEOF()) { StringRef Tok = next(); - if (Handler Fn = Cmd.lookup(Tok)) + if (Handler Fn = Cmd.lookup(Tok)) { (this->*Fn)(); - else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) - Opt.Commands.emplace_back(Cmd); - else + } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) { + if (Opt.HasContents) + Opt.Commands.emplace_back(Cmd); + else + Opt.Assignments.emplace_back(Cmd); + } else { setError("unknown directive: " + Tok); + } } } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index f08bd0762b5f..a866470fa034 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -118,6 +118,8 @@ struct PhdrsCommand { // ScriptConfiguration holds linker script parse results. struct ScriptConfiguration { + // Used to create symbol assignments outside SECTIONS command. + std::vector> Assignments; // Used to assign addresses to sections. std::vector> Commands; @@ -142,6 +144,7 @@ template class LinkerScript { public: LinkerScript(); ~LinkerScript(); + void createAssignments(); void createSections(OutputSectionFactory &Factory); std::vector> createPhdrs(); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index a3c59d45261a..3475de80279d 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -249,6 +249,8 @@ template void Writer::run() { CommonInputSection Common(getCommonSymbols()); CommonInputSection::X = &Common; + Script::X->createAssignments(); + Script::X->OutputSections = &OutputSections; if (ScriptConfig->HasContents) Script::X->createSections(Factory); diff --git a/lld/test/ELF/linkerscript/linkerscript-symbols.s b/lld/test/ELF/linkerscript/linkerscript-symbols.s index 8136b5fd5c51..f8b0a31e3b93 100644 --- a/lld/test/ELF/linkerscript/linkerscript-symbols.s +++ b/lld/test/ELF/linkerscript/linkerscript-symbols.s @@ -67,6 +67,15 @@ # RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=HIDDEN5 %s # HIDDEN5: 0000000000000000 *ABS* 00000000 somesym +# Simple symbol assignment. All three symbols should have the +# same value. +# RUN: echo "foo = 0x100; SECTIONS { bar = foo; } baz = bar;" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE2 %s +# SIMPLE2: 0000000000000100 *ABS* 00000000 foo +# SIMPLE2: 0000000000000100 *ABS* 00000000 bar +# SIMPLE2: 0000000000000100 *ABS* 00000000 baz + .global _start _start: nop