diff options
| author | Eugene Leviant <evgeny.leviant@gmail.com> | 2016-09-07 07:08:43 +0000 |
|---|---|---|
| committer | Eugene Leviant <evgeny.leviant@gmail.com> | 2016-09-07 07:08:43 +0000 |
| commit | db741e7203b9246816bc911e3e5fa7b19ffc0c14 (patch) | |
| tree | 2b9cf7ba49c660b68a099eb23eb54c03695f3f62 /lld/ELF/LinkerScript.cpp | |
| parent | f333de37528567ce384554bc333386e4a474af0b (diff) | |
| download | bcm5719-llvm-db741e7203b9246816bc911e3e5fa7b19ffc0c14.tar.gz bcm5719-llvm-db741e7203b9246816bc911e3e5fa7b19ffc0c14.zip | |
Support ABSOLUE keyword in symbol assignments
This patch allows making section defined symbols absolute:
.foo : {
begin_foo = ABSOLUTE(.);
*(.foo)
}
Differential revision: https://reviews.llvm.org/D24135
llvm-svn: 280788
Diffstat (limited to 'lld/ELF/LinkerScript.cpp')
| -rw-r--r-- | lld/ELF/LinkerScript.cpp | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 5f04382a64b..8e0016a2310 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -56,6 +56,12 @@ template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) { Cmd->Sym = Sym->body(); } +template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) { + if (Cmd->IsAbsolute) + addRegular<ELFT>(Cmd); + else + addSynthetic<ELFT>(Cmd); +} // If a symbol was in PROVIDE(), we need to define it only when // it is an undefined symbol. template <class ELFT> static bool shouldDefine(SymbolAssignment *Cmd) { @@ -184,7 +190,7 @@ LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) { for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) { if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) { if (shouldDefine<ELFT>(OutCmd)) - addSynthetic<ELFT>(OutCmd); + addSymbol<ELFT>(OutCmd); OutCmd->GoesAfter = Ret.empty() ? nullptr : Ret.back(); continue; } @@ -267,6 +273,26 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) { } } +// Sets value of a section-defined symbol. Two kinds of +// symbols are processed: synthetic symbols, whose value +// is an offset from beginning of section and regular +// symbols whose value is absolute. +template <class ELFT> +static void assignSectionSymbol(SymbolAssignment *Cmd, + OutputSectionBase<ELFT> *Sec, + typename ELFT::uint Off) { + if (!Cmd->Sym) + return; + + if (auto *Body = dyn_cast<DefinedSynthetic<ELFT>>(Cmd->Sym)) { + Body->Section = Sec; + Body->Value = Cmd->Expression(Sec->getVA() + Off) - Sec->getVA(); + return; + } + auto *Body = cast<DefinedRegular<ELFT>>(Cmd->Sym); + Body->Value = Cmd->Expression(Sec->getVA() + Off); +} + // Linker script may define start and end symbols for special section types, // like .got, .eh_frame_hdr, .eh_frame and others. Those sections are not a list // of regular input input sections, therefore our way of defining symbols for @@ -280,12 +306,7 @@ void addStartEndSymbols(OutputSectionCommand *Cmd, for (std::unique_ptr<BaseCommand> &Base : Cmd->Commands) { if (auto *AssignCmd = dyn_cast<SymbolAssignment>(Base.get())) { - if (auto *Sym = cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) { - Sym->Section = Sec; - Sym->Value = - AssignCmd->Expression(Sec->getVA() + (Start ? 0 : Sec->getSize())) - - Sec->getVA(); - } + assignSectionSymbol<ELFT>(AssignCmd, Sec, Start ? 0 : Sec->getSize()); } else { if (!Start && isa<SymbolAssignment>(PrevCmd)) error("section '" + Sec->getName() + @@ -322,19 +343,13 @@ void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase<ELFT> *Sec) { if (D != AssignCmd->GoesAfter) break; - uintX_t Value = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA(); if (AssignCmd->Name == ".") { // Update to location counter means update to section size. - Off = Value; + Off = AssignCmd->Expression(Sec->getVA() + Off) - Sec->getVA(); Sec->setSize(Off); continue; } - - if (DefinedSynthetic<ELFT> *Sym = - cast_or_null<DefinedSynthetic<ELFT>>(AssignCmd->Sym)) { - Sym->Section = OutSec; - Sym->Value = Value; - } + assignSectionSymbol<ELFT>(AssignCmd, Sec, Off); } }; @@ -631,7 +646,7 @@ private: unsigned readPhdrType(); SortKind readSortKind(); SymbolAssignment *readProvideHidden(bool Provide, bool Hidden); - SymbolAssignment *readProvideOrAssignment(StringRef Tok); + SymbolAssignment *readProvideOrAssignment(StringRef Tok, bool MakeAbsolute); void readSort(); Expr readAssert(); @@ -710,7 +725,7 @@ void ScriptParser::readLinkerScript() { readSections(); } else if (Tok == "VERSION") { readVersion(); - } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok)) { + } else if (SymbolAssignment *Cmd = readProvideOrAssignment(Tok, true)) { if (Opt.HasContents) Opt.Commands.emplace_back(Cmd); else @@ -872,7 +887,7 @@ void ScriptParser::readSections() { expect("{"); while (!Error && !skip("}")) { StringRef Tok = next(); - BaseCommand *Cmd = readProvideOrAssignment(Tok); + BaseCommand *Cmd = readProvideOrAssignment(Tok, true); if (!Cmd) { if (Tok == "ASSERT") Cmd = new AssertCommand(readAssert()); @@ -1020,7 +1035,7 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) { while (!Error && !skip("}")) { StringRef Tok = next(); - if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok)) + if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok, false)) Cmd->Commands.emplace_back(Assignment); else if (Tok == "FILL") Cmd->Filler = readFill(); @@ -1063,7 +1078,8 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) { return Cmd; } -SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) { +SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok, + bool MakeAbsolute) { SymbolAssignment *Cmd = nullptr; if (peek() == "=" || peek() == "+=") { Cmd = readAssignment(Tok); @@ -1075,6 +1091,8 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) { } else if (Tok == "PROVIDE_HIDDEN") { Cmd = readProvideHidden(true, true); } + if (Cmd && MakeAbsolute) + Cmd->IsAbsolute = true; return Cmd; } @@ -1153,11 +1171,18 @@ static uint64_t getHeaderSize() { SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { StringRef Op = next(); + bool IsAbsolute = false; + Expr E; assert(Op == "=" || Op == "+="); - Expr E = readExpr(); + if (skip("ABSOLUTE")) { + E = readParenExpr(); + IsAbsolute = true; + } else { + E = readExpr(); + } if (Op == "+=") E = [=](uint64_t Dot) { return getSymbolValue(Name, Dot) + E(Dot); }; - return new SymbolAssignment(Name, E); + return new SymbolAssignment(Name, E, IsAbsolute); } // This is an operator-precedence parser to parse a linker |

