Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -24,8 +24,6 @@ template class OutputSectionBase; template class OutputSectionFactory; -typedef std::function Expr; - // Parses a linker script. Calling this function updates // Config and ScriptConfig. void readLinkerScript(MemoryBufferRef MB); @@ -49,11 +47,11 @@ }; struct SymbolAssignment : BaseCommand { - SymbolAssignment(StringRef Name, Expr E) - : BaseCommand(AssignmentKind), Name(Name), Expression(E) {} + SymbolAssignment(StringRef Name, std::function Expr) + : BaseCommand(AssignmentKind), Name(Name), Expr(Expr) {} static bool classof(const BaseCommand *C); StringRef Name; - Expr Expression; + std::function Expr; bool Provide = false; // Hidden and Ignore can be true, only if Provide is true bool Hidden = false; @@ -107,6 +105,9 @@ // List of section patterns specified with KEEP commands. They will // be kept even if they are unused and --gc-sections is specified. std::vector KeptSections; + + // The current value of the special variable ".". + uint64_t Dot = 0; }; extern ScriptConfiguration *ScriptConfig; @@ -136,8 +137,6 @@ int getSectionIndex(StringRef Name); std::vector getPhdrIndices(StringRef SectionName); void dispatchAssignment(SymbolAssignment *Cmd); - - uintX_t Dot; }; // Variable template is a C++14 feature, so we can't template Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -152,12 +152,11 @@ template void LinkerScript::dispatchAssignment(SymbolAssignment *Cmd) { - uint64_t Val = Cmd->Expression(Dot); if (Cmd->Name == ".") { - Dot = Val; + Opt.Dot = Cmd->Expr(); } else if (!Cmd->Ignore) { auto *D = cast>(Symtab::X->find(Cmd->Name)); - D->Value = Val; + D->Value = Cmd->Expr(); } } @@ -176,7 +175,8 @@ } // Assign addresses as instructed by linker script SECTIONS sub-commands. - Dot = Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); + Opt.Dot = + Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); uintX_t MinVA = std::numeric_limits::max(); uintX_t ThreadBssOffset = 0; @@ -195,18 +195,18 @@ continue; if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { - uintX_t TVA = Dot + ThreadBssOffset; + uintX_t TVA = Opt.Dot + ThreadBssOffset; TVA = alignTo(TVA, Sec->getAlignment()); Sec->setVA(TVA); - ThreadBssOffset = TVA - Dot + Sec->getSize(); + ThreadBssOffset = TVA - Opt.Dot + Sec->getSize(); continue; } if (Sec->getFlags() & SHF_ALLOC) { - Dot = alignTo(Dot, Sec->getAlignment()); - Sec->setVA(Dot); - MinVA = std::min(MinVA, Dot); - Dot += Sec->getSize(); + Opt.Dot = alignTo(Opt.Dot, Sec->getAlignment()); + Sec->setVA(Opt.Dot); + MinVA = std::min(MinVA, (uintX_t)Opt.Dot); + Opt.Dot += Sec->getSize(); continue; } } @@ -421,11 +421,13 @@ unsigned readPhdrType(); void readProvide(bool Hidden); - Expr readExpr(); - Expr readExpr1(Expr Lhs, int MinPrec); - Expr readPrimary(); - Expr readTernary(Expr Cond); - Expr combine(StringRef Op, Expr Lhs, Expr Rhs); + std::function readExpr(); + std::function readExpr1(std::function Lhs, + int MinPrec); + std::function readPrimary(); + std::function readTernary(std::function Cond); + std::function combine(StringRef Op, std::function Lhs, + std::function Rhs); const static StringMap Cmd; ScriptConfiguration &Opt = *ScriptConfig; @@ -710,19 +712,21 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { expect("="); - Expr E = readExpr(); - auto *Cmd = new SymbolAssignment(Name, E); + auto *Cmd = new SymbolAssignment(Name, readExpr()); Opt.Commands.emplace_back(Cmd); return Cmd; } // This is an operator-precedence parser to parse a linker // script expression. -Expr ScriptParser::readExpr() { return readExpr1(readPrimary(), 0); } +std::function ScriptParser::readExpr() { + return readExpr1(readPrimary(), 0); +} // This is a part of the operator-precedence parser. This function // assumes that the remaining token stream starts with an operator. -Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) { +std::function ScriptParser::readExpr1(std::function Lhs, + int MinPrec) { while (!atEOF() && !Error) { // Read an operator and an expression. StringRef Op1 = peek(); @@ -731,7 +735,7 @@ if (precedence(Op1) < MinPrec) break; next(); - Expr Rhs = readPrimary(); + std::function Rhs = readPrimary(); // Evaluate the remaining part of the expression first if the // next operator has greater precedence than the previous one. @@ -756,14 +760,14 @@ return 0; } -Expr ScriptParser::readPrimary() { +std::function ScriptParser::readPrimary() { StringRef Tok = next(); if (Tok == ".") - return [](uint64_t Dot) { return Dot; }; + return []() { return ScriptConfig->Dot; }; if (Tok == "(") { - Expr E = readExpr(); + std::function E = readExpr(); expect(")"); return E; } @@ -772,24 +776,25 @@ // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html. if (Tok == "ALIGN") { expect("("); - Expr E = readExpr(); + std::function E = readExpr(); expect(")"); - return [=](uint64_t Dot) { return alignTo(Dot, E(Dot)); }; + return [=]() { return alignTo(ScriptConfig->Dot, E()); }; } if (Tok == "CONSTANT") { expect("("); StringRef Tok = next(); expect(")"); - return [=](uint64_t Dot) { return getConstant(Tok); }; + return [=]() { return getConstant(Tok); }; } if (Tok == "DATA_SEGMENT_ALIGN") { expect("("); - Expr E = readExpr(); + std::function E = readExpr(); expect(","); readExpr(); expect(")"); - return [=](uint64_t Dot) -> uint64_t { - uint64_t Val = E(Dot); + return [=]() -> uint64_t { + uint64_t Val = E(); + uint64_t Dot = ScriptConfig->Dot; return alignTo(Dot, Val) + (Dot & (Val - 1)); }; } @@ -797,55 +802,58 @@ expect("("); expect("."); expect(")"); - return [](uint64_t Dot) { return Dot; }; + return []() { return ScriptConfig->Dot; }; } // Parse a number literal uint64_t V = 0; if (Tok.getAsInteger(0, V)) setError("malformed number: " + Tok); - return [=](uint64_t Dot) { return V; }; + return [=]() { return V; }; } -Expr ScriptParser::readTernary(Expr Cond) { +std::function +ScriptParser::readTernary(std::function Cond) { next(); - Expr L = readExpr(); + std::function L = readExpr(); expect(":"); - Expr R = readExpr(); - return [=](uint64_t Dot) { return Cond(Dot) ? L(Dot) : R(Dot); }; + std::function R = readExpr(); + return [=]() { return Cond() ? L() : R(); }; } -Expr ScriptParser::combine(StringRef Op, Expr L, Expr R) { +std::function ScriptParser::combine(StringRef Op, + std::function L, + std::function R) { if (Op == "*") - return [=](uint64_t Dot) { return L(Dot) * R(Dot); }; + return [=]() { return L() * R(); }; if (Op == "/") { - return [=](uint64_t Dot) -> uint64_t { - uint64_t RHS = R(Dot); + return [=]() -> uint64_t { + uint64_t RHS = R(); if (RHS == 0) { error("division by zero"); return 0; } - return L(Dot) / RHS; + return L() / RHS; }; } if (Op == "+") - return [=](uint64_t Dot) { return L(Dot) + R(Dot); }; + return [=]() { return L() + R(); }; if (Op == "-") - return [=](uint64_t Dot) { return L(Dot) - R(Dot); }; + return [=]() { return L() - R(); }; if (Op == "<") - return [=](uint64_t Dot) { return L(Dot) < R(Dot); }; + return [=]() { return L() < R(); }; if (Op == ">") - return [=](uint64_t Dot) { return L(Dot) > R(Dot); }; + return [=]() { return L() > R(); }; if (Op == ">=") - return [=](uint64_t Dot) { return L(Dot) >= R(Dot); }; + return [=]() { return L() >= R(); }; if (Op == "<=") - return [=](uint64_t Dot) { return L(Dot) <= R(Dot); }; + return [=]() { return L() <= R(); }; if (Op == "==") - return [=](uint64_t Dot) { return L(Dot) == R(Dot); }; + return [=]() { return L() == R(); }; if (Op == "!=") - return [=](uint64_t Dot) { return L(Dot) != R(Dot); }; + return [=]() { return L() != R(); }; if (Op == "&") - return [=](uint64_t Dot) { return L(Dot) & R(Dot); }; + return [=]() { return L() & R(); }; llvm_unreachable("invalid operator"); }