[lld] r278322 - [ELF] Symbol assignment within output section description

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 11 00:56:44 PDT 2016


Author: evgeny777
Date: Thu Aug 11 02:56:43 2016
New Revision: 278322

URL: http://llvm.org/viewvc/llvm-project?rev=278322&view=rev
Log:
[ELF] Symbol assignment within output section description

Added:
    lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=278322&r1=278321&r2=278322&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Thu Aug 11 02:56:43 2016
@@ -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::Ob
 
 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>

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=278322&r1=278321&r2=278322&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Thu Aug 11 02:56:43 2016
@@ -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) {}

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=278322&r1=278321&r2=278322&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Aug 11 02:56:43 2016
@@ -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> Pa
   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(con
   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>
+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>
-static void addSection(OutputSectionFactory<ELFT> &Factory,
-                       std::vector<OutputSectionBase<ELFT> *> &Out,
-                       InputSectionBase<ELFT> *C, StringRef Name) {
-  OutputSectionBase<ELFT> *Sec;
+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,40 +258,51 @@ 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.
   for (const std::unique_ptr<ObjectFile<ELFT>> &F :
        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<
   }
 }
 
+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<
         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<
       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(
   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,18 +807,12 @@ 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") {
-      Cmd = new AssertCommand(readAssert());
-    } else {
-      Cmd = readOutputSectionDescription(Tok);
+    BaseCommand *Cmd = readProvideOrAssignment(Tok);
+    if (!Cmd) {
+      if (Tok == "ASSERT")
+        Cmd = new AssertCommand(readAssert());
+      else
+        Cmd = readOutputSectionDescription(Tok);
     }
     Opt.Commands.emplace_back(Cmd);
   }
@@ -836,11 +949,14 @@ ScriptParser::readOutputSectionDescripti
       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::readProv
   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;

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=278322&r1=278321&r2=278322&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Aug 11 02:56:43 2016
@@ -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 *);
 

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=278322&r1=278321&r2=278322&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Aug 11 02:56:43 2016
@@ -1762,6 +1762,8 @@ OutputSectionFactory<ELFT>::create(Input
   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};

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=278322&r1=278321&r2=278322&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Thu Aug 11 02:56:43 2016
@@ -58,7 +58,7 @@ static typename ELFT::uint getSymVA(cons
       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;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=278322&r1=278321&r2=278322&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Aug 11 02:56:43 2016
@@ -238,6 +238,9 @@ template <class ELFT> void Writer<ELFT>:
     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>:
       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>:
   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>:
   // 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>);

Added: lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s?rev=278322&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s (added)
+++ lld/trunk/test/ELF/linkerscript/linkerscript-symbols-synthetic.s Thu Aug 11 02:56:43 2016
@@ -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




More information about the llvm-commits mailing list