[ELF] Add Section() to expression object
This allows making symbols containing ADDR(section) synthetic,
and defining synthetic symbols outside SECTIONS block.
Differential revision: https://reviews.llvm.org/D25441
llvm-svn: 287090
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 1f65c37..5bf3692 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -75,9 +75,17 @@
}
template <class ELFT> static void addSynthetic(SymbolAssignment *Cmd) {
+ // If we have SECTIONS block then output sections haven't been created yet.
+ const OutputSectionBase *Sec =
+ ScriptConfig->HasSections ? nullptr : Cmd->Expression.Section();
Symbol *Sym = Symtab<ELFT>::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<DefinedSynthetic<ELFT>>(Cmd->Sym)->Value =
+ Cmd->Expression(0) - Sec->Addr;
}
template <class ELFT> static void addSymbol(SymbolAssignment *Cmd) {
@@ -373,14 +381,14 @@
// is an offset from beginning of section and regular
// symbols whose value is absolute.
template <class ELFT>
-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<DefinedSynthetic<ELFT>>(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<DefinedRegular<ELFT>>(Cmd->Sym);
@@ -452,7 +460,7 @@
CurOutSec->Size = Dot - CurOutSec->Addr;
return;
}
- assignSectionSymbol<ELFT>(AssignCmd, CurOutSec, Dot);
+ assignSectionSymbol<ELFT>(AssignCmd, Dot);
return;
}
@@ -667,8 +675,7 @@
if (Cmd->Name == ".") {
Dot = Cmd->Expression(Dot);
} else if (Cmd->Sym) {
- assignSectionSymbol<ELFT>(
- Cmd, CurOutSec ? CurOutSec : (*OutputSections)[0], Dot);
+ assignSectionSymbol<ELFT>(Cmd, Dot);
}
continue;
}
@@ -849,39 +856,14 @@
}
template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionAddress(StringRef Name) {
- for (OutputSectionBase *Sec : *OutputSections)
- if (Sec->getName() == Name)
- return Sec->Addr;
- error("undefined section " + Name);
- return 0;
-}
+const OutputSectionBase *LinkerScript<ELFT>::getOutputSection(StringRef Name) {
+ static OutputSectionBase FakeSec("", 0, 0);
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionLMA(StringRef Name) {
for (OutputSectionBase *Sec : *OutputSections)
if (Sec->getName() == Name)
- return Sec->getLMA();
+ return Sec;
error("undefined section " + Name);
- return 0;
-}
-
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {
- for (OutputSectionBase *Sec : *OutputSections)
- if (Sec->getName() == Name)
- return Sec->Size;
- error("undefined section " + Name);
- return 0;
-}
-
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::getOutputSectionAlign(StringRef Name) {
- for (OutputSectionBase *Sec : *OutputSections)
- if (Sec->getName() == Name)
- return Sec->Addralign;
- error("undefined section " + Name);
- return 0;
+ return &FakeSec;
}
template <class ELFT> uint64_t LinkerScript<ELFT>::getHeaderSize() {
@@ -905,6 +887,26 @@
return DR && !DR->Section;
}
+// Gets section symbol belongs to. Symbol "." doesn't belong to any
+// specific section but isn't absolute at the same time, so we try
+// to find suitable section for it as well.
+template <class ELFT>
+const OutputSectionBase *LinkerScript<ELFT>::getSymbolSection(StringRef S) {
+ SymbolBody *Sym = Symtab<ELFT>::X->find(S);
+ if (!Sym) {
+ if (OutputSections->empty())
+ return nullptr;
+ return CurOutSec ? CurOutSec : (*OutputSections)[0];
+ }
+
+ if (auto *DR = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym))
+ return DR->Section ? DR->Section->OutSec : nullptr;
+ if (auto *DS = dyn_cast_or_null<DefinedSynthetic<ELFT>>(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.
@@ -1511,7 +1513,11 @@
}
if (Op == "+")
return {[=](uint64_t Dot) { return L(Dot) + R(Dot); },
- [=]() { return L.IsAbsolute() && R.IsAbsolute(); }};
+ [=]() { return L.IsAbsolute() && R.IsAbsolute(); },
+ [=]() {
+ const OutputSectionBase *S = L.Section();
+ return S ? S : R.Section();
+ }};
if (Op == "-")
return [=](uint64_t Dot) { return L(Dot) - R(Dot); };
if (Op == "<<")
@@ -1650,12 +1656,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();
@@ -1708,12 +1718,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(); };
@@ -1727,7 +1739,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) {