diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 90 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 4 |
2 files changed, 52 insertions, 42 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 4e8ee8bffda..14861d9bb68 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -79,25 +79,6 @@ uint64_t ExprValue::getSectionOffset() const { return getValue() - getSecAddr(); } -static SymbolBody *addRegular(SymbolAssignment *Cmd) { - 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); - Sym->Binding = STB_GLOBAL; - ExprValue Value = Cmd->Expression(); - SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; - - // We want to set symbol values early if we can. This allows us to use symbols - // as variables in linker scripts. Doing so allows us to write expressions - // like this: `alignment = 16; . = ALIGN(., alignment)` - uint64_t SymValue = Value.Sec ? 0 : Value.getValue(); - replaceBody<DefinedRegular>(Sym, nullptr, Cmd->Name, /*IsLocal=*/false, - Visibility, STT_NOTYPE, SymValue, 0, Sec); - return Sym->body(); -} - OutputSection *LinkerScript::createOutputSection(StringRef Name, StringRef Location) { OutputSection *&SecRef = NameToOutputSection[Name]; @@ -127,14 +108,55 @@ void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) { error(Loc + ": unable to move location counter backward for: " + CurAddressState->OutSec->Name); Dot = Val; + // Update to location counter means update to section size. if (InSec) CurAddressState->OutSec->Size = Dot - CurAddressState->OutSec->Addr; } -// Sets value of a 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. +// This function is called from processCommands, while we are +// fixing the output section layout. +void LinkerScript::addSymbol(SymbolAssignment *Cmd) { + if (Cmd->Name == ".") + return; + + // If a symbol was in PROVIDE(), we need to define it only when + // it is a referenced undefined symbol. + SymbolBody *B = Symtab->find(Cmd->Name); + if (Cmd->Provide && (!B || B->isDefined())) + return; + + // Define a symbol. + 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); + Sym->Binding = STB_GLOBAL; + ExprValue Value = Cmd->Expression(); + SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec; + + // When this function is called, section addresses have not been + // fixed yet. So, we may or may not know the value of the RHS + // expression. + // + // For example, if an expression is `x = 42`, we know x is always 42. + // However, if an expression is `x = .`, there's no way to know its + // value at the moment. + // + // We want to set symbol values early if we can. This allows us to + // use symbols as variables in linker scripts. Doing so allows us to + // write expressions like this: `alignment = 16; . = ALIGN(., alignment)`. + uint64_t SymValue = Value.Sec ? 0 : Value.getValue(); + + replaceBody<DefinedRegular>(Sym, nullptr, Cmd->Name, /*IsLocal=*/false, + Visibility, STT_NOTYPE, SymValue, 0, Sec); + Cmd->Sym = cast<DefinedRegular>(Sym->body()); +} + +// 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. void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { if (Cmd->Name == ".") { setDot(Cmd->Expression, Cmd->Location, InSec); @@ -144,30 +166,16 @@ void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) { if (!Cmd->Sym) return; - auto *Sym = cast<DefinedRegular>(Cmd->Sym); ExprValue V = Cmd->Expression(); if (V.isAbsolute()) { - Sym->Value = V.getValue(); - Sym->Section = nullptr; + Cmd->Sym->Section = nullptr; + Cmd->Sym->Value = V.getValue(); } else { - Sym->Section = V.Sec; - Sym->Value = V.getSectionOffset(); + Cmd->Sym->Section = V.Sec; + Cmd->Sym->Value = V.getSectionOffset(); } } -void LinkerScript::addSymbol(SymbolAssignment *Cmd) { - if (Cmd->Name == ".") - return; - - // If a symbol was in PROVIDE(), we need to define it only when - // it is a referenced undefined symbol. - SymbolBody *B = Symtab->find(Cmd->Name); - if (Cmd->Provide && (!B || B->isDefined())) - return; - - Cmd->Sym = addRegular(Cmd); -} - bool SymbolAssignment::classof(const BaseCommand *C) { return C->Kind == AssignmentKind; } @@ -359,6 +367,7 @@ void LinkerScript::processCommands(OutputSectionFactory &Factory) { Aether = make<OutputSection>("", 0, SHF_ALLOC); Aether->SectionIndex = 1; auto State = make_unique<AddressState>(Opt); + // CurAddressState captures the local AddressState and makes it accessible // deliberately. This is needed as there are some cases where we cannot just // thread the current state through to a lambda function created by the @@ -785,6 +794,7 @@ void LinkerScript::assignAddresses() { // -image-base if set. Dot = Config->ImageBase ? *Config->ImageBase : 0; auto State = make_unique<AddressState>(Opt); + // CurAddressState captures the local AddressState and makes it accessible // deliberately. This is needed as there are some cases where we cannot just // thread the current state through to a lambda function created by the diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 6aa80c82e46..26c9b20e137 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -28,7 +28,7 @@ namespace lld { namespace elf { -class DefinedCommon; +class DefinedRegular; class SymbolBody; class InputSectionBase; class InputSection; @@ -93,7 +93,7 @@ struct SymbolAssignment : BaseCommand { // The LHS of an expression. Name is either a symbol name or ".". StringRef Name; - SymbolBody *Sym = nullptr; + DefinedRegular *Sym = nullptr; // The RHS of an expression. Expr Expression; |