Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -43,12 +43,15 @@ struct Expr { std::function Val; std::function IsAbsolute; + std::function Section; uint64_t operator()(uint64_t Dot) const { return Val(Dot); } operator bool() const { return (bool)Val; } - Expr(std::function Val, std::function IsAbsolute) - : Val(Val), IsAbsolute(IsAbsolute) {} - template Expr(T V) : Expr(V, []() { return true; }) {} + Expr(std::function Val, std::function IsAbsolute, + std::function Section) + : Val(Val), IsAbsolute(IsAbsolute), Section(Section) {} + template + Expr(T V) : Expr(V, []() { return true; }, []() { return nullptr; }) {} Expr() : Expr(nullptr) {} }; @@ -182,14 +185,12 @@ ~LinkerScriptBase() = default; public: - virtual uint64_t getOutputSectionAddress(StringRef Name) = 0; - virtual uint64_t getOutputSectionSize(StringRef Name) = 0; - virtual uint64_t getOutputSectionAlign(StringRef Name) = 0; - virtual uint64_t getOutputSectionLMA(StringRef Name) = 0; virtual uint64_t getHeaderSize() = 0; virtual uint64_t getSymbolValue(StringRef S) = 0; virtual bool isDefined(StringRef S) = 0; virtual bool isAbsolute(StringRef S) = 0; + virtual const OutputSectionBase *getSymbolSection(StringRef S) = 0; + virtual const OutputSectionBase *getOutputSection(StringRef S) = 0; }; // ScriptConfiguration holds linker script parse results. @@ -231,14 +232,12 @@ void assignOffsets(OutputSectionCommand *Cmd); void assignAddresses(std::vector> &Phdrs); bool hasPhdrsCommands(); - uint64_t getOutputSectionAddress(StringRef Name) override; - uint64_t getOutputSectionSize(StringRef Name) override; - uint64_t getOutputSectionAlign(StringRef Name) override; - uint64_t getOutputSectionLMA(StringRef Name) override; uint64_t getHeaderSize() override; uint64_t getSymbolValue(StringRef S) override; bool isDefined(StringRef S) override; bool isAbsolute(StringRef S) override; + const OutputSectionBase *getSymbolSection(StringRef S) override; + const OutputSectionBase *getOutputSection(StringRef S) override; std::vector *OutputSections; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -75,9 +75,17 @@ } template static void addSynthetic(SymbolAssignment *Cmd) { + // If we have SECTIONS block then output sections haven't bee created yet. + const OutputSectionBase *Sec = + ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section(); Symbol *Sym = Symtab::X->addSynthetic( - Cmd->Name, nullptr, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT); + Cmd->Name, Sec, 0, Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT); Cmd->Sym = Sym->body(); + + // If we already know section then we can calculate symbol value immediately. + if (Sec) + cast>(Cmd->Sym)->Value = + Cmd->Expression(0) - Sec->Addr; } template static void addSymbol(SymbolAssignment *Cmd) { @@ -373,14 +381,14 @@ // is an offset from beginning of section and regular // symbols whose value is absolute. template -static void assignSectionSymbol(SymbolAssignment *Cmd, OutputSectionBase *Sec, +static void assignSectionSymbol(SymbolAssignment *Cmd, typename ELFT::uint Value) { if (!Cmd->Sym) return; if (auto *Body = dyn_cast>(Cmd->Sym)) { - Body->Section = Sec; - Body->Value = Cmd->Expression(Value) - Sec->Addr; + Body->Section = Cmd->Expression.Section(); + Body->Value = Cmd->Expression(Value) - Body->Section->Addr; return; } auto *Body = cast>(Cmd->Sym); @@ -452,7 +460,7 @@ CurOutSec->Size = Dot - CurOutSec->Addr; return; } - assignSectionSymbol(AssignCmd, CurOutSec, Dot); + assignSectionSymbol(AssignCmd, Dot); return; } @@ -631,8 +639,7 @@ if (Cmd->Name == ".") { Dot = Cmd->Expression(Dot); } else if (Cmd->Sym) { - assignSectionSymbol( - Cmd, CurOutSec ? CurOutSec : (*OutputSections)[0], Dot); + assignSectionSymbol(Cmd, Dot); } continue; } @@ -828,39 +835,14 @@ } template -uint64_t LinkerScript::getOutputSectionAddress(StringRef Name) { - for (OutputSectionBase *Sec : *OutputSections) - if (Sec->getName() == Name) - return Sec->Addr; - error("undefined section " + Name); - return 0; -} - -template -uint64_t LinkerScript::getOutputSectionLMA(StringRef Name) { - for (OutputSectionBase *Sec : *OutputSections) - if (Sec->getName() == Name) - return Sec->getLMA(); - error("undefined section " + Name); - return 0; -} - -template -uint64_t LinkerScript::getOutputSectionSize(StringRef Name) { - for (OutputSectionBase *Sec : *OutputSections) - if (Sec->getName() == Name) - return Sec->Size; - error("undefined section " + Name); - return 0; -} +const OutputSectionBase *LinkerScript::getOutputSection(StringRef Name) { + static OutputSectionBase FakeSec("", 0, 0); -template -uint64_t LinkerScript::getOutputSectionAlign(StringRef Name) { for (OutputSectionBase *Sec : *OutputSections) if (Sec->getName() == Name) - return Sec->Addralign; + return Sec; error("undefined section " + Name); - return 0; + return &FakeSec; } template uint64_t LinkerScript::getHeaderSize() { @@ -884,6 +866,23 @@ return DR && !DR->Section; } +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]; + } + + if (auto *DR = dyn_cast_or_null>(Sym)) + return DR->Section ? DR->Section->OutSec : nullptr; + if (auto *DS = dyn_cast_or_null>(Sym)) + return DS->Section; + + return nullptr; +} + // Returns indices of ELF headers containing specific section, identified // by Name. Each index is a zero based number of ELF header listed within // PHDRS {} script block. @@ -1490,7 +1489,11 @@ } if (Op == "+") return {[=](uint64_t Dot) { return L(Dot) + R(Dot); }, - [=]() { return L.IsAbsolute() && R.IsAbsolute(); }}; + [=]() { return L.IsAbsolute() && R.IsAbsolute(); }, + [=]() { + auto *S = L.Section(); + return S ? S : R.Section(); + }}; if (Op == "-") return [=](uint64_t Dot) { return L(Dot) - R(Dot); }; if (Op == "<<") @@ -1629,12 +1632,16 @@ // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. if (Tok == "ADDR") { StringRef Name = readParenLiteral(); - return - [=](uint64_t Dot) { return ScriptBase->getOutputSectionAddress(Name); }; + return { + [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Addr; }, + [=]() { return false; }, + [=]() { return ScriptBase->getOutputSection(Name); }}; } if (Tok == "LOADADDR") { StringRef Name = readParenLiteral(); - return [=](uint64_t Dot) { return ScriptBase->getOutputSectionLMA(Name); }; + return [=](uint64_t Dot) { + return ScriptBase->getOutputSection(Name)->getLMA(); + }; } if (Tok == "ASSERT") return readAssert(); @@ -1687,12 +1694,14 @@ } if (Tok == "SIZEOF") { StringRef Name = readParenLiteral(); - return [=](uint64_t Dot) { return ScriptBase->getOutputSectionSize(Name); }; + return + [=](uint64_t Dot) { return ScriptBase->getOutputSection(Name)->Size; }; } if (Tok == "ALIGNOF") { StringRef Name = readParenLiteral(); - return - [=](uint64_t Dot) { return ScriptBase->getOutputSectionAlign(Name); }; + return [=](uint64_t Dot) { + return ScriptBase->getOutputSection(Name)->Addralign; + }; } if (Tok == "SIZEOF_HEADERS") return [=](uint64_t Dot) { return ScriptBase->getHeaderSize(); }; @@ -1706,7 +1715,8 @@ if (Tok != "." && !isValidCIdentifier(Tok)) setError("malformed number: " + Tok); return {[=](uint64_t Dot) { return getSymbolValue(Tok, Dot); }, - [=]() { return isAbsolute(Tok); }}; + [=]() { return isAbsolute(Tok); }, + [=]() { return ScriptBase->getSymbolSection(Tok); }}; } Expr ScriptParser::readTernary(Expr Cond) { Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -64,8 +64,8 @@ Symbol *addRegular(StringRef Name, const Elf_Sym &Sym, InputSectionBase *Section); - Symbol *addSynthetic(StringRef N, OutputSectionBase *Section, uintX_t Value, - uint8_t StOther); + Symbol *addSynthetic(StringRef N, const OutputSectionBase *Section, + uintX_t Value, uint8_t StOther); void addShared(SharedFile *F, StringRef Name, const Elf_Sym &Sym, const typename ELFT::Verdef *Verdef); Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -422,7 +422,8 @@ } template -Symbol *SymbolTable::addSynthetic(StringRef N, OutputSectionBase *Section, +Symbol *SymbolTable::addSynthetic(StringRef N, + const OutputSectionBase *Section, uintX_t Value, uint8_t StOther) { Symbol *S; bool WasInserted; Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -249,7 +249,8 @@ template class DefinedSynthetic : public Defined { public: typedef typename ELFT::uint uintX_t; - DefinedSynthetic(StringRef N, uintX_t Value, OutputSectionBase *Section); + DefinedSynthetic(StringRef N, uintX_t Value, + const OutputSectionBase *Section); static bool classof(const SymbolBody *S) { return S->kind() == SymbolBody::DefinedSyntheticKind; Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -216,7 +216,7 @@ template DefinedSynthetic::DefinedSynthetic(StringRef N, uintX_t Value, - OutputSectionBase *Section) + const OutputSectionBase *Section) : Defined(SymbolBody::DefinedSyntheticKind, N, STV_HIDDEN, 0 /* Type */), Value(Value), Section(Section) {} Index: test/ELF/linkerscript/symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/symbols-synthetic.s +++ test/ELF/linkerscript/symbols-synthetic.s @@ -42,6 +42,21 @@ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# Check that we can specify synthetic symbols without defining SECTIONS. +# RUN: echo "PROVIDE_HIDDEN(_begin_sec = _start); \ +# RUN: PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text));" > %t.script +# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=NO-SEC %s + +# Check that we can do the same as above inside SECTIONS block. +# RUN: echo "SECTIONS { \ +# RUN: . = 0x11000; \ +# RUN: .text : { *(.text) } \ +# RUN: PROVIDE_HIDDEN(_begin_sec = ADDR(.text)); \ +# RUN: PROVIDE_HIDDEN(_end_sec = ADDR(.text) + SIZEOF(.text)); }" > %t.script +# RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t +# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=IN-SEC %s + # SIMPLE: 0000000000000128 .foo 00000000 .hidden _end_sec # SIMPLE-NEXT: 0000000000000120 .foo 00000000 _begin_sec # SIMPLE-NEXT: 0000000000000128 *ABS* 00000000 _end_sec_abs @@ -59,6 +74,12 @@ # SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end # SIMPLE-NEXT: 0000000000001020 *ABS* 00000000 __eh_frame_hdr_end2 +# NO-SEC: 0000000000011000 .text 00000000 .hidden _begin_sec +# NO-SEC-NEXT: 0000000000011001 .text 00000000 .hidden _end_sec + +# IN-SEC: 0000000000011000 .text 00000000 .hidden _begin_sec +# IN-SEC-NEXT: 0000000000011001 .text 00000000 .hidden _end_sec + .global _start _start: nop