<div dir="ltr">This is really nontrivial pieces of code. You may want to do pre-submit review next time.<div class="gmail_extra"><br><div class="gmail_quote">On Sun, Feb 22, 2015 at 4:04 PM, Shankar Easwaran <span dir="ltr"><<a href="mailto:shankare@codeaurora.org" target="_blank">shankare@codeaurora.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: shankare<br>
Date: Sun Feb 22 18:04:49 2015<br>
New Revision: 230194<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=230194&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=230194&view=rev</a><br>
Log:<br>
[ELF] Add .gnu.linkonce support.<br>
<br>
When the GNU linker sees two input sections with the same name, and the name<br>
starts with ".gnu.linkonce.", the linker will only keep one copy and discard the<br>
other. Any section whose name starts with “.gnu.linkonce.” is a COMDAT section.<br>
<br>
Some architectures like Hexagon use this section to store floating point constants,<br>
that need be deduped.<br>
<br>
This patch adds gnu.linkonce functionality to the ELFReader.<br>
<br>
Added:<br>
    lld/trunk/test/elf/gnulinkonce/<br>
    lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test<br>
    lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test<br>
    lld/trunk/test/elf/gnulinkonce/gnulinkonce.test<br>
Modified:<br>
    lld/trunk/lib/ReaderWriter/ELF/Atoms.h<br>
    lld/trunk/lib/ReaderWriter/ELF/ELFFile.h<br>
    lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h<br>
    lld/trunk/lib/ReaderWriter/ELF/TODO.txt<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=230194&r1=230193&r2=230194&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=230194&r1=230193&r2=230194&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)<br>
+++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Sun Feb 22 18:04:49 2015<br>
@@ -179,14 +179,16 @@ public:<br>
   uint64_t size() const override {<br>
     // Common symbols are not allocated in object files,<br>
     // so use st_size to tell how many bytes are required.<br>
-    if ((_symbol->getType() == llvm::ELF::STT_COMMON) ||<br>
-        _symbol->st_shndx == llvm::ELF::SHN_COMMON)<br>
+    if (_symbol && (_symbol->getType() == llvm::ELF::STT_COMMON ||<br>
+                    _symbol->st_shndx == llvm::ELF::SHN_COMMON))<br>
       return (uint64_t) _symbol->st_size;<br>
<br>
     return _contentData.size();<br>
   }<br>
<br>
   Scope scope() const override {<br>
+    if (!_symbol)<br>
+      return scopeGlobal;<br></blockquote><div><br></div><div>How can this condition happen? Looks like previously _symbol was guaranteed to be non-null. Now, it looks like a null pointer can be assigned to _symbol so you need null check everywhere.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
     if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)<br>
       return scopeLinkageUnit;<br>
     else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)<br>
@@ -199,6 +201,9 @@ public:<br>
   Interposable interposable() const override { return interposeNo; }<br>
<br>
   Merge merge() const override {<br>
+    if (!_symbol)<br>
+      return mergeNo;<br>
+<br>
     if (_symbol->getBinding() == llvm::ELF::STB_WEAK)<br>
       return mergeAsWeak;<br>
<br>
@@ -216,6 +221,9 @@ public:<br>
     ContentType ret = typeUnknown;<br>
     uint64_t flags = _section->sh_flags;<br>
<br>
+    if (!_symbol && _sectionName.startswith(".gnu.linkonce"))<br></blockquote><div><br></div><div>In the commit message you wrote that sections starts with "gnu.linkonce." is GNU linkonce sections. You dropped the last "." (dot) here.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      return typeGnuLinkOnce;<br>
+<br>
     if (!(flags & llvm::ELF::SHF_ALLOC))<br>
       return _contentType = typeNoAlloc;<br>
<br>
@@ -286,6 +294,9 @@ public:<br>
   }<br>
