diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:08:33 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:08:33 +0000 | 
| commit | 20d35e67e67f106f617c939725101223211659f0 (patch) | |
| tree | 64eb963cbf5ba58765e0a6b64a440965d66a7a4d /ELF/LinkerScript.cpp | |
| parent | ae1a339de31cf4065777531959a11e55a2e5fa00 (diff) | |
Notes
Diffstat (limited to 'ELF/LinkerScript.cpp')
| -rw-r--r-- | ELF/LinkerScript.cpp | 413 | 
1 files changed, 272 insertions, 141 deletions
| diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp index 8f50a977fd75..abdd899da487 100644 --- a/ELF/LinkerScript.cpp +++ b/ELF/LinkerScript.cpp @@ -15,13 +15,13 @@  #include "Config.h"  #include "InputSection.h"  #include "OutputSections.h" -#include "Strings.h"  #include "SymbolTable.h"  #include "Symbols.h"  #include "SyntheticSections.h"  #include "Target.h"  #include "Writer.h"  #include "lld/Common/Memory.h" +#include "lld/Common/Strings.h"  #include "lld/Common/Threads.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/StringRef.h" @@ -74,7 +74,7 @@ uint64_t ExprValue::getSectionOffset() const {    // If the alignment is trivial, we don't have to compute the full    // value to know the offset. This allows this function to succeed in    // cases where the output section is not yet known. -  if (Alignment == 1) +  if (Alignment == 1 && (!Sec || !Sec->getOutputSection()))      return Val;    return getValue() - getSecAddr();  } @@ -102,28 +102,67 @@ OutputSection *LinkerScript::getOrCreateOutputSection(StringRef Name) {    return CmdRef;  } +// Expands the memory region by the specified size. +static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size, +                               StringRef RegionName, StringRef SecName) { +  MemRegion->CurPos += Size; +  uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin; +  if (NewSize > MemRegion->Length) +    error("section '" + SecName + "' will not fit in region '" + RegionName + +          "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes"); +} + +void LinkerScript::expandMemoryRegions(uint64_t Size) { +  if (Ctx->MemRegion) +    expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name, +                       Ctx->OutSec->Name); +  if (Ctx->LMARegion) +    expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name, +                       Ctx->OutSec->Name); +} + +void LinkerScript::expandOutputSection(uint64_t Size) { +  Ctx->OutSec->Size += Size; +  expandMemoryRegions(Size); +} +  void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {    uint64_t Val = E().getValue();    if (Val < Dot && InSec)      error(Loc + ": unable to move location counter backward for: " +            Ctx->OutSec->Name); -  Dot = Val;    // Update to location counter means update to section size.    if (InSec) -    Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr; +    expandOutputSection(Val - Dot); +  else +    expandMemoryRegions(Val - Dot); + +  Dot = Val;  } -// 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 true; +  return false; +} + +// 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 +192,76 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) {    Cmd->Sym = cast<Defined>(Sym);  } +// This function is called from LinkerScript::declareSymbols. +// It creates a placeholder symbol if needed. +static void declareSymbol(SymbolAssignment *Cmd) { +  if (!shouldDefineSym(Cmd)) +    return; + +  // 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 method is used to handle INSERT AFTER statement. Here we rebuild +// the list of script commands to mix sections inserted into. +void LinkerScript::processInsertCommands() { +  std::vector<BaseCommand *> V; +  auto Insert = [&](std::vector<BaseCommand *> &From) { +    V.insert(V.end(), From.begin(), From.end()); +    From.clear(); +  }; + +  for (BaseCommand *Base : SectionCommands) { +    if (auto *OS = dyn_cast<OutputSection>(Base)) { +      Insert(InsertBeforeCommands[OS->Name]); +      V.push_back(Base); +      Insert(InsertAfterCommands[OS->Name]); +      continue; +    } +    V.push_back(Base); +  } + +  for (auto &Cmds : {InsertBeforeCommands, InsertAfterCommands}) +    for (const std::pair<StringRef, std::vector<BaseCommand *>> &P : Cmds) +      if (!P.second.empty()) +        error("unable to INSERT AFTER/BEFORE " + P.first + +              ": section not defined"); + +  SectionCommands = std::move(V); +} + +// 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) { +    if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { +      declareSymbol(Cmd); +      continue; +    } + +    // If the output section directive has constraints, +    // we can't say for sure if it is going to be included or not. +    // Skip such sections for now. Improve the checks if we ever +    // need symbols from that sections to be declared early. +    auto *Sec = cast<OutputSection>(Base); +    if (Sec->Constraint != ConstraintKind::NoConstraint) +      continue; +    for (BaseCommand *Base2 : Sec->SectionCommands) +      if (auto *Cmd = dyn_cast<SymbolAssignment>(Base2)) +        declareSymbol(Cmd); +  } +} +  // 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. @@ -249,23 +358,11 @@ static void sortSections(MutableArrayRef<InputSection *> Vec,  //    --sort-section is handled as an inner SORT command.  // 3. If one SORT command is given, and if it is SORT_NONE, don't sort.  // 4. If no SORT command is given, sort according to --sort-section. -// 5. If no SORT commands are given and --sort-section is not specified, -//    apply sorting provided by --symbol-ordering-file if any exist. -static void sortInputSections( -    MutableArrayRef<InputSection *> Vec, const SectionPattern &Pat, -    const DenseMap<SectionBase *, int> &Order) { +static void sortInputSections(MutableArrayRef<InputSection *> Vec, +                              const SectionPattern &Pat) {    if (Pat.SortOuter == SortSectionPolicy::None)      return; -  if (Pat.SortOuter == SortSectionPolicy::Default && -      Config->SortSection == SortSectionPolicy::Default) { -    // If -symbol-ordering-file was given, sort accordingly. -    // Usually, Order is empty. -    if (!Order.empty()) -      sortByOrder(Vec, [&](InputSectionBase *S) { return Order.lookup(S); }); -    return; -  } -    if (Pat.SortInner == SortSectionPolicy::Default)      sortSections(Vec, Config->SortSection);    else @@ -275,8 +372,7 @@ static void sortInputSections(  // Compute and remember which sections the InputSectionDescription matches.  std::vector<InputSection *> -LinkerScript::computeInputSections(const InputSectionDescription *Cmd, -                                   const DenseMap<SectionBase *, int> &Order) { +LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {    std::vector<InputSection *> Ret;    // Collects all sections that satisfy constraints of Cmd. @@ -290,8 +386,11 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd,        // For -emit-relocs we have to ignore entries like        //   .rela.dyn : { *(.rela.data) }        // which are common because they are in the default bfd script. -      if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA) -        continue; +      // We do not ignore SHT_REL[A] linker-synthesized sections here because +      // want to support scripts that do custom layout for them. +      if (auto *IS = dyn_cast<InputSection>(Sec)) +        if (IS->getRelocatedSection()) +          continue;        std::string Filename = getFilename(Sec->File);        if (!Cmd->FilePat.match(Filename) || @@ -307,7 +406,7 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd,      }      sortInputSections(MutableArrayRef<InputSection *>(Ret).slice(SizeBefore), -                      Pat, Order); +                      Pat);    }    return Ret;  } @@ -315,22 +414,31 @@ 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::DynStrTab || S == InX::RelaPlt || S == InX::RelaDyn || +        S == InX::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; +      S->Assigned = false;      S->Live = false;      discard(S->DependentSections);    }  } -std::vector<InputSection *> LinkerScript::createInputSectionList( -    OutputSection &OutCmd, const DenseMap<SectionBase *, int> &Order) { +std::vector<InputSection *> +LinkerScript::createInputSectionList(OutputSection &OutCmd) {    std::vector<InputSection *> Ret;    for (BaseCommand *Base : OutCmd.SectionCommands) {      if (auto *Cmd = dyn_cast<InputSectionDescription>(Base)) { -      Cmd->Sections = computeInputSections(Cmd, Order); +      Cmd->Sections = computeInputSections(Cmd);        Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end());      }    } @@ -359,7 +467,6 @@ void LinkerScript::processSectionCommands() {    Ctx->OutSec = Aether;    size_t I = 0; -  DenseMap<SectionBase *, int> Order = buildSectionOrder();    // Add input sections to output sections.    for (BaseCommand *Base : SectionCommands) {      // Handle symbol assignments outside of any output section. @@ -369,12 +476,13 @@ void LinkerScript::processSectionCommands() {      }      if (auto *Sec = dyn_cast<OutputSection>(Base)) { -      std::vector<InputSection *> V = createInputSectionList(*Sec, Order); +      std::vector<InputSection *> V = createInputSectionList(*Sec);        // The output section name `/DISCARD/' is special.        // Any input section assigned to it is discarded.        if (Sec->Name == "/DISCARD/") {          discard(V); +        Sec->SectionCommands.clear();          continue;        } @@ -414,6 +522,8 @@ void LinkerScript::processSectionCommands() {        Sec->SectionIndex = I++;        if (Sec->Noload)          Sec->Type = SHT_NOBITS; +      if (Sec->NonAlloc) +        Sec->Flags &= ~(uint64_t)SHF_ALLOC;      }    }    Ctx = nullptr; @@ -484,7 +594,7 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,    // ignored. We should not have two output .text sections just because one was    // in a group and another was not for example.    // -  // It also seems that that wording was a late addition and didn't get the +  // It also seems that wording was a late addition and didn't get the    // necessary scrutiny.    //    // Merging sections with different flags is expected by some users. One @@ -529,11 +639,11 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,  void LinkerScript::addOrphanSections() {    unsigned End = SectionCommands.size();    StringMap<OutputSection *> Map; -    std::vector<OutputSection *> V; -  for (InputSectionBase *S : InputSections) { + +  auto Add = [&](InputSectionBase *S) {      if (!S->Live || S->Parent) -      continue; +      return;      StringRef Name = getOutputSectionName(S); @@ -545,12 +655,24 @@ void LinkerScript::addOrphanSections() {      if (OutputSection *Sec =              findByName(makeArrayRef(SectionCommands).slice(0, End), Name)) {        Sec->addSection(cast<InputSection>(S)); -      continue; +      return;      }      if (OutputSection *OS = addInputSec(Map, S, Name))        V.push_back(OS); -    assert(S->getOutputSection()->SectionIndex == INT_MAX); +    assert(S->getOutputSection()->SectionIndex == UINT32_MAX); +  }; + +  // For futher --emit-reloc handling code we need target output section +  // to be created before we create relocation output section, so we want +  // to create target sections first. We do not want priority handling +  // for synthetic sections because them are special. +  for (InputSectionBase *IS : InputSections) { +    if (auto *Sec = dyn_cast<InputSection>(IS)) +      if (InputSectionBase *Rel = Sec->getRelocatedSection()) +        if (auto *RelIS = dyn_cast_or_null<InputSectionBase>(Rel->Parent)) +          Add(RelIS); +    Add(IS);    }    // If no SECTIONS command was given, we should insert sections commands @@ -585,36 +707,15 @@ void LinkerScript::output(InputSection *S) {    // Update output section size after adding each section. This is so that    // SIZEOF works correctly in the case below:    // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } -  Ctx->OutSec->Size = Pos - Ctx->OutSec->Addr; - -  // If there is a memory region associated with this input section, then -  // place the section in that region and update the region index. -  if (Ctx->MemRegion) { -    uint64_t &CurOffset = Ctx->MemRegionOffset[Ctx->MemRegion]; -    CurOffset += Pos - Before; -    uint64_t CurSize = CurOffset - Ctx->MemRegion->Origin; -    if (CurSize > Ctx->MemRegion->Length) { -      uint64_t OverflowAmt = CurSize - Ctx->MemRegion->Length; -      error("section '" + Ctx->OutSec->Name + "' will not fit in region '" + -            Ctx->MemRegion->Name + "': overflowed by " + Twine(OverflowAmt) + -            " bytes"); -    } -  } +  expandOutputSection(Pos - Before);  }  void LinkerScript::switchTo(OutputSection *Sec) { -  if (Ctx->OutSec == Sec) -    return; -    Ctx->OutSec = Sec; -  Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment); -  // If neither AT nor AT> is specified for an allocatable section, the linker -  // 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 -  if (Ctx->LMAOffset) -    Ctx->OutSec->LMAOffset = Ctx->LMAOffset(); +  uint64_t Before = advance(0, 1); +  Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment); +  expandMemoryRegions(Ctx->OutSec->Addr - Before);  }  // This function searches for a memory region to place the given output @@ -624,9 +725,8 @@ MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) {    // If a memory region name was specified in the output section command,    // then try to find that region first.    if (!Sec->MemoryRegionName.empty()) { -    auto It = MemoryRegions.find(Sec->MemoryRegionName); -    if (It != MemoryRegions.end()) -      return It->second; +    if (MemoryRegion *M = MemoryRegions.lookup(Sec->MemoryRegionName)) +      return M;      error("memory region '" + Sec->MemoryRegionName + "' not declared");      return nullptr;    } @@ -659,24 +759,27 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {      setDot(Sec->AddrExpr, Sec->Location, false);    Ctx->MemRegion = Sec->MemRegion; +  Ctx->LMARegion = Sec->LMARegion;    if (Ctx->MemRegion) -    Dot = Ctx->MemRegionOffset[Ctx->MemRegion]; - -  if (Sec->LMAExpr) { -    uint64_t D = Dot; -    Ctx->LMAOffset = [=] { return Sec->LMAExpr().getValue() - D; }; -  } +    Dot = Ctx->MemRegion->CurPos;    switchTo(Sec); -  // We do not support custom layout for compressed debug sectons. -  // At this point we already know their size and have compressed content. -  if (Ctx->OutSec->Flags & SHF_COMPRESSED) -    return; +  if (Sec->LMAExpr) +    Ctx->LMAOffset = Sec->LMAExpr().getValue() - Dot; + +  if (MemoryRegion *MR = Sec->LMARegion) +    Ctx->LMAOffset = MR->CurPos - Dot; + +  // If neither AT nor AT> is specified for an allocatable section, the linker +  // 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 +  if (PhdrEntry *L = Ctx->OutSec->PtLoad) +    L->LMAOffset = Ctx->LMAOffset; -  // The Size previously denoted how many InputSections had been added to this -  // section, and was used for sorting SHF_LINK_ORDER sections. Reset it to -  // compute the actual size value. +  // We can call this method multiple times during the creation of +  // thunks and want to start over calculation each time.    Sec->Size = 0;    // We visited SectionsCommands from processSectionCommands to @@ -685,7 +788,9 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {    for (BaseCommand *Base : Sec->SectionCommands) {      // This handles the assignments to symbol or to the dot.      if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { +      Cmd->Addr = Dot;        assignSymbol(Cmd, true); +      Cmd->Size = Dot - Cmd->Addr;        continue;      } @@ -693,15 +798,7 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {      if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {        Cmd->Offset = Dot - Ctx->OutSec->Addr;        Dot += Cmd->Size; -      if (Ctx->MemRegion) -        Ctx->MemRegionOffset[Ctx->MemRegion] += Cmd->Size; -      Ctx->OutSec->Size = Dot - Ctx->OutSec->Addr; -      continue; -    } - -    // Handle ASSERT(). -    if (auto *Cmd = dyn_cast<AssertCommand>(Base)) { -      Cmd->Expression(); +      expandOutputSection(Cmd->Size);        continue;      } @@ -726,24 +823,28 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {    }  } -void LinkerScript::removeEmptyCommands() { -  // It is common practice to use very generic linker scripts. So for any -  // given run some of the output sections in the script will be empty. -  // We could create corresponding empty output sections, but that would -  // clutter the output. -  // We instead remove trivially empty sections. The bfd linker seems even -  // more aggressive at removing them. -  llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { -    if (auto *Sec = dyn_cast<OutputSection>(Base)) -      return !Sec->Live; +static bool isDiscardable(OutputSection &Sec) { +  // We do not remove empty sections that are explicitly +  // assigned to any segment. +  if (!Sec.Phdrs.empty())      return false; -  }); -} -static bool isAllSectionDescription(const OutputSection &Cmd) { -  for (BaseCommand *Base : Cmd.SectionCommands) +  // We do not want to remove sections that reference symbols in address and +  // other expressions. We add script symbols as undefined, and want to ensure +  // all of them are defined in the output, hence have to keep them. +  if (Sec.ExpressionsUseSymbols) +    return false; + +  for (BaseCommand *Base : Sec.SectionCommands) { +    if (auto Cmd = dyn_cast<SymbolAssignment>(Base)) +      // Don't create empty output sections just for unreferenced PROVIDE +      // symbols. +      if (Cmd->Name != "." && !Cmd->Sym) +        continue; +      if (!isa<InputSectionDescription>(*Base))        return false; +  }    return true;  } @@ -759,7 +860,7 @@ void LinkerScript::adjustSectionsBeforeSorting() {    // Given that we want to create the section, we have to worry what impact    // it will have on the link. For example, if we just create a section with    // 0 for flags, it would change which PT_LOADs are created. -  // We could remember that that particular section is dummy and ignore it in +  // We could remember that particular section is dummy and ignore it in    // other parts of the linker, but unfortunately there are quite a few places    // that would need to change:    //   * The program header creation. @@ -770,34 +871,54 @@ void LinkerScript::adjustSectionsBeforeSorting() {    // the previous sections. Only a few flags are needed to keep the impact low.    uint64_t Flags = SHF_ALLOC; -  for (BaseCommand *Cmd : SectionCommands) { +  for (BaseCommand *&Cmd : SectionCommands) {      auto *Sec = dyn_cast<OutputSection>(Cmd);      if (!Sec)        continue; -    if (Sec->Live) { -      Flags = Sec->Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR); -      continue; -    } - -    if (isAllSectionDescription(*Sec)) -      continue; -    Sec->Live = true; -    Sec->Flags = Flags; +    // Handle align (e.g. ".foo : ALIGN(16) { ... }"). +    if (Sec->AlignExpr) +      Sec->Alignment = +          std::max<uint32_t>(Sec->Alignment, Sec->AlignExpr().getValue()); + +    // A live output section means that some input section was added to it. It +    // might have been removed (if it was empty synthetic section), but we at +    // least know the flags. +    if (Sec->Live) +      Flags = Sec->Flags; + +    // We do not want to keep any special flags for output section +    // in case it is empty. +    bool IsEmpty = getInputSections(Sec).empty(); +    if (IsEmpty) +      Sec->Flags = Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR); + +    if (IsEmpty && isDiscardable(*Sec)) { +      Sec->Live = false; +      Cmd = nullptr; +    }    } + +  // It is common practice to use very generic linker scripts. So for any +  // given run some of the output sections in the script will be empty. +  // We could create corresponding empty output sections, but that would +  // clutter the output. +  // We instead remove trivially empty sections. The bfd linker seems even +  // more aggressive at removing them. +  llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { return !Base; });  }  void LinkerScript::adjustSectionsAfterSorting() {    // Try and find an appropriate memory region to assign offsets in.    for (BaseCommand *Base : SectionCommands) {      if (auto *Sec = dyn_cast<OutputSection>(Base)) { -      if (!Sec->Live) -        continue; +      if (!Sec->LMARegionName.empty()) { +        if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName)) +          Sec->LMARegion = M; +        else +          error("memory region '" + Sec->LMARegionName + "' not declared"); +      }        Sec->MemRegion = findMemoryRegion(Sec); -      // Handle align (e.g. ".foo : ALIGN(16) { ... }"). -      if (Sec->AlignExpr) -        Sec->Alignment = -            std::max<uint32_t>(Sec->Alignment, Sec->AlignExpr().getValue());      }    } @@ -808,9 +929,9 @@ void LinkerScript::adjustSectionsAfterSorting() {    // PHDRS { seg PT_LOAD; }    // SECTIONS { .aaa : { *(.aaa) } }    std::vector<StringRef> DefPhdrs; -  auto FirstPtLoad = -      std::find_if(PhdrsCommands.begin(), PhdrsCommands.end(), -                   [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; }); +  auto FirstPtLoad = llvm::find_if(PhdrsCommands, [](const PhdrsCommand &Cmd) { +    return Cmd.Type == PT_LOAD; +  });    if (FirstPtLoad != PhdrsCommands.end())      DefPhdrs.push_back(FirstPtLoad->Name); @@ -839,6 +960,15 @@ static OutputSection *findFirstSection(PhdrEntry *Load) {    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. +  if (!Script->HasSectionsCommand || AllocateHeaders) +    return 0; +  // Otherwise only allocate program headers if that would not add a page. +  return alignDown(Min, Config->MaxPageSize); +} +  // Try to find an address for the file and program headers output sections,  // which were unconditionally added to the first PT_LOAD segment earlier.  // @@ -862,17 +992,22 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {      return;    PhdrEntry *FirstPTLoad = *It; +  bool HasExplicitHeaders = +      llvm::any_of(PhdrsCommands, [](const PhdrsCommand &Cmd) { +        return Cmd.HasPhdrs || Cmd.HasFilehdr; +      });    uint64_t HeaderSize = getHeaderSize(); -  // When linker script with SECTIONS is being used, don't output headers -  // unless there's a space for them. -  uint64_t Base = HasSectionsCommand ? alignDown(Min, Config->MaxPageSize) : 0; -  if (HeaderSize <= Min - Base || Script->hasPhdrsCommands()) { +  if (HeaderSize <= Min - computeBase(Min, HasExplicitHeaders)) {      Min = alignDown(Min - HeaderSize, Config->MaxPageSize);      Out::ElfHeader->Addr = Min;      Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size;      return;    } +  // Error if we were explicitly asked to allocate headers. +  if (HasExplicitHeaders) +    error("could not allocate headers"); +    Out::ElfHeader->PtLoad = nullptr;    Out::ProgramHeaders->PtLoad = nullptr;    FirstPTLoad->FirstSec = findFirstSection(FirstPTLoad); @@ -883,8 +1018,8 @@ void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {  LinkerScript::AddressState::AddressState() {    for (auto &MRI : Script->MemoryRegions) { -    const MemoryRegion *MR = MRI.second; -    MemRegionOffset[MR] = MR->Origin; +    MemoryRegion *MR = MRI.second; +    MR->CurPos = MR->Origin;    }  } @@ -916,15 +1051,11 @@ void LinkerScript::assignAddresses() {    for (BaseCommand *Base : SectionCommands) {      if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { +      Cmd->Addr = Dot;        assignSymbol(Cmd, false); +      Cmd->Size = Dot - Cmd->Addr;        continue;      } - -    if (auto *Cmd = dyn_cast<AssertCommand>(Base)) { -      Cmd->Expression(); -      continue; -    } -      assignOffsets(cast<OutputSection>(Base));    }    Ctx = nullptr; @@ -988,9 +1119,9 @@ ExprValue LinkerScript::getSymbolValue(StringRef Name, const Twine &Loc) {    if (Symbol *Sym = Symtab->find(Name)) {      if (auto *DS = dyn_cast<Defined>(Sym))        return {DS->Section, false, DS->Value, Loc}; -    if (auto *SS = dyn_cast<SharedSymbol>(Sym)) -      if (!ErrorOnMissingSection || SS->CopyRelSec) -        return {SS->CopyRelSec, false, 0, Loc}; +    if (isa<SharedSymbol>(Sym)) +      if (!ErrorOnMissingSection) +        return {nullptr, false, 0, Loc};    }    error(Loc + ": symbol not found: " + Name); | 
