diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index ead231b8f7dc..480b2f0c25b2 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -95,7 +95,23 @@ static bool isUnderSysroot(StringRef Path) { // symbols, whose value is an offset from beginning of section and regular // symbols whose value is absolute. template -static void assignSymbol(SymbolAssignment *Cmd, typename ELFT::uint Dot = 0) { +void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { + if (Cmd->Name == ".") { + uintX_t Val = Cmd->Expression(Dot); + if (Val < Dot) { + if (InSec) + error("unable to move location counter backward for: " + + CurOutSec->Name); + else + error("unable to move location counter backward"); + } + Dot = Val; + // Update to location counter means update to section size. + if (InSec) + CurOutSec->Size = Dot - CurOutSec->Addr; + return; + } + if (!Cmd->Sym) return; @@ -113,7 +129,8 @@ static void assignSymbol(SymbolAssignment *Cmd, typename ELFT::uint Dot = 0) { cast>(Cmd->Sym)->Value = Cmd->Expression(Dot); } -template static void addSymbol(SymbolAssignment *Cmd) { +template +void LinkerScript::addSymbol(SymbolAssignment *Cmd) { if (Cmd->Name == ".") return; @@ -133,7 +150,7 @@ template static void addSymbol(SymbolAssignment *Cmd) { // If there are sections, then let the value be assigned later in // `assignAddresses`. if (!ScriptConfig->HasSections) - assignSymbol(Cmd); + assignSymbol(Cmd); } bool SymbolAssignment::classof(const BaseCommand *C) { @@ -310,7 +327,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { // Handle symbol assignments outside of any output section. if (auto *Cmd = dyn_cast(Base1.get())) { - addSymbol(Cmd); + addSymbol(Cmd); continue; } @@ -352,7 +369,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { // ".foo : { ...; bar = .; }". Handle them. for (const std::unique_ptr &Base : Cmd->Commands) if (auto *OutCmd = dyn_cast(Base.get())) - addSymbol(OutCmd); + addSymbol(OutCmd); // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign // is given, input sections are aligned to that value, whether the @@ -451,17 +468,7 @@ void LinkerScript::switchTo(OutputSectionBase *Sec) { template void LinkerScript::process(BaseCommand &Base) { // This handles the assignments to symbol or to a location counter (.) if (auto *AssignCmd = dyn_cast(&Base)) { - if (AssignCmd->Name == ".") { - // Update to location counter means update to section size. - uintX_t Val = AssignCmd->Expression(Dot); - if (Val < Dot) - error("unable to move location counter backward for: " + - CurOutSec->Name); - Dot = Val; - CurOutSec->Size = Dot - CurOutSec->Addr; - return; - } - assignSymbol(AssignCmd, Dot); + assignSymbol(AssignCmd, true); return; } @@ -784,11 +791,7 @@ void LinkerScript::assignAddresses(std::vector &Phdrs) { for (const std::unique_ptr &Base : Opt.Commands) { if (auto *Cmd = dyn_cast(Base.get())) { - if (Cmd->Name == ".") { - Dot = Cmd->Expression(Dot); - } else if (Cmd->Sym) { - assignSymbol(Cmd, Dot); - } + assignSymbol(Cmd); continue; } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 9eda62956016..2063db482627 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -275,6 +275,8 @@ public: int getSectionIndex(StringRef Name); private: + void assignSymbol(SymbolAssignment *Cmd, bool InSec = false); + void addSymbol(SymbolAssignment *Cmd); void computeInputSections(InputSectionDescription *); void discard(ArrayRef *> V); diff --git a/lld/test/ELF/linkerscript/locationcountererr2.s b/lld/test/ELF/linkerscript/locationcountererr2.s new file mode 100644 index 000000000000..fd78b30d9dc5 --- /dev/null +++ b/lld/test/ELF/linkerscript/locationcountererr2.s @@ -0,0 +1,5 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "SECTIONS { . = 0x20; . = 0x10; }" > %t.script +# RUN: not ld.lld %t.o --script %t.script -o %t -shared 2>&1 | FileCheck %s +# CHECK: unable to move location counter backward