summaryrefslogtreecommitdiffstats
path: root/lld/ELF/LinkerScript.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/LinkerScript.cpp')
-rw-r--r--lld/ELF/LinkerScript.cpp50
1 files changed, 43 insertions, 7 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 23c3a11a9d1..e6d0e455dd9 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -114,16 +114,28 @@ void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {
Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr;
}
-// This function is called from processSectionCommands,
-// while we are fixing the output section layout.
-void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
+// Used for handling linker symbol assignments, for both finalizing
+// their values and doing early declarations. Returns true if symbol
+// should be defined from linker script.
+static bool shouldDefineSym(SymbolAssignment *Cmd) {
if (Cmd->Name == ".")
- return;
+ return false;
- // If a symbol was in PROVIDE(), we need to define it only when
- // it is a referenced undefined symbol.
+ if (!Cmd->Provide)
+ return true;
+
+ // If a symbol was in PROVIDE(), we need to define it only
+ // when it is a referenced undefined symbol.
Symbol *B = Symtab->find(Cmd->Name);
- if (Cmd->Provide && (!B || B->isDefined()))
+ if (!B || B->isDefined())
+ return false;
+ return true;
+}
+
+// This function is called from processSectionCommands,
+// while we are fixing the output section layout.
+void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
+ if (!shouldDefineSym(Cmd))
return;
// Define a symbol.
@@ -153,6 +165,30 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
Cmd->Sym = cast<Defined>(Sym);
}
+// Symbols defined in script should not be inlined by LTO. At the same time
+// we don't know their final values until late stages of link. Here we scan
+// over symbol assignment commands and create placeholder symbols if needed.
+void LinkerScript::declareSymbols() {
+ assert(!Ctx);
+ for (BaseCommand *Base : SectionCommands) {
+ auto *Cmd = dyn_cast<SymbolAssignment>(Base);
+ if (!Cmd || !shouldDefineSym(Cmd))
+ continue;
+
+ // We can't calculate final value right now.
+ Symbol *Sym;
+ uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
+ std::tie(Sym, std::ignore) =
+ Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility,
+ /*CanOmitFromDynSym*/ false,
+ /*File*/ nullptr);
+ replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility,
+ STT_NOTYPE, 0, 0, nullptr);
+ Cmd->Sym = cast<Defined>(Sym);
+ Cmd->Provide = false;
+ }
+}
+
// This function is called from assignAddresses, while we are
// fixing the output section addresses. This function is supposed
// to set the final value for a given symbol assignment.
OpenPOWER on IntegriCloud