Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -26,6 +26,7 @@ class ScriptParser; template class InputSectionBase; template class OutputSectionBase; +template class SymbolTable; // This class represents each rule in SECTIONS command. struct SectionRule { @@ -38,14 +39,15 @@ }; // This enum represents what we can observe in SECTIONS tag of script: +// AssignmentKind is an assignment of a symbol to a value, like ".blah = 0x100" // ExprKind is a location counter change, like ". = . + 0x1000" // SectionKind is a description of output section, like ".data :..." -enum SectionsCommandKind { ExprKind, SectionKind }; +enum SectionsCommandKind { AssignmentKind, ExprKind, SectionKind }; struct SectionsCommand { SectionsCommandKind Kind; std::vector Expr; - StringRef SectionName; + StringRef SectionOrSymbolName; }; // ScriptConfiguration holds linker script parse results. @@ -59,6 +61,7 @@ // Used to assign addresses to sections. std::vector Commands; + bool AddSymbols = false; bool DoLayout = false; llvm::BumpPtrAllocator Alloc; @@ -79,6 +82,7 @@ ArrayRef getFiller(StringRef Name); bool isDiscarded(InputSectionBase *S); bool shouldKeep(InputSectionBase *S); + void addSymbols(); void assignAddresses(ArrayRef *> S); int compareSections(StringRef A, StringRef B); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -207,6 +207,13 @@ } template +void LinkerScript::addSymbols() { + for (SectionsCommand &Cmd : Opt.Commands) + if (Cmd.Kind == AssignmentKind) + Symtab::X->addAbsolute(Cmd.SectionOrSymbolName, STV_DEFAULT); +} + +template void LinkerScript::assignAddresses( ArrayRef *> Sections) { // Orphan sections are sections present in the input files which @@ -235,7 +242,7 @@ // ont section with such name, if the alignment, flags or type // attribute differs. for (OutputSectionBase *Sec : Sections) { - if (Sec->getName() != Cmd.SectionName) + if (Sec->getName() != Cmd.SectionOrSymbolName) continue; if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { @@ -282,7 +289,7 @@ auto Begin = Opt.Commands.begin(); auto End = Opt.Commands.end(); auto I = std::find_if(Begin, End, [&](SectionsCommand &N) { - return N.Kind == SectionKind && N.SectionName == Name; + return N.Kind == SectionKind && N.SectionOrSymbolName == Name; }); return I == End ? INT_MAX : (I - Begin); } @@ -322,7 +329,8 @@ void readSections(); void readLocationCounterValue(); - void readOutputSectionDescription(); + void readSymbolAssignment(StringRef SymName); + void readOutputSectionDescription(StringRef OutSec); const static StringMap Cmd; ScriptConfiguration &Opt = *ScriptConfig; @@ -485,16 +493,36 @@ Opt.DoLayout = true; expect("{"); while (!Error && !skip("}")) { - StringRef Tok = peek(); - if (Tok == ".") - readLocationCounterValue(); - else - readOutputSectionDescription(); + StringRef Tok = next(); + StringRef NextTok = peek(); + if (NextTok == "=") { + if (Tok == ".") + readLocationCounterValue(); + else + readSymbolAssignment(Tok); + } + else { + readOutputSectionDescription(Tok); + } + } +} + +void ScriptParser::readSymbolAssignment(StringRef SymName) { + Opt.AddSymbols = true; + expect("="); + Opt.Commands.push_back({AssignmentKind, {}, SymName}); + SectionsCommand &Cmd = Opt.Commands.back(); + while (!Error) { + StringRef Tok = next(); + if (Tok == ";") + break; + Cmd.Expr.push_back(Tok); } + if (Cmd.Expr.empty()) + error("error in symbol assignment expression"); } void ScriptParser::readLocationCounterValue() { - expect("."); expect("="); Opt.Commands.push_back({ExprKind, {}, ""}); SectionsCommand &Cmd = Opt.Commands.back(); @@ -508,8 +536,7 @@ error("error in location counter expression"); } -void ScriptParser::readOutputSectionDescription() { - StringRef OutSec = next(); +void ScriptParser::readOutputSectionDescription(StringRef OutSec) { Opt.Commands.push_back({SectionKind, {}, OutSec}); expect(":"); expect("{"); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -211,6 +211,8 @@ if (!Config->DiscardAll) copyLocalSymbols(); addReservedSymbols(); + if (ScriptConfig->AddSymbols) + Script::X->addSymbols(); createSections(); if (HasError) return; Index: test/ELF/linkerscript-assignment.s =================================================================== --- test/ELF/linkerscript-assignment.s +++ test/ELF/linkerscript-assignment.s @@ -0,0 +1,23 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o +# RUN: ld.lld -shared %t2.o -soname shared -o %t2.so + +# RUN: echo "SECTIONS { __executable_start = 0x100; }" > %t.script +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld -T %t.script %t.o -o %t +# RUN: llvm-readobj -t %t | FileCheck %s + +# CHECK: Symbol { +# CHECK: Name: __executable_start +# CHECK: Value: 0x0 +# CHECK: Size: 0 +# CHECK: Binding: Global +# CHECK: Type: None +# CHECK: Other: 0 +# CHECK: Section: Absolute +# CHECK: } + +.globl _start +_start: + ret