<br>
   Alignment alignment() const override {<br>
+    if (!_symbol)<br>
+      return Alignment(0);<br>
+<br>
     // Obtain proper value of st_value field.<br>
     const auto symValue = getSymbolValue(_symbol);<br>
<br>
@@ -323,7 +334,7 @@ public:<br>
<br>
   StringRef customSectionName() const override {<br>
     if ((contentType() == typeZeroFill) ||<br>
-        (_symbol->st_shndx == llvm::ELF::SHN_COMMON))<br>
+        (_symbol && _symbol->st_shndx == llvm::ELF::SHN_COMMON))<br>
       return ".bss";<br>
     return _sectionName;<br>
   }<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/ELF/ELFFile.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFFile.h?rev=230194&r1=230193&r2=230194&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFFile.h?rev=230194&r1=230193&r2=230194&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/ELF/ELFFile.h (original)<br>
+++ lld/trunk/lib/ReaderWriter/ELF/ELFFile.h Sun Feb 22 18:04:49 2015<br>
@@ -168,8 +168,23 @@ public:<br>
     return _absoluteAtoms;<br>
   }<br>
<br>
-  Atom *findAtom(const Elf_Sym *symbol) {<br>
-    return _symbolToAtomMapping.lookup(symbol);<br>
+  Atom *findAtom(const Elf_Sym *sourceSymbol, const Elf_Sym *targetSymbol) {<br>
+    // All references to atoms inside a group are through undefined atoms.<br>
+    Atom *targetAtom = _symbolToAtomMapping.lookup(targetSymbol);<br>
+    if (targetAtom->definition() != Atom::definitionRegular)<br>
+      return targetAtom;<br>
+    if ((llvm::dyn_cast<DefinedAtom>(targetAtom))->scope() ==<br>
+        DefinedAtom::scopeTranslationUnit)<br>
+      return targetAtom;<br>
+    if (!redirectReferenceUsingUndefAtom(sourceSymbol, targetSymbol))<br>
+      return targetAtom;<br>
+    auto undefForGroupchild = _undefAtomsForgroupChild.find(targetAtom->name());<br>
+    if (undefForGroupchild != _undefAtomsForgroupChild.end())<br>
+      return undefForGroupchild->getValue();<br>
+    auto undefGroupChildAtom =<br>
+        new (_readerStorage) SimpleUndefinedAtom(*this, targetAtom->name());<br>
+    _undefinedAtoms._atoms.push_back(undefGroupChildAtom);<br>
+    return (_undefAtomsForgroupChild[targetAtom->name()] = undefGroupChildAtom);<br>
   }<br></blockquote><div><br></div><div>This really needs a comment to describe what the intention of the conditions is.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
 protected:<br>
@@ -258,6 +273,12 @@ protected:<br>
     return shdr && (shdr->sh_type == llvm::ELF::SHT_PROGBITS) && syms.empty();<br>
   }<br>
<br>
+  /// Handle creation of atoms for .gnu.linkonce sections.<br>
+  std::error_code handleGnuLinkOnceSection(<br>
+      StringRef sectionName,<br>
+      llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,<br>
+      const Elf_Shdr *shdr);<br>
+<br>
   /// Process the Undefined symbol and create an atom for it.<br>
   ErrorOr<ELFUndefinedAtom<ELFT> *><br>
   handleUndefinedSymbol(StringRef symName, const Elf_Sym *sym) {<br>
@@ -286,6 +307,11 @@ protected:<br>
            symbol->st_shndx == llvm::ELF::SHN_COMMON;<br>
   }<br>
<br>
+  /// Returns true if the section is a gnulinkonce section.<br>
+  bool isGnuLinkOnceSection(StringRef sectionName) const {<br>
+    return sectionName.startswith(".gnu.linkonce");<br>
+  }<br>
+<br>
   /// Returns correct st_value for the symbol depending on the architecture.<br>
   /// For most architectures it's just a regular st_value with no changes.<br>
   virtual uint64_t getSymbolValue(const Elf_Sym *symbol) const {<br>
@@ -333,6 +359,10 @@ protected:<br>
     return mergeAtom;<br>
   }<br>
