forked from OSchip/llvm-project
				
			[ELF] Symbol assignment within output section description
llvm-svn: 278322
This commit is contained in:
		
							parent
							
								
									88f0c31f13
								
							
						
					
					
						commit
						ceabe80e97
					
				| 
						 | 
				
			
			@ -71,6 +71,7 @@ template <class ELFT>
 | 
			
		|||
typename ELFT::uint InputSectionBase<ELFT>::getOffset(uintX_t Offset) const {
 | 
			
		||||
  switch (SectionKind) {
 | 
			
		||||
  case Regular:
 | 
			
		||||
  case Layout:
 | 
			
		||||
    return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
 | 
			
		||||
  case EHFrame:
 | 
			
		||||
    // The file crtbeginT.o has relocations pointing to the start of an empty
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +130,7 @@ InputSection<ELFT>::InputSection(elf::ObjectFile<ELFT> *F,
 | 
			
		|||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
 | 
			
		||||
  return S->SectionKind == Base::Regular;
 | 
			
		||||
  return S->SectionKind == Base::Regular || S->SectionKind == Base::Layout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ protected:
 | 
			
		|||
  SmallVector<char, 0> Uncompressed;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions };
 | 
			
		||||
  enum Kind { Regular, EHFrame, Merge, MipsReginfo, MipsOptions, Layout };
 | 
			
		||||
  Kind SectionKind;
 | 
			
		||||
 | 
			
		||||
  InputSectionBase() : Repl(this) {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,36 @@ using namespace lld::elf;
 | 
			
		|||
 | 
			
		||||
ScriptConfiguration *elf::ScriptConfig;
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
static Symbol *addSymbolToSymtabAux(StringRef Name, uint8_t StOther) {
 | 
			
		||||
  return Symtab<ELFT>::X->addRegular(Name, STB_GLOBAL, StOther);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
static Symbol *addSymbolToSymtabAux(StringRef Name, typename ELFT::uint Value,
 | 
			
		||||
                                    OutputSectionBase<ELFT> *Section) {
 | 
			
		||||
  return Symtab<ELFT>::X->addSynthetic(Name, Section, Value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT, class... ArgsT>
 | 
			
		||||
static bool addSymbolToSymtab(SymbolAssignment &Cmd, ArgsT... Args) {
 | 
			
		||||
  if (Cmd.Name == ".")
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  // If a symbol was in PROVIDE(), define it only when it is an
 | 
			
		||||
  // undefined symbol.
 | 
			
		||||
  SymbolBody *B = Symtab<ELFT>::X->find(Cmd.Name);
 | 
			
		||||
  if (Cmd.Provide && !(B && B->isUndefined()))
 | 
			
		||||
    return false;
 | 
			
		||||
 | 
			
		||||
  Symbol *Sym =
 | 
			
		||||
      addSymbolToSymtabAux<ELFT>(Cmd.Name, std::forward<ArgsT>(Args)...);
 | 
			
		||||
 | 
			
		||||
  Sym->Visibility = Cmd.Hidden ? STV_HIDDEN : STV_DEFAULT;
 | 
			
		||||
  Cmd.Sym = Sym->body();
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SymbolAssignment::classof(const BaseCommand *C) {
 | 
			
		||||
  return C->Kind == AssignmentKind;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -78,21 +108,6 @@ static bool match(ArrayRef<StringRef> Patterns, StringRef S) {
 | 
			
		|||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a vector of (<output section name>, <input section description>).
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
std::vector<std::pair<StringRef, const InputSectionDescription *>>
 | 
			
		||||
LinkerScript<ELFT>::getSectionMap() {
 | 
			
		||||
  std::vector<std::pair<StringRef, const InputSectionDescription *>> Ret;
 | 
			
		||||
 | 
			
		||||
  for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands)
 | 
			
		||||
    if (auto *Cmd1 = dyn_cast<OutputSectionCommand>(Base1.get()))
 | 
			
		||||
      for (const std::unique_ptr<BaseCommand> &Base2 : Cmd1->Commands)
 | 
			
		||||
        if (auto *Cmd2 = dyn_cast<InputSectionDescription>(Base2.get()))
 | 
			
		||||
          Ret.emplace_back(Cmd1->Name, Cmd2);
 | 
			
		||||
 | 
			
		||||
  return Ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool fileMatches(const InputSectionDescription *Desc,
 | 
			
		||||
                        StringRef Filename) {
 | 
			
		||||
  if (!globMatch(Desc->FilePattern, Filename))
 | 
			
		||||
| 
						 | 
				
			
			@ -121,18 +136,101 @@ LinkerScript<ELFT>::getInputSections(const InputSectionDescription *I) {
 | 
			
		|||
  return Ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add input section to output section. If there is no output section yet,
 | 
			
		||||
// then create it and add to output section list.
 | 
			
		||||
namespace {
 | 
			
		||||
template <class ELFT> class LayoutInputSection : public InputSection<ELFT> {
 | 
			
		||||
public:
 | 
			
		||||
  LayoutInputSection(SymbolAssignment *Cmd);
 | 
			
		||||
  static bool classof(const InputSectionBase<ELFT> *S);
 | 
			
		||||
  SymbolAssignment *Cmd;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  typename ELFT::Shdr Hdr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Helper class, which builds output section list, also
 | 
			
		||||
// creating symbol sections, when needed
 | 
			
		||||
template <class ELFT> class OutputSectionBuilder {
 | 
			
		||||
public:
 | 
			
		||||
  OutputSectionBuilder(OutputSectionFactory<ELFT> &F,
 | 
			
		||||
                       std::vector<OutputSectionBase<ELFT> *> *Out)
 | 
			
		||||
      : Factory(F), OutputSections(Out) {}
 | 
			
		||||
 | 
			
		||||
  void addSection(StringRef OutputName, InputSectionBase<ELFT> *I);
 | 
			
		||||
  void addSymbol(SymbolAssignment *Cmd) {
 | 
			
		||||
    PendingSymbols.emplace_back(new LayoutInputSection<ELFT>(Cmd));
 | 
			
		||||
  }
 | 
			
		||||
  void flushSymbols();
 | 
			
		||||
  void flushSection();
 | 
			
		||||
  void finalize();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  OutputSectionFactory<ELFT> &Factory;
 | 
			
		||||
  std::vector<OutputSectionBase<ELFT> *> *OutputSections;
 | 
			
		||||
  OutputSectionBase<ELFT> *Current = nullptr;
 | 
			
		||||
  std::vector<std::unique_ptr<LayoutInputSection<ELFT>>> PendingSymbols;
 | 
			
		||||
  static std::vector<std::unique_ptr<LayoutInputSection<ELFT>>> OwningSections;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
static void addSection(OutputSectionFactory<ELFT> &Factory,
 | 
			
		||||
                       std::vector<OutputSectionBase<ELFT> *> &Out,
 | 
			
		||||
                       InputSectionBase<ELFT> *C, StringRef Name) {
 | 
			
		||||
  OutputSectionBase<ELFT> *Sec;
 | 
			
		||||
std::vector<std::unique_ptr<LayoutInputSection<ELFT>>>
 | 
			
		||||
    OutputSectionBuilder<ELFT>::OwningSections;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T> static T *zero(T *Val) {
 | 
			
		||||
  memset(Val, 0, sizeof(*Val));
 | 
			
		||||
  return Val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
LayoutInputSection<ELFT>::LayoutInputSection(SymbolAssignment *Cmd)
 | 
			
		||||
    : InputSection<ELFT>(nullptr, zero(&Hdr)), Cmd(Cmd) {
 | 
			
		||||
  this->Live = true;
 | 
			
		||||
  this->SectionKind = InputSectionBase<ELFT>::Layout;
 | 
			
		||||
  Hdr.sh_type = SHT_NOBITS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
bool LayoutInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
 | 
			
		||||
  return S->SectionKind == InputSectionBase<ELFT>::Layout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
void OutputSectionBuilder<ELFT>::addSection(StringRef OutputName,
 | 
			
		||||
                                            InputSectionBase<ELFT> *C) {
 | 
			
		||||
  bool IsNew;
 | 
			
		||||
  std::tie(Sec, IsNew) = Factory.create(C, Name);
 | 
			
		||||
  std::tie(Current, IsNew) = Factory.create(C, OutputName);
 | 
			
		||||
  if (IsNew)
 | 
			
		||||
    Out.push_back(Sec);
 | 
			
		||||
  Sec->addSection(C);
 | 
			
		||||
    OutputSections->push_back(Current);
 | 
			
		||||
  flushSymbols();
 | 
			
		||||
  Current->addSection(C);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> void OutputSectionBuilder<ELFT>::flushSymbols() {
 | 
			
		||||
  for (std::unique_ptr<LayoutInputSection<ELFT>> &I : PendingSymbols)
 | 
			
		||||
    if (I->Cmd->Name == "." || addSymbolToSymtab<ELFT>(*I->Cmd, 0, Current)) {
 | 
			
		||||
      // Only regular output sections are supported.
 | 
			
		||||
      if (dyn_cast_or_null<OutputSection<ELFT>>(Current)) {
 | 
			
		||||
        Current->addSection(I.get());
 | 
			
		||||
        OwningSections.push_back(std::move(I));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  PendingSymbols.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> void OutputSectionBuilder<ELFT>::flushSection() {
 | 
			
		||||
  flushSymbols();
 | 
			
		||||
  Current = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> void OutputSectionBuilder<ELFT>::finalize() {
 | 
			
		||||
  // Assign offsets to all sections which don't contain symbols
 | 
			
		||||
  for (OutputSectionBase<ELFT> *S : *OutputSections)
 | 
			
		||||
    if (llvm::find_if(OwningSections,
 | 
			
		||||
                      [&](std::unique_ptr<LayoutInputSection<ELFT>> &L) {
 | 
			
		||||
                        return L->OutSec == S;
 | 
			
		||||
                      }) == OwningSections.end())
 | 
			
		||||
      S->assignOffsets();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
| 
						 | 
				
			
			@ -160,28 +258,38 @@ getComparator(SortKind K) {
 | 
			
		|||
template <class ELFT>
 | 
			
		||||
void LinkerScript<ELFT>::createSections(
 | 
			
		||||
    OutputSectionFactory<ELFT> &Factory) {
 | 
			
		||||
  for (auto &P : getSectionMap()) {
 | 
			
		||||
    StringRef OutputName = P.first;
 | 
			
		||||
    const InputSectionDescription *Cmd = P.second;
 | 
			
		||||
    std::vector<InputSectionBase<ELFT> *> Sections = getInputSections(Cmd);
 | 
			
		||||
  OutputSectionBuilder<ELFT> Builder(Factory, OutputSections);
 | 
			
		||||
 | 
			
		||||
  auto Add = [&](StringRef OutputName, const InputSectionDescription *Cmd) {
 | 
			
		||||
    std::vector<InputSectionBase<ELFT> *> Sections = getInputSections(Cmd);
 | 
			
		||||
    if (OutputName == "/DISCARD/") {
 | 
			
		||||
      for (InputSectionBase<ELFT> *S : Sections) {
 | 
			
		||||
        S->Live = false;
 | 
			
		||||
        reportDiscarded(S);
 | 
			
		||||
      }
 | 
			
		||||
      continue;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Cmd->SortInner)
 | 
			
		||||
      std::stable_sort(Sections.begin(), Sections.end(),
 | 
			
		||||
                       getComparator<ELFT>(Cmd->SortInner));
 | 
			
		||||
    if (Cmd->SortOuter)
 | 
			
		||||
      std::stable_sort(Sections.begin(), Sections.end(),
 | 
			
		||||
                       getComparator<ELFT>(Cmd->SortOuter));
 | 
			
		||||
 | 
			
		||||
    for (InputSectionBase<ELFT> *S : Sections)
 | 
			
		||||
      addSection(Factory, *OutputSections, S, OutputName);
 | 
			
		||||
      Builder.addSection(OutputName, S);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands)
 | 
			
		||||
    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base1.get())) {
 | 
			
		||||
      for (const std::unique_ptr<BaseCommand> &Base2 : Cmd->Commands)
 | 
			
		||||
        if (auto *Assignment = dyn_cast<SymbolAssignment>(Base2.get()))
 | 
			
		||||
          Builder.addSymbol(Assignment);
 | 
			
		||||
        else
 | 
			
		||||
          Add(Cmd->Name, cast<InputSectionDescription>(Base2.get()));
 | 
			
		||||
 | 
			
		||||
      Builder.flushSection();
 | 
			
		||||
    } else if (auto *Cmd2 = dyn_cast<SymbolAssignment>(Base1.get())) {
 | 
			
		||||
      addSymbolToSymtab<ELFT>(*Cmd2, STV_DEFAULT);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  // Add all other input sections, which are not listed in script.
 | 
			
		||||
| 
						 | 
				
			
			@ -189,11 +297,12 @@ void LinkerScript<ELFT>::createSections(
 | 
			
		|||
       Symtab<ELFT>::X->getObjectFiles())
 | 
			
		||||
    for (InputSectionBase<ELFT> *S : F->getSections())
 | 
			
		||||
      if (!isDiscarded(S) && !S->OutSec)
 | 
			
		||||
        addSection(Factory, *OutputSections, S, getOutputSectionName(S));
 | 
			
		||||
        Builder.addSection(getOutputSectionName(S), S);
 | 
			
		||||
 | 
			
		||||
  // Remove from the output all the sections which did not meet
 | 
			
		||||
  // the optional constraints.
 | 
			
		||||
  filter();
 | 
			
		||||
  Builder.finalize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class R, class T>
 | 
			
		||||
| 
						 | 
				
			
			@ -224,6 +333,35 @@ template <class ELFT> void LinkerScript<ELFT>::filter() {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> void assignOffsets(OutputSectionBase<ELFT> *Sec) {
 | 
			
		||||
  // Non-zero size means we have assigned offsets earlier in
 | 
			
		||||
  // OutputSectionBuilder<ELFT>::finalize
 | 
			
		||||
  auto *OutSec = dyn_cast<OutputSection<ELFT>>(Sec);
 | 
			
		||||
  if (Sec->getSize() || !OutSec)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  typedef typename ELFT::uint uintX_t;
 | 
			
		||||
  uintX_t Off = 0;
 | 
			
		||||
 | 
			
		||||
  for (InputSection<ELFT> *I : OutSec->Sections) {
 | 
			
		||||
    if (auto *L = dyn_cast<LayoutInputSection<ELFT>>(I)) {
 | 
			
		||||
      uintX_t Value = L->Cmd->Expression(Sec->getVA() + Off) - Sec->getVA();
 | 
			
		||||
      if (L->Cmd->Name == ".")
 | 
			
		||||
        Off = Value;
 | 
			
		||||
      else
 | 
			
		||||
        cast<DefinedSynthetic<ELFT>>(L->Cmd->Sym)->Value = Value;
 | 
			
		||||
    } else {
 | 
			
		||||
      Off = alignTo(Off, I->Alignment);
 | 
			
		||||
      I->OutSecOff = Off;
 | 
			
		||||
      Off += I->getSize();
 | 
			
		||||
    }
 | 
			
		||||
    // Update section size inside for-loop, so that SIZEOF 
 | 
			
		||||
    // works correctly in the case below:
 | 
			
		||||
    // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
 | 
			
		||||
    Sec->setSize(Off);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
 | 
			
		||||
  ArrayRef<OutputSectionBase<ELFT> *> Sections = *OutputSections;
 | 
			
		||||
  // Orphan sections are sections present in the input files which
 | 
			
		||||
| 
						 | 
				
			
			@ -275,6 +413,7 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
 | 
			
		|||
        uintX_t TVA = Dot + ThreadBssOffset;
 | 
			
		||||
        TVA = alignTo(TVA, Sec->getAlignment());
 | 
			
		||||
        Sec->setVA(TVA);
 | 
			
		||||
        assignOffsets(Sec);
 | 
			
		||||
        ThreadBssOffset = TVA - Dot + Sec->getSize();
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -282,6 +421,7 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
 | 
			
		|||
      if (Sec->getFlags() & SHF_ALLOC) {
 | 
			
		||||
        Dot = alignTo(Dot, Sec->getAlignment());
 | 
			
		||||
        Sec->setVA(Dot);
 | 
			
		||||
        assignOffsets(Sec);
 | 
			
		||||
        MinVA = std::min(MinVA, Dot);
 | 
			
		||||
        Dot += Sec->getSize();
 | 
			
		||||
        continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -395,28 +535,6 @@ int LinkerScript<ELFT>::compareSections(StringRef A, StringRef B) {
 | 
			
		|||
  return I < J ? -1 : 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add symbols defined by linker scripts.
 | 
			
		||||
template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() {
 | 
			
		||||
  for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
 | 
			
		||||
    auto *Cmd = dyn_cast<SymbolAssignment>(Base.get());
 | 
			
		||||
    if (!Cmd || Cmd->Name == ".")
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    // If a symbol was in PROVIDE(), define it only when it is an
 | 
			
		||||
    // undefined symbol.
 | 
			
		||||
    SymbolBody *B = Symtab<ELFT>::X->find(Cmd->Name);
 | 
			
		||||
    if (Cmd->Provide && !(B && B->isUndefined()))
 | 
			
		||||
      continue;
 | 
			
		||||
 | 
			
		||||
    // Define an absolute symbol. The symbol value will be assigned later.
 | 
			
		||||
    // (At this point, we don't know the final address yet.)
 | 
			
		||||
    Symbol *Sym = Symtab<ELFT>::X->addUndefined(Cmd->Name);
 | 
			
		||||
    replaceBody<DefinedRegular<ELFT>>(Sym, Cmd->Name, STV_DEFAULT);
 | 
			
		||||
    Sym->Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;
 | 
			
		||||
    Cmd->Sym = Sym->body();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() {
 | 
			
		||||
  return !Opt.PhdrsCommands.empty();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -499,6 +617,7 @@ private:
 | 
			
		|||
  unsigned readPhdrType();
 | 
			
		||||
  SortKind readSortKind();
 | 
			
		||||
  SymbolAssignment *readProvide(bool Hidden);
 | 
			
		||||
  SymbolAssignment *readProvideOrAssignment(StringRef Tok);
 | 
			
		||||
  Expr readAlign();
 | 
			
		||||
  void readSort();
 | 
			
		||||
  Expr readAssert();
 | 
			
		||||
| 
						 | 
				
			
			@ -688,17 +807,11 @@ void ScriptParser::readSections() {
 | 
			
		|||
  expect("{");
 | 
			
		||||
  while (!Error && !skip("}")) {
 | 
			
		||||
    StringRef Tok = next();
 | 
			
		||||
    BaseCommand *Cmd;
 | 
			
		||||
    if (peek() == "=" || peek() == "+=") {
 | 
			
		||||
      Cmd = readAssignment(Tok);
 | 
			
		||||
      expect(";");
 | 
			
		||||
    } else if (Tok == "PROVIDE") {
 | 
			
		||||
      Cmd = readProvide(false);
 | 
			
		||||
    } else if (Tok == "PROVIDE_HIDDEN") {
 | 
			
		||||
      Cmd = readProvide(true);
 | 
			
		||||
    } else if (Tok == "ASSERT") {
 | 
			
		||||
    BaseCommand *Cmd = readProvideOrAssignment(Tok);
 | 
			
		||||
    if (!Cmd) {
 | 
			
		||||
      if (Tok == "ASSERT")
 | 
			
		||||
        Cmd = new AssertCommand(readAssert());
 | 
			
		||||
    } else {
 | 
			
		||||
      else
 | 
			
		||||
        Cmd = readOutputSectionDescription(Tok);
 | 
			
		||||
    }
 | 
			
		||||
    Opt.Commands.emplace_back(Cmd);
 | 
			
		||||
| 
						 | 
				
			
			@ -836,11 +949,14 @@ ScriptParser::readOutputSectionDescription(StringRef OutSec) {
 | 
			
		|||
      Cmd->Commands.emplace_back(readInputSectionDescription());
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    if (skip("SORT")) {
 | 
			
		||||
 | 
			
		||||
    StringRef Tok = next();
 | 
			
		||||
    if (SymbolAssignment *Assignment = readProvideOrAssignment(Tok))
 | 
			
		||||
      Cmd->Commands.emplace_back(Assignment);
 | 
			
		||||
    else if (Tok == "SORT")
 | 
			
		||||
      readSort();
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    setError("unknown command " + peek());
 | 
			
		||||
    else
 | 
			
		||||
      setError("unknown command " + Tok);
 | 
			
		||||
  }
 | 
			
		||||
  Cmd->Phdrs = readOutputSectionPhdrs();
 | 
			
		||||
  Cmd->Filler = readOutputSectionFiller();
 | 
			
		||||
| 
						 | 
				
			
			@ -877,6 +993,19 @@ SymbolAssignment *ScriptParser::readProvide(bool Hidden) {
 | 
			
		|||
  return Cmd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
 | 
			
		||||
  SymbolAssignment *Cmd = nullptr;
 | 
			
		||||
  if (peek() == "=" || peek() == "+=") {
 | 
			
		||||
    Cmd = readAssignment(Tok);
 | 
			
		||||
    expect(";");
 | 
			
		||||
  } else if (Tok == "PROVIDE") {
 | 
			
		||||
    Cmd = readProvide(false);
 | 
			
		||||
  } else if (Tok == "PROVIDE_HIDDEN") {
 | 
			
		||||
    Cmd = readProvide(true);
 | 
			
		||||
  }
 | 
			
		||||
  return Cmd;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint64_t getSymbolValue(StringRef S, uint64_t Dot) {
 | 
			
		||||
  if (S == ".")
 | 
			
		||||
    return Dot;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -146,7 +146,6 @@ public:
 | 
			
		|||
  bool shouldKeep(InputSectionBase<ELFT> *S);
 | 
			
		||||
  void assignAddresses();
 | 
			
		||||
  int compareSections(StringRef A, StringRef B);
 | 
			
		||||
  void addScriptedSymbols();
 | 
			
		||||
  bool hasPhdrsCommands();
 | 
			
		||||
  uintX_t getOutputSectionSize(StringRef Name);
 | 
			
		||||
  uintX_t getSizeOfHeaders();
 | 
			
		||||
| 
						 | 
				
			
			@ -154,9 +153,6 @@ public:
 | 
			
		|||
  std::vector<OutputSectionBase<ELFT> *> *OutputSections;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::vector<std::pair<StringRef, const InputSectionDescription *>>
 | 
			
		||||
  getSectionMap();
 | 
			
		||||
 | 
			
		||||
  std::vector<InputSectionBase<ELFT> *>
 | 
			
		||||
  getInputSections(const InputSectionDescription *);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1762,6 +1762,8 @@ OutputSectionFactory<ELFT>::create(InputSectionBase<ELFT> *C,
 | 
			
		|||
  case InputSectionBase<ELFT>::MipsOptions:
 | 
			
		||||
    Sec = new MipsOptionsOutputSection<ELFT>();
 | 
			
		||||
    break;
 | 
			
		||||
  case InputSectionBase<ELFT>::Layout:
 | 
			
		||||
    llvm_unreachable("Invalid section type");
 | 
			
		||||
  }
 | 
			
		||||
  OwningSections.emplace_back(Sec);
 | 
			
		||||
  return {Sec, true};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body,
 | 
			
		|||
      Offset += Addend;
 | 
			
		||||
      Addend = 0;
 | 
			
		||||
    }
 | 
			
		||||
    uintX_t VA = SC->OutSec->getVA() + SC->getOffset(Offset);
 | 
			
		||||
    uintX_t VA = (SC->OutSec ? SC->OutSec->getVA() : 0) + SC->getOffset(Offset);
 | 
			
		||||
    if (D.isTls())
 | 
			
		||||
      return VA - Out<ELFT>::TlsPhdr->p_vaddr;
 | 
			
		||||
    return VA;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -238,6 +238,9 @@ template <class ELFT> void Writer<ELFT>::run() {
 | 
			
		|||
    copyLocalSymbols();
 | 
			
		||||
  addReservedSymbols();
 | 
			
		||||
 | 
			
		||||
  if (Target->NeedsThunks)
 | 
			
		||||
    forEachRelSec(createThunks<ELFT>);
 | 
			
		||||
 | 
			
		||||
  CommonInputSection<ELFT> Common(getCommonSymbols<ELFT>());
 | 
			
		||||
  CommonInputSection<ELFT>::X = &Common;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -659,6 +662,14 @@ template <class ELFT> void Writer<ELFT>::createSections() {
 | 
			
		|||
      Sec->addSection(C);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  sortInitFini(findSection(".init_array"));
 | 
			
		||||
  sortInitFini(findSection(".fini_array"));
 | 
			
		||||
  sortCtorsDtors(findSection(".ctors"));
 | 
			
		||||
  sortCtorsDtors(findSection(".dtors"));
 | 
			
		||||
 | 
			
		||||
  for (OutputSectionBase<ELFT> *Sec : OutputSections)
 | 
			
		||||
    Sec->assignOffsets();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create output section objects and add them to OutputSections.
 | 
			
		||||
| 
						 | 
				
			
			@ -667,12 +678,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
 | 
			
		|||
  Out<ELFT>::InitArray = findSection(".init_array");
 | 
			
		||||
  Out<ELFT>::FiniArray = findSection(".fini_array");
 | 
			
		||||
 | 
			
		||||
  // Sort section contents for __attribute__((init_priority(N)).
 | 
			
		||||
  sortInitFini(Out<ELFT>::InitArray);
 | 
			
		||||
  sortInitFini(Out<ELFT>::FiniArray);
 | 
			
		||||
  sortCtorsDtors(findSection(".ctors"));
 | 
			
		||||
  sortCtorsDtors(findSection(".dtors"));
 | 
			
		||||
 | 
			
		||||
  // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
 | 
			
		||||
  // symbols for sections, so that the runtime can get the start and end
 | 
			
		||||
  // addresses of each section by section name. Add such symbols.
 | 
			
		||||
| 
						 | 
				
			
			@ -692,21 +697,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
 | 
			
		|||
  // Define __rel[a]_iplt_{start,end} symbols if needed.
 | 
			
		||||
  addRelIpltSymbols();
 | 
			
		||||
 | 
			
		||||
  // Add scripted symbols with zero values now.
 | 
			
		||||
  // Real values will be assigned later
 | 
			
		||||
  Script<ELFT>::X->addScriptedSymbols();
 | 
			
		||||
 | 
			
		||||
  if (!Out<ELFT>::EhFrame->empty()) {
 | 
			
		||||
    OutputSections.push_back(Out<ELFT>::EhFrame);
 | 
			
		||||
    Out<ELFT>::EhFrame->finalize();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (Target->NeedsThunks)
 | 
			
		||||
    forEachRelSec(createThunks<ELFT>);
 | 
			
		||||
 | 
			
		||||
  for (OutputSectionBase<ELFT> *Sec : OutputSections)
 | 
			
		||||
    Sec->assignOffsets();
 | 
			
		||||
 | 
			
		||||
  // Scan relocations. This must be done after every symbol is declared so that
 | 
			
		||||
  // we can correctly decide if a dynamic relocation is needed.
 | 
			
		||||
  forEachRelSec(scanRelocations<ELFT>);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
# REQUIRES: x86
 | 
			
		||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
 | 
			
		||||
 | 
			
		||||
# Simple symbol assignment within input section list. The '.' symbol
 | 
			
		||||
# is not location counter but offset from the beginning of output
 | 
			
		||||
# section .foo
 | 
			
		||||
# RUN: echo "SECTIONS { \
 | 
			
		||||
# RUN:          .foo : { \
 | 
			
		||||
# RUN:              begin_foo = .; \
 | 
			
		||||
# RUN:              *(.foo) \
 | 
			
		||||
# RUN:              end_foo = .; \
 | 
			
		||||
# RUN:              size_foo_1 = SIZEOF(.foo); \
 | 
			
		||||
# RUN:              . = ALIGN(0x1000); \
 | 
			
		||||
# RUN:              begin_bar = .; \
 | 
			
		||||
# RUN:              *(.bar) \
 | 
			
		||||
# RUN:              end_bar = .; \
 | 
			
		||||
# RUN:              size_foo_2 = SIZEOF(.foo); \ 
 | 
			
		||||
# RUN:            } \
 | 
			
		||||
# RUN:            size_foo_3 = SIZEOF(.foo); }" > %t.script
 | 
			
		||||
# RUN: ld.lld -o %t1 --script %t.script %t
 | 
			
		||||
# RUN: llvm-objdump -t %t1 | FileCheck --check-prefix=SIMPLE %s
 | 
			
		||||
# SIMPLE:      0000000000000120         .foo    00000000 begin_foo
 | 
			
		||||
# SIMPLE-NEXT: 0000000000000128         .foo    00000000 end_foo
 | 
			
		||||
# SIMPLE-NEXT: 0000000000000008         .foo    00000000 size_foo_1
 | 
			
		||||
# SIMPLE-NEXT: 0000000000001000         .foo    00000000 begin_bar
 | 
			
		||||
# SIMPLE-NEXT: 0000000000001004         .foo    00000000 end_bar
 | 
			
		||||
# SIMPLE-NEXT: 0000000000000ee4         .foo    00000000 size_foo_2
 | 
			
		||||
# SIMPLE-NEXT: 0000000000000ee4         *ABS*   00000000 size_foo_3
 | 
			
		||||
 | 
			
		||||
.global _start
 | 
			
		||||
_start:
 | 
			
		||||
 nop
 | 
			
		||||
 | 
			
		||||
.section .foo,"a"
 | 
			
		||||
 .quad 0
 | 
			
		||||
 | 
			
		||||
.section .bar,"a"
 | 
			
		||||
 .long 0
 | 
			
		||||
		Loading…
	
		Reference in New Issue