diff options
Diffstat (limited to 'ELF/LinkerScript.cpp')
-rw-r--r-- | ELF/LinkerScript.cpp | 55 |
1 files changed, 23 insertions, 32 deletions
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp index abdd899da487a..fbc0254162059 100644 --- a/ELF/LinkerScript.cpp +++ b/ELF/LinkerScript.cpp @@ -116,7 +116,8 @@ void LinkerScript::expandMemoryRegions(uint64_t Size) { if (Ctx->MemRegion) expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name, Ctx->OutSec->Name); - if (Ctx->LMARegion) + // Only expand the LMARegion if it is different from MemRegion. + if (Ctx->LMARegion && Ctx->MemRegion != Ctx->LMARegion) expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name, Ctx->OutSec->Name); } @@ -168,7 +169,7 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) { // 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, + std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, Visibility, /*CanOmitFromDynSym*/ false, /*File*/ nullptr); ExprValue Value = Cmd->Expression(); @@ -201,13 +202,14 @@ static void declareSymbol(SymbolAssignment *Cmd) { // 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, + std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, 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; + Sym->ScriptDefined = true; } // This method is used to handle INSERT AFTER statement. Here we rebuild @@ -413,18 +415,16 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { void LinkerScript::discard(ArrayRef<InputSection *> V) { for (InputSection *S : V) { - if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab || - S == InX::DynStrTab || S == InX::RelaPlt || S == InX::RelaDyn || - S == InX::RelrDyn) + if (S == In.ShStrTab || S == In.RelaDyn || S == In.RelrDyn) error("discarding " + S->Name + " section is not allowed"); // You can discard .hash and .gnu.hash sections by linker scripts. Since // they are synthesized sections, we need to handle them differently than // other regular sections. - if (S == InX::GnuHashTab) - InX::GnuHashTab = nullptr; - if (S == InX::HashTab) - InX::HashTab = nullptr; + if (S == In.GnuHashTab) + In.GnuHashTab = nullptr; + if (S == In.HashTab) + In.HashTab = nullptr; S->Assigned = false; S->Live = false; @@ -700,6 +700,7 @@ uint64_t LinkerScript::advance(uint64_t Size, unsigned Alignment) { } void LinkerScript::output(InputSection *S) { + assert(Ctx->OutSec == S->getParent()); uint64_t Before = advance(0, 1); uint64_t Pos = advance(S->getSize(), S->Alignment); S->OutSecOff = Pos - S->getSize() - Ctx->OutSec->Addr; @@ -750,6 +751,13 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) { return nullptr; } +static OutputSection *findFirstSection(PhdrEntry *Load) { + for (OutputSection *Sec : OutputSections) + if (Sec->PtLoad == Load) + return Sec; + return nullptr; +} + // This function assigns offsets to input sections and an output section // for a single sections command (e.g. ".text { *(.text); }"). void LinkerScript::assignOffsets(OutputSection *Sec) { @@ -775,8 +783,11 @@ void LinkerScript::assignOffsets(OutputSection *Sec) { // will set the LMA such that the difference between VMA and LMA for the // section is the same as the preceding output section in the same region // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html + // This, however, should only be done by the first "non-header" section + // in the segment. if (PhdrEntry *L = Ctx->OutSec->PtLoad) - L->LMAOffset = Ctx->LMAOffset; + if (Sec == findFirstSection(L)) + L->LMAOffset = Ctx->LMAOffset; // We can call this method multiple times during the creation of // thunks and want to start over calculation each time. @@ -805,21 +816,8 @@ void LinkerScript::assignOffsets(OutputSection *Sec) { // Handle a single input section description command. // It calculates and assigns the offsets for each section and also // updates the output section size. - auto *Cmd = cast<InputSectionDescription>(Base); - for (InputSection *Sec : Cmd->Sections) { - // We tentatively added all synthetic sections at the beginning and - // removed empty ones afterwards (because there is no way to know - // whether they were going be empty or not other than actually running - // linker scripts.) We need to ignore remains of empty sections. - if (auto *S = dyn_cast<SyntheticSection>(Sec)) - if (S->empty()) - continue; - - if (!Sec->Live) - continue; - assert(Ctx->OutSec == Sec->getParent()); + for (InputSection *Sec : cast<InputSectionDescription>(Base)->Sections) output(Sec); - } } } @@ -953,13 +951,6 @@ void LinkerScript::adjustSectionsAfterSorting() { } } -static OutputSection *findFirstSection(PhdrEntry *Load) { - for (OutputSection *Sec : OutputSections) - if (Sec->PtLoad == Load) - return Sec; - return nullptr; -} - static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) { // If there is no SECTIONS or if the linkerscript is explicit about program // headers, do our best to allocate them. |