<br>
+  /// Does the atom need to be redirected using a separate undefined atom ?<br></blockquote><div><br></div><div>Please remove the space before "?"</div><div><br></div><div>Why do we sometimes want to redirect a symbol to an undefined atom? Needs an explanation here.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+  bool redirectReferenceUsingUndefAtom(const Elf_Sym *sourceSymbol,<br>
+                                       const Elf_Sym *targetSymbol) const;<br>
+<br>
   llvm::BumpPtrAllocator _readerStorage;<br>
   std::unique_ptr<llvm::object::ELFFile<ELFT> > _objFile;<br>
   atom_collection_vector<DefinedAtom> _definedAtoms;<br>
@@ -350,6 +380,11 @@ protected:<br>
   std::unordered_map<StringRef, range<Elf_Rel_Iter>> _relocationReferences;<br>
   std::vector<ELFReference<ELFT> *> _references;<br>
   llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;<br>
+  // Group child atoms have a pair corresponding to the signature and the<br>
+  // section header of the section that was used for generating the signature.<br>
+  llvm::DenseMap<const Elf_Sym *, std::pair<StringRef, const Elf_Shdr *>><br>
+      _groupChild;<br>
+  llvm::StringMap<Atom *> _undefAtomsForgroupChild;<br></blockquote><div><br></div><div>undefAtomsForgroupChild -> undefAtomsForGroupChild</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
   /// \brief Atoms that are created for a section that has the merge property<br>
   /// set<br>
@@ -623,6 +658,11 @@ std::error_code ELFFile<ELFT>::createSym<br>
 }<br>
<br>
 template <class ELFT> std::error_code ELFFile<ELFT>::createAtoms() {<br>
+  // Holds all the atoms that are part of the section. They are the targets of<br>
+  // the kindGroupChild reference.<br>
+  llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> atomsForSection;<br>
+  // group sections have a mapping of the section header to the signature.<br>
+  llvm::DenseMap<const Elf_Shdr *, StringRef> groupSections;<br>
   for (auto &i : _sectionSymbols) {<br>
     const Elf_Shdr *section = i.first;<br>
     std::vector<Elf_Sym_Iter> &symbols = i.second;<br>
@@ -641,11 +681,21 @@ template <class ELFT> std::error_code EL<br>
     if (std::error_code ec = sectionContents.getError())<br>
       return ec;<br>
<br>
+    bool addAtoms = true;<br>
+<br>
+    if (isGnuLinkOnceSection(*sectionName)) {<br>
+      groupSections.insert(std::make_pair(section, *sectionName));<br>
+      addAtoms = false;<br>
+    }<br>
+<br>
     if (handleSectionWithNoSymbols(section, symbols)) {<br>
       ELFDefinedAtom<ELFT> *newAtom =<br>
           createSectionAtom(section, *sectionName, *sectionContents);<br>
-      _definedAtoms._atoms.push_back(newAtom);<br>
       newAtom->setOrdinal(++_ordinal);<br>
+      if (addAtoms)<br>
+        _definedAtoms._atoms.push_back(newAtom);<br>
+      else<br>
+        atomsForSection[*sectionName].push_back(newAtom);<br>
       continue;<br>
     }<br>
<br>
@@ -693,8 +743,11 @@ template <class ELFT> std::error_code EL<br>
           auto definedMergeAtom = handleDefinedSymbol(<br>
               symbolName, *sectionName, &**si, section, symbolData,<br>
               _references.size(), _references.size(), _references);<br>
-          _definedAtoms._atoms.push_back(*definedMergeAtom);<br>
           (*definedMergeAtom)->setOrdinal(++_ordinal);<br>
+          if (addAtoms)<br>
+            _definedAtoms._atoms.push_back(*definedMergeAtom);<br>
+          else<br>
+            atomsForSection[*sectionName].push_back(*definedMergeAtom);<br>
         }<br>
         continue;<br>
       }<br>
@@ -740,19 +793,60 @@ template <class ELFT> std::error_code EL<br>
       // is a weak atom.<br>
       previousAtom = anonAtom ? anonAtom : newAtom;<br>
<br>
-      _definedAtoms._atoms.push_back(newAtom);<br>
+      if (addAtoms)<br>
+        _definedAtoms._atoms.push_back(newAtom);<br>
+      else<br>
+        atomsForSection[*sectionName].push_back(newAtom);<br>
+<br>
       _symbolToAtomMapping.insert(std::make_pair(&*symbol, newAtom));<br>
       if (anonAtom) {<br>
         anonAtom->setOrdinal(++_ordinal);<br>
-        _definedAtoms._atoms.push_back(anonAtom);<br>
+        if (addAtoms)<br>
+          _definedAtoms._atoms.push_back(anonAtom);<br>
+        else<br>
+          atomsForSection[*sectionName].push_back(anonAtom);<br>
       }<br>
     }<br>
   }<br>
<br>
+  // Iterate over all the group sections to create parent atoms pointing to<br>
+  // group-child atoms.<br>
+  for (auto &sect : groupSections) {<br>
+    StringRef signature = sect.second;<br>
+    if (isGnuLinkOnceSection(signature))<br>
+      handleGnuLinkOnceSection(signature, atomsForSection, sect.first);<br>
+  }<br>
+<br>
   updateReferences();<br>
   return std::error_code();<br>
 }<br>
<br>
+template <class ELFT><br>
+std::error_code ELFFile<ELFT>::handleGnuLinkOnceSection( <br></blockquote><div><br></div><div>This function never fails, so it should return void isntead of error_code.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+    StringRef signature,<br>
+    llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,<br>
+    const Elf_Shdr *shdr) {<br>
+  unsigned int referenceStart = _references.size();<br>
+  std::vector<ELFReference<ELFT> *> refs;<br>
+  for (auto ha : atomsForSection[signature]) {<br>
+    _groupChild[ha->symbol()] = std::make_pair(signature, shdr);<br>
+    ELFReference<ELFT> *ref =<br>
+        new (_readerStorage) ELFReference<ELFT>(lld::Reference::kindGroupChild);<br>
+    ref->setTarget(ha);<br>
+    refs.push_back(ref);<br>
+  }<br>
+  atomsForSection[signature].clear();<br>
+  // Create a gnu linkonce atom.<br>
+  auto gnuLinkOnceAtom = handleDefinedSymbol(<br>
+      signature, signature, nullptr, shdr, ArrayRef<uint8_t>(), referenceStart,<br>
+      _references.size(), _references);<br>
+  (*gnuLinkOnceAtom)->setOrdinal(++_ordinal);<br>
+  _definedAtoms._atoms.push_back(*gnuLinkOnceAtom);<br>
+  for (auto reference : refs)<br>
+    (*gnuLinkOnceAtom)->addReference(reference);<br>
+  return std::error_code();<br>
+}<br>
+<br>
 template <class ELFT> std::error_code ELFFile<ELFT>::createAtomsFromContext() {<br>
   if (!_useWrap)<br>
     return std::error_code();<br>
@@ -882,7 +976,7 @@ template <class ELFT> void ELFFile<ELFT><br>
       // If the atom is not in mergeable string section, the target atom is<br>
       // simply that atom.<br>
       if (!isMergeableStringSection(shdr)) {<br>
-        ri->setTarget(findAtom(symbol));<br>
+        ri->setTarget(findAtom(ri->symbol(), symbol));<br>
         continue;<br>
       }<br>
       updateReferenceForMergeStringAccess(ri, symbol, shdr);<br>
@@ -954,6 +1048,24 @@ void ELFFile<ELFT>::createEdge(ELFDefine<br>
   from->addReference(reference);<br>
 }<br>
<br>
+/// Does the atom need to be redirected using a separate undefined atom ?<br>
+template <class ELFT><br>
+bool ELFFile<ELFT>::redirectReferenceUsingUndefAtom(<br>
+    const Elf_Sym *sourceSymbol, const Elf_Sym *targetSymbol) const {<br>
+  auto groupChild = _groupChild.find(targetSymbol);<br>
+<br>
+  // If the reference is not to a group child atom, there is no need to redirect<br>
+  // using a undefined atom.<br>
+  if (groupChild == _groupChild.end())<br>
+    return false;<br>
+<br>
+  if (sourceSymbol->st_shndx != targetSymbol->st_shndx) {<br>
+    return true;<br>
+  } </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+  return false;<br></blockquote><div><br></div><div>Just return the condition in the last "if" statement instead of returning true and false.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+} </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
 } // end namespace elf<br>
 } // end namespace lld<br>
<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=230194&r1=230193&r2=230194&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=230194&r1=230193&r2=230194&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)<br>
+++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Sun Feb 22 18:04:49 2015<br>
@@ -361,6 +361,9 @@ const lld::AtomLayout &AtomSection<ELFT><br>
     _atoms.push_back(new (_alloc) lld::AtomLayout(atom, mOffset, 0));<br>
     this->_msize = mOffset + definedAtom->size();<br>
     break;<br>
+  case DefinedAtom::typeGnuLinkOnce:<br>
+    // Discard gnu linkonce atoms as they are just used to identify signature.<br>
+    break;<br>
   default:<br>
     llvm::dbgs() << definedAtom->contentType() << "\n";<br>
     llvm_unreachable("Uexpected content type.");<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/ELF/TODO.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TODO.txt?rev=230194&r1=230193&r2=230194&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TODO.txt?rev=230194&r1=230193&r2=230194&view=diff</a><br>
==============================================================================<br>
--- lld/trunk/lib/ReaderWriter/ELF/TODO.txt (original)<br>
+++ lld/trunk/lib/ReaderWriter/ELF/TODO.txt Sun Feb 22 18:04:49 2015<br>
@@ -14,6 +14,4 @@ lib/ReaderWriter/ELF<br>
<br>
 - Section Groups.<br>
<br>
-- Gnu linkonce sections.<br>
-<br>
 - Fix section flags as they appear in input (update content permissions)<br>
<br>
Added: lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test?rev=230194&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test?rev=230194&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test (added)<br>
+++ lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test Sun Feb 22 18:04:49 2015<br>
@@ -0,0 +1,147 @@<br>
+# Tests that the linker is able to read .gnu.linkonce sections and link them<br>
+# appropriately. The testcase has been created by using the following source<br>
+# code.<br>
+# TODO: This test should produce a discarded reference error message which it<br>
+# doesnot currently.<br>
+# linkoncea.s<br>
+#        .section .gnu.linkonce.d.dummy,"aw"<br>
+#bar:<br>
+#        .long    0<br>
+# linkonceb.s<br>
+#        .section .gnu.linkonce.d.dummy,"aw"<br>
+#foo:<br>
+#        .long    0<br>
+#        .section .blah, "aw"<br>
+#        .long    foo<br>
+#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o<br>
+#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o<br>
+#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \<br>
+#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml<br>
+#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \<br>
+#RUN: --noinhibit-exec -o %t2.out<br>
+#RUN: FileCheck %s -check-prefix=CHECKGNULINKONCE < %t2.out.yaml<br>
+#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGNULINKONCESECTIONS<br>
+#CHECKGNULINKONCE: - name:            .gnu.linkonce.d.dummy<br>
+#CHECKGNULINKONCE:   scope:           global<br>
+#CHECKGNULINKONCE:   type:            gnu-linkonce<br>
+#CHECKGNULINKONCE:   section-choice:  custom-required<br>
+#CHECKGNULINKONCE:   section-name:    .gnu.linkonce.d.dummy<br>
+#CHECKGNULINKONCE:   permissions:     rw-<br>
+#CHECKGNULINKONCE:   references:<br>
+#CHECKGNULINKONCE:     - kind:            group-child<br>
+#CHECKGNULINKONCE:       offset:          0<br>
+#CHECKGNULINKONCE:       target:          bar<br>
+#CHECKGNULINKONCESECTIONS:   Section {<br>
+#CHECKGNULINKONCESECTIONS:     Name: .gnu.linkonce.d.dummy<br>
+#CHECKGNULINKONCESECTIONS:     Type: SHT_PROGBITS<br>
+#CHECKGNULINKONCESECTIONS:     Flags [ (0x3)<br>
+#CHECKGNULINKONCESECTIONS:       SHF_ALLOC (0x2)<br>
+#CHECKGNULINKONCESECTIONS:       SHF_WRITE (0x1)<br>
+#CHECKGNULINKONCESECTIONS:     ]<br>
+#CHECKGNULINKONCESECTIONS:     Size: 4<br>
+#CHECKGNULINKONCESECTIONS:   }<br>
+---<br>
+FileHeader:<br>
+  Class:           ELFCLASS64<br>
+  Data:            ELFDATA2LSB<br>
+  Type:            ET_REL<br>
+  Machine:         EM_X86_64<br>
+Sections:<br>
+  - Name:            .text<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .data<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .bss<br>
+    Type:            SHT_NOBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .gnu.linkonce.d.dummy<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+Symbols:<br>
+  Local:<br>
+    - Name:            .text<br>
+      Type:            STT_SECTION<br>
+      Section:         .text<br>
+    - Name:            .data<br>
+      Type:            STT_SECTION<br>
+      Section:         .data<br>
+    - Name:            .bss<br>
+      Type:            STT_SECTION<br>
+      Section:         .bss<br>
+    - Name:            .gnu.linkonce.d.dummy<br>
+      Type:            STT_SECTION<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+    - Name:            bar<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+...<br>
+---<br>
+FileHeader:<br>
+  Class:           ELFCLASS64<br>
+  Data:            ELFDATA2LSB<br>
+  Type:            ET_REL<br>
+  Machine:         EM_X86_64<br>
+Sections:<br>
+  - Name:            .text<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .data<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .bss<br>
+    Type:            SHT_NOBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .gnu.linkonce.d.dummy<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+  - Name:            .blah<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+  - Name:            .rela.blah<br>
+    Type:            SHT_RELA<br>
+    Link:            .symtab<br>
+    AddressAlign:    0x0000000000000008<br>
+    Info:            .blah<br>
+    Relocations:<br>
+      - Offset:          0x0000000000000000<br>
+        Symbol:          foo<br>
+        Type:            R_X86_64_32<br>
+Symbols:<br>
+  Local:<br>
+    - Name:            .text<br>
+      Type:            STT_SECTION<br>
+      Section:         .text<br>
+    - Name:            .data<br>
+      Type:            STT_SECTION<br>
+      Section:         .data<br>
+    - Name:            .bss<br>
+      Type:            STT_SECTION<br>
+      Section:         .bss<br>
+    - Name:            .gnu.linkonce.d.dummy<br>
+      Type:            STT_SECTION<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+    - Name:            foo<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+    - Name:            .blah<br>
+      Type:            STT_SECTION<br>
+      Section:         .blah<br>
+...<br>
<br>
Added: lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test?rev=230194&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test?rev=230194&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test (added)<br>
+++ lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test Sun Feb 22 18:04:49 2015<br>
@@ -0,0 +1,129 @@<br>
+# Tests that the linker is able to read .gnu.linkonce sections and link them<br>
+# appropriately. The testcase has been created by using the following source<br>
+# code. This test checks that the linker produces an undefined error.<br>
+# linkoncea.s<br>
+#        .section .gnu.linkonce.d.dummy,"aw"<br>
+#bar:<br>
+#        .long    0<br>
+# linkonceb.s<br>
+#        .section .gnu.linkonce.d.dummy,"aw"<br>
+#        .global foo<br>
+#foo:<br>
+#        .long    0<br>
+#        .section .blah, "aw"<br>
+#        .long    foo<br>
+#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o<br>
+#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o<br>
+#RUN: not lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \<br>
+#RUN:  --output-filetype=yaml -o %t2.out.yaml 2>&1 | FileCheck \<br>
+#RUN: -check-prefix=UNDEFS %s<br>
+#RUN: not lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \<br>
+#RUN: -o %t2.out 2>&1 | FileCheck -check-prefix=UNDEFS %s<br>
+#UNDEFS: Undefined symbol: {{.*}} foo<br>
+---<br>
+FileHeader:<br>
+  Class:           ELFCLASS64<br>
+  Data:            ELFDATA2LSB<br>
+  Type:            ET_REL<br>
+  Machine:         EM_X86_64<br>
+Sections:<br>
+  - Name:            .text<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .data<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .bss<br>
+    Type:            SHT_NOBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .gnu.linkonce.d.dummy<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+Symbols:<br>
+  Local:<br>
+    - Name:            .text<br>
+      Type:            STT_SECTION<br>
+      Section:         .text<br>
+    - Name:            .data<br>
+      Type:            STT_SECTION<br>
+      Section:         .data<br>
+    - Name:            .bss<br>
+      Type:            STT_SECTION<br>
+      Section:         .bss<br>
+    - Name:            .gnu.linkonce.d.dummy<br>
+      Type:            STT_SECTION<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+    - Name:            bar<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+...<br>
+---<br>
+FileHeader:<br>
+  Class:           ELFCLASS64<br>
+  Data:            ELFDATA2LSB<br>
+  OSABI:           ELFOSABI_GNU<br>
+  Type:            ET_REL<br>
+  Machine:         EM_X86_64<br>
+Sections:<br>
+  - Name:            .text<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .data<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .bss<br>
+    Type:            SHT_NOBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .gnu.linkonce.d.dummy<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+  - Name:            .blah<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+  - Name:            .rela.blah<br>
+    Type:            SHT_RELA<br>
+    Link:            .symtab<br>
+    AddressAlign:    0x0000000000000008<br>
+    Info:            .blah<br>
+    Relocations:<br>
+      - Offset:          0x0000000000000000<br>
+        Symbol:          foo<br>
+        Type:            R_X86_64_32<br>
+Symbols:<br>
+  Local:<br>
+    - Name:            .text<br>
+      Type:            STT_SECTION<br>
+      Section:         .text<br>
+    - Name:            .data<br>
+      Type:            STT_SECTION<br>
+      Section:         .data<br>
+    - Name:            .bss<br>
+      Type:            STT_SECTION<br>
+      Section:         .bss<br>
+    - Name:            .gnu.linkonce.d.dummy<br>
+      Type:            STT_SECTION<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+    - Name:            .blah<br>
+      Type:            STT_SECTION<br>
+      Section:         .blah<br>
+  Global:<br>
+    - Name:            foo<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+...<br>
<br>
Added: lld/trunk/test/elf/gnulinkonce/gnulinkonce.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce.test?rev=230194&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce.test?rev=230194&view=auto</a><br>
==============================================================================<br>
--- lld/trunk/test/elf/gnulinkonce/gnulinkonce.test (added)<br>
+++ lld/trunk/test/elf/gnulinkonce/gnulinkonce.test Sun Feb 22 18:04:49 2015<br>
@@ -0,0 +1,151 @@<br>
+# Tests that the linker is able to read .gnu.linkonce sections and link them<br>
+# appropriately. The testcase has been created by using the following source<br>
+# code<br>
+# linkonce1a.s<br>
+# ------------<br>
+#        .section .gnu.linkonce.d.dummy,"aw"<br>
+#bar:<br>
+#        .long    0<br>
+# linkonce1b.s<br>
+# ------------<br>
+#    .globl main<br>
+#    .globl start<br>
+#    .globl _start<br>
+#    .globl __start<br>
+#    .text<br>
+#main:<br>
+#start:<br>
+#_start:<br>
+#__start:<br>
+#    .long    0<br>
+#<br>
+#        .section .gnu.linkonce.d.dummy,"aw"<br>
+#foo:<br>
+#        .long    0<br>
+#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o<br>
+#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o<br>
+#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \<br>
+#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml<br>
+#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \<br>
+#RUN: --noinhibit-exec -o %t2.out<br>
+#RUN: FileCheck %s -check-prefix=CHECKGNULINKONCE < %t2.out.yaml<br>
+#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGNULINKONCESECTIONS<br>
+#CHECKGNULINKONCE: - name:            .gnu.linkonce.d.dummy<br>
+#CHECKGNULINKONCE:   scope:           global<br>
+#CHECKGNULINKONCE:   type:            gnu-linkonce<br>
+#CHECKGNULINKONCE:   section-choice:  custom-required<br>
+#CHECKGNULINKONCE:   section-name:    .gnu.linkonce.d.dummy<br>
+#CHECKGNULINKONCE:   permissions:     rw-<br>
+#CHECKGNULINKONCE:   references:<br>
+#CHECKGNULINKONCE:     - kind:            group-child<br>
+#CHECKGNULINKONCE:       offset:          0<br>
+#CHECKGNULINKONCE:       target:          bar<br>
+#CHECKGNULINKONCE:     - kind:            group-child<br>
+#CHECKGNULINKONCE:       offset:          0<br>
+#CHECKGNULINKONCESECTIONS:   Section {<br>
+#CHECKGNULINKONCESECTIONS:     Name: .gnu.linkonce.d.dummy<br>
+#CHECKGNULINKONCESECTIONS:     Type: SHT_PROGBITS<br>
+#CHECKGNULINKONCESECTIONS:     Flags [ (0x3)<br>
+#CHECKGNULINKONCESECTIONS:       SHF_ALLOC (0x2)<br>
+#CHECKGNULINKONCESECTIONS:       SHF_WRITE (0x1)<br>
+#CHECKGNULINKONCESECTIONS:     ]<br>
+#CHECKGNULINKONCESECTIONS:     Size: 4<br>
+#CHECKGNULINKONCESECTIONS:   }<br>
+---<br>
+FileHeader:<br>
+  Class:           ELFCLASS64<br>
+  Data:            ELFDATA2LSB<br>
+  OSABI:           ELFOSABI_GNU<br>
+  Type:            ET_REL<br>
+  Machine:         EM_X86_64<br>
+Sections:<br>
+  - Name:            .text<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .data<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .bss<br>
+    Type:            SHT_NOBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .gnu.linkonce.d.dummy<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+Symbols:<br>
+  Local:<br>
+    - Name:            bar<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+    - Name:            .text<br>
+      Type:            STT_SECTION<br>
+      Section:         .text<br>
+    - Name:            .data<br>
+      Type:            STT_SECTION<br>
+      Section:         .data<br>
+    - Name:            .bss<br>
+      Type:            STT_SECTION<br>
+      Section:         .bss<br>
+    - Name:            .gnu.linkonce.d.dummy<br>
+      Type:            STT_SECTION<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+...<br>
+---<br>
+FileHeader:<br>
+  Class:           ELFCLASS64<br>
+  Data:            ELFDATA2LSB<br>
+  Type:            ET_REL<br>
+  Machine:         EM_X86_64<br>
+Sections:<br>
+  - Name:            .text<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         '00000000'<br>
+  - Name:            .data<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .bss<br>
+    Type:            SHT_NOBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000004<br>
+    Content:         ''<br>
+  - Name:            .gnu.linkonce.d.dummy<br>
+    Type:            SHT_PROGBITS<br>
+    Flags:           [ SHF_WRITE, SHF_ALLOC ]<br>
+    AddressAlign:    0x0000000000000001<br>
+    Content:         '00000000'<br>
+Symbols:<br>
+  Local:<br>
+    - Name:            .text<br>
+      Type:            STT_SECTION<br>
+      Section:         .text<br>
+    - Name:            .data<br>
+      Type:            STT_SECTION<br>
+      Section:         .data<br>
+    - Name:            .bss<br>
+      Type:            STT_SECTION<br>
+      Section:         .bss<br>
+    - Name:            .gnu.linkonce.d.dummy<br>
+      Type:            STT_SECTION<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+    - Name:            foo<br>
+      Section:         .gnu.linkonce.d.dummy<br>
+  Global:<br>
+    - Name:            main<br>
+      Section:         .text<br>
+    - Name:            start<br>
+      Section:         .text<br>
+    - Name:            _start<br>
+      Section:         .text<br>
+    - Name:            __start<br>
+      Section:         .text<br>
+...<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>