[lld] r230194 - [ELF] Add .gnu.linkonce support.

Rui Ueyama ruiu at google.com
Sun Feb 22 19:20:43 PST 2015


This is really nontrivial pieces of code. You may want to do pre-submit
review next time.

On Sun, Feb 22, 2015 at 4:04 PM, Shankar Easwaran <shankare at codeaurora.org>
wrote:

> Author: shankare
> Date: Sun Feb 22 18:04:49 2015
> New Revision: 230194
>
> URL: http://llvm.org/viewvc/llvm-project?rev=230194&view=rev
> Log:
> [ELF] Add .gnu.linkonce support.
>
> When the GNU linker sees two input sections with the same name, and the
> name
> starts with ".gnu.linkonce.", the linker will only keep one copy and
> discard the
> other. Any section whose name starts with “.gnu.linkonce.” is a COMDAT
> section.
>
> Some architectures like Hexagon use this section to store floating point
> constants,
> that need be deduped.
>
> This patch adds gnu.linkonce functionality to the ELFReader.
>
> Added:
>     lld/trunk/test/elf/gnulinkonce/
>
> lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
>     lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test
>     lld/trunk/test/elf/gnulinkonce/gnulinkonce.test
> Modified:
>     lld/trunk/lib/ReaderWriter/ELF/Atoms.h
>     lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
>     lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
>     lld/trunk/lib/ReaderWriter/ELF/TODO.txt
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/Atoms.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/Atoms.h?rev=230194&r1=230193&r2=230194&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/Atoms.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/Atoms.h Sun Feb 22 18:04:49 2015
> @@ -179,14 +179,16 @@ public:
>    uint64_t size() const override {
>      // Common symbols are not allocated in object files,
>      // so use st_size to tell how many bytes are required.
> -    if ((_symbol->getType() == llvm::ELF::STT_COMMON) ||
> -        _symbol->st_shndx == llvm::ELF::SHN_COMMON)
> +    if (_symbol && (_symbol->getType() == llvm::ELF::STT_COMMON ||
> +                    _symbol->st_shndx == llvm::ELF::SHN_COMMON))
>        return (uint64_t) _symbol->st_size;
>
>      return _contentData.size();
>    }
>
>    Scope scope() const override {
> +    if (!_symbol)
> +      return scopeGlobal;
>

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.


>      if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
>        return scopeLinkageUnit;
>      else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
> @@ -199,6 +201,9 @@ public:
>    Interposable interposable() const override { return interposeNo; }
>
>    Merge merge() const override {
> +    if (!_symbol)
> +      return mergeNo;
> +
>      if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
>        return mergeAsWeak;
>
> @@ -216,6 +221,9 @@ public:
>      ContentType ret = typeUnknown;
>      uint64_t flags = _section->sh_flags;
>
> +    if (!_symbol && _sectionName.startswith(".gnu.linkonce"))
>

In the commit message you wrote that sections starts with "gnu.linkonce."
is GNU linkonce sections. You dropped the last "." (dot) here.


> +      return typeGnuLinkOnce;
> +
>      if (!(flags & llvm::ELF::SHF_ALLOC))
>        return _contentType = typeNoAlloc;
>
> @@ -286,6 +294,9 @@ public:
>    }
>
>    Alignment alignment() const override {
> +    if (!_symbol)
> +      return Alignment(0);
> +
>      // Obtain proper value of st_value field.
>      const auto symValue = getSymbolValue(_symbol);
>
> @@ -323,7 +334,7 @@ public:
>
>    StringRef customSectionName() const override {
>      if ((contentType() == typeZeroFill) ||
> -        (_symbol->st_shndx == llvm::ELF::SHN_COMMON))
> +        (_symbol && _symbol->st_shndx == llvm::ELF::SHN_COMMON))
>        return ".bss";
>      return _sectionName;
>    }
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/ELFFile.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/ELFFile.h?rev=230194&r1=230193&r2=230194&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/ELFFile.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/ELFFile.h Sun Feb 22 18:04:49 2015
> @@ -168,8 +168,23 @@ public:
>      return _absoluteAtoms;
>    }
>
> -  Atom *findAtom(const Elf_Sym *symbol) {
> -    return _symbolToAtomMapping.lookup(symbol);
> +  Atom *findAtom(const Elf_Sym *sourceSymbol, const Elf_Sym
> *targetSymbol) {
> +    // All references to atoms inside a group are through undefined atoms.
> +    Atom *targetAtom = _symbolToAtomMapping.lookup(targetSymbol);
> +    if (targetAtom->definition() != Atom::definitionRegular)
> +      return targetAtom;
> +    if ((llvm::dyn_cast<DefinedAtom>(targetAtom))->scope() ==
> +        DefinedAtom::scopeTranslationUnit)
> +      return targetAtom;
> +    if (!redirectReferenceUsingUndefAtom(sourceSymbol, targetSymbol))
> +      return targetAtom;
> +    auto undefForGroupchild =
> _undefAtomsForgroupChild.find(targetAtom->name());
> +    if (undefForGroupchild != _undefAtomsForgroupChild.end())
> +      return undefForGroupchild->getValue();
> +    auto undefGroupChildAtom =
> +        new (_readerStorage) SimpleUndefinedAtom(*this,
> targetAtom->name());
> +    _undefinedAtoms._atoms.push_back(undefGroupChildAtom);
> +    return (_undefAtomsForgroupChild[targetAtom->name()] =
> undefGroupChildAtom);
>    }
>

This really needs a comment to describe what the intention of the
conditions is.


>
>  protected:
> @@ -258,6 +273,12 @@ protected:
>      return shdr && (shdr->sh_type == llvm::ELF::SHT_PROGBITS) &&
> syms.empty();
>    }
>
> +  /// Handle creation of atoms for .gnu.linkonce sections.
> +  std::error_code handleGnuLinkOnceSection(
> +      StringRef sectionName,
> +      llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>>
> &atomsForSection,
> +      const Elf_Shdr *shdr);
> +
>    /// Process the Undefined symbol and create an atom for it.
>    ErrorOr<ELFUndefinedAtom<ELFT> *>
>    handleUndefinedSymbol(StringRef symName, const Elf_Sym *sym) {
> @@ -286,6 +307,11 @@ protected:
>             symbol->st_shndx == llvm::ELF::SHN_COMMON;
>    }
>
> +  /// Returns true if the section is a gnulinkonce section.
> +  bool isGnuLinkOnceSection(StringRef sectionName) const {
> +    return sectionName.startswith(".gnu.linkonce");
> +  }
> +
>    /// Returns correct st_value for the symbol depending on the
> architecture.
>    /// For most architectures it's just a regular st_value with no changes.
>    virtual uint64_t getSymbolValue(const Elf_Sym *symbol) const {
> @@ -333,6 +359,10 @@ protected:
>      return mergeAtom;
>    }
>
> +  /// Does the atom need to be redirected using a separate undefined atom
> ?
>

Please remove the space before "?"

Why do we sometimes want to redirect a symbol to an undefined atom? Needs
an explanation here.


> +  bool redirectReferenceUsingUndefAtom(const Elf_Sym *sourceSymbol,
> +                                       const Elf_Sym *targetSymbol) const;
> +
>    llvm::BumpPtrAllocator _readerStorage;
>    std::unique_ptr<llvm::object::ELFFile<ELFT> > _objFile;
>    atom_collection_vector<DefinedAtom> _definedAtoms;
> @@ -350,6 +380,11 @@ protected:
>    std::unordered_map<StringRef, range<Elf_Rel_Iter>>
> _relocationReferences;
>    std::vector<ELFReference<ELFT> *> _references;
>    llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
> +  // Group child atoms have a pair corresponding to the signature and the
> +  // section header of the section that was used for generating the
> signature.
> +  llvm::DenseMap<const Elf_Sym *, std::pair<StringRef, const Elf_Shdr *>>
> +      _groupChild;
> +  llvm::StringMap<Atom *> _undefAtomsForgroupChild;
>

undefAtomsForgroupChild -> undefAtomsForGroupChild


>    /// \brief Atoms that are created for a section that has the merge
> property
>    /// set
> @@ -623,6 +658,11 @@ std::error_code ELFFile<ELFT>::createSym
>  }
>
>  template <class ELFT> std::error_code ELFFile<ELFT>::createAtoms() {
> +  // Holds all the atoms that are part of the section. They are the
> targets of
> +  // the kindGroupChild reference.
> +  llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> atomsForSection;
> +  // group sections have a mapping of the section header to the signature.
> +  llvm::DenseMap<const Elf_Shdr *, StringRef> groupSections;
>    for (auto &i : _sectionSymbols) {
>      const Elf_Shdr *section = i.first;
>      std::vector<Elf_Sym_Iter> &symbols = i.second;
> @@ -641,11 +681,21 @@ template <class ELFT> std::error_code EL
>      if (std::error_code ec = sectionContents.getError())
>        return ec;
>
> +    bool addAtoms = true;
> +
> +    if (isGnuLinkOnceSection(*sectionName)) {
> +      groupSections.insert(std::make_pair(section, *sectionName));
> +      addAtoms = false;
> +    }
> +
>      if (handleSectionWithNoSymbols(section, symbols)) {
>        ELFDefinedAtom<ELFT> *newAtom =
>            createSectionAtom(section, *sectionName, *sectionContents);
> -      _definedAtoms._atoms.push_back(newAtom);
>        newAtom->setOrdinal(++_ordinal);
> +      if (addAtoms)
> +        _definedAtoms._atoms.push_back(newAtom);
> +      else
> +        atomsForSection[*sectionName].push_back(newAtom);
>        continue;
>      }
>
> @@ -693,8 +743,11 @@ template <class ELFT> std::error_code EL
>            auto definedMergeAtom = handleDefinedSymbol(
>                symbolName, *sectionName, &**si, section, symbolData,
>                _references.size(), _references.size(), _references);
> -          _definedAtoms._atoms.push_back(*definedMergeAtom);
>            (*definedMergeAtom)->setOrdinal(++_ordinal);
> +          if (addAtoms)
> +            _definedAtoms._atoms.push_back(*definedMergeAtom);
> +          else
> +            atomsForSection[*sectionName].push_back(*definedMergeAtom);
>          }
>          continue;
>        }
> @@ -740,19 +793,60 @@ template <class ELFT> std::error_code EL
>        // is a weak atom.
>        previousAtom = anonAtom ? anonAtom : newAtom;
>
> -      _definedAtoms._atoms.push_back(newAtom);
> +      if (addAtoms)
> +        _definedAtoms._atoms.push_back(newAtom);
> +      else
> +        atomsForSection[*sectionName].push_back(newAtom);
> +
>        _symbolToAtomMapping.insert(std::make_pair(&*symbol, newAtom));
>        if (anonAtom) {
>          anonAtom->setOrdinal(++_ordinal);
> -        _definedAtoms._atoms.push_back(anonAtom);
> +        if (addAtoms)
> +          _definedAtoms._atoms.push_back(anonAtom);
> +        else
> +          atomsForSection[*sectionName].push_back(anonAtom);
>        }
>      }
>    }
>
> +  // Iterate over all the group sections to create parent atoms pointing
> to
> +  // group-child atoms.
> +  for (auto &sect : groupSections) {
> +    StringRef signature = sect.second;
> +    if (isGnuLinkOnceSection(signature))
> +      handleGnuLinkOnceSection(signature, atomsForSection, sect.first);
> +  }
> +
>    updateReferences();
>    return std::error_code();
>  }
>
> +template <class ELFT>
> +std::error_code ELFFile<ELFT>::handleGnuLinkOnceSection(
>

This function never fails, so it should return void isntead of error_code.


> +    StringRef signature,
> +    llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
> +    const Elf_Shdr *shdr) {
> +  unsigned int referenceStart = _references.size();
> +  std::vector<ELFReference<ELFT> *> refs;
> +  for (auto ha : atomsForSection[signature]) {
> +    _groupChild[ha->symbol()] = std::make_pair(signature, shdr);
> +    ELFReference<ELFT> *ref =
> +        new (_readerStorage)
> ELFReference<ELFT>(lld::Reference::kindGroupChild);
> +    ref->setTarget(ha);
> +    refs.push_back(ref);
> +  }
> +  atomsForSection[signature].clear();
> +  // Create a gnu linkonce atom.
> +  auto gnuLinkOnceAtom = handleDefinedSymbol(
> +      signature, signature, nullptr, shdr, ArrayRef<uint8_t>(),
> referenceStart,
> +      _references.size(), _references);
> +  (*gnuLinkOnceAtom)->setOrdinal(++_ordinal);
> +  _definedAtoms._atoms.push_back(*gnuLinkOnceAtom);
> +  for (auto reference : refs)
> +    (*gnuLinkOnceAtom)->addReference(reference);
> +  return std::error_code();
> +}
> +
>  template <class ELFT> std::error_code
> ELFFile<ELFT>::createAtomsFromContext() {
>    if (!_useWrap)
>      return std::error_code();
> @@ -882,7 +976,7 @@ template <class ELFT> void ELFFile<ELFT>
>        // If the atom is not in mergeable string section, the target atom
> is
>        // simply that atom.
>        if (!isMergeableStringSection(shdr)) {
> -        ri->setTarget(findAtom(symbol));
> +        ri->setTarget(findAtom(ri->symbol(), symbol));
>          continue;
>        }
>        updateReferenceForMergeStringAccess(ri, symbol, shdr);
> @@ -954,6 +1048,24 @@ void ELFFile<ELFT>::createEdge(ELFDefine
>    from->addReference(reference);
>  }
>
> +/// Does the atom need to be redirected using a separate undefined atom ?
> +template <class ELFT>
> +bool ELFFile<ELFT>::redirectReferenceUsingUndefAtom(
> +    const Elf_Sym *sourceSymbol, const Elf_Sym *targetSymbol) const {
> +  auto groupChild = _groupChild.find(targetSymbol);
> +
> +  // If the reference is not to a group child atom, there is no need to
> redirect
> +  // using a undefined atom.
> +  if (groupChild == _groupChild.end())
> +    return false;
> +
> +  if (sourceSymbol->st_shndx != targetSymbol->st_shndx) {
> +    return true;
> +  }

+
> +  return false;
>

Just return the condition in the last "if" statement instead of returning
true and false.


> +}

+
>  } // end namespace elf
>  } // end namespace lld
>
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h?rev=230194&r1=230193&r2=230194&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/SectionChunks.h Sun Feb 22 18:04:49 2015
> @@ -361,6 +361,9 @@ const lld::AtomLayout &AtomSection<ELFT>
>      _atoms.push_back(new (_alloc) lld::AtomLayout(atom, mOffset, 0));
>      this->_msize = mOffset + definedAtom->size();
>      break;
> +  case DefinedAtom::typeGnuLinkOnce:
> +    // Discard gnu linkonce atoms as they are just used to identify
> signature.
> +    break;
>    default:
>      llvm::dbgs() << definedAtom->contentType() << "\n";
>      llvm_unreachable("Uexpected content type.");
>
> Modified: lld/trunk/lib/ReaderWriter/ELF/TODO.txt
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/TODO.txt?rev=230194&r1=230193&r2=230194&view=diff
>
> ==============================================================================
> --- lld/trunk/lib/ReaderWriter/ELF/TODO.txt (original)
> +++ lld/trunk/lib/ReaderWriter/ELF/TODO.txt Sun Feb 22 18:04:49 2015
> @@ -14,6 +14,4 @@ lib/ReaderWriter/ELF
>
>  - Section Groups.
>
> -- Gnu linkonce sections.
> -
>  - Fix section flags as they appear in input (update content permissions)
>
> Added:
> lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test?rev=230194&view=auto
>
> ==============================================================================
> ---
> lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
> (added)
> +++
> lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
> Sun Feb 22 18:04:49 2015
> @@ -0,0 +1,147 @@
> +# Tests that the linker is able to read .gnu.linkonce sections and link
> them
> +# appropriately. The testcase has been created by using the following
> source
> +# code.
> +# TODO: This test should produce a discarded reference error message
> which it
> +# doesnot currently.
> +# linkoncea.s
> +#        .section .gnu.linkonce.d.dummy,"aw"
> +#bar:
> +#        .long    0
> +# linkonceb.s
> +#        .section .gnu.linkonce.d.dummy,"aw"
> +#foo:
> +#        .long    0
> +#        .section .blah, "aw"
> +#        .long    foo
> +#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o
> +#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o
> +#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
> +#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
> +#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
> +#RUN: --noinhibit-exec -o %t2.out
> +#RUN: FileCheck %s -check-prefix=CHECKGNULINKONCE < %t2.out.yaml
> +#RUN: llvm-readobj -sections %t2.out | FileCheck %s
> -check-prefix=CHECKGNULINKONCESECTIONS
> +#CHECKGNULINKONCE: - name:            .gnu.linkonce.d.dummy
> +#CHECKGNULINKONCE:   scope:           global
> +#CHECKGNULINKONCE:   type:            gnu-linkonce
> +#CHECKGNULINKONCE:   section-choice:  custom-required
> +#CHECKGNULINKONCE:   section-name:    .gnu.linkonce.d.dummy
> +#CHECKGNULINKONCE:   permissions:     rw-
> +#CHECKGNULINKONCE:   references:
> +#CHECKGNULINKONCE:     - kind:            group-child
> +#CHECKGNULINKONCE:       offset:          0
> +#CHECKGNULINKONCE:       target:          bar
> +#CHECKGNULINKONCESECTIONS:   Section {
> +#CHECKGNULINKONCESECTIONS:     Name: .gnu.linkonce.d.dummy
> +#CHECKGNULINKONCESECTIONS:     Type: SHT_PROGBITS
> +#CHECKGNULINKONCESECTIONS:     Flags [ (0x3)
> +#CHECKGNULINKONCESECTIONS:       SHF_ALLOC (0x2)
> +#CHECKGNULINKONCESECTIONS:       SHF_WRITE (0x1)
> +#CHECKGNULINKONCESECTIONS:     ]
> +#CHECKGNULINKONCESECTIONS:     Size: 4
> +#CHECKGNULINKONCESECTIONS:   }
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .data
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .bss
> +    Type:            SHT_NOBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .gnu.linkonce.d.dummy
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +Symbols:
> +  Local:
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .gnu.linkonce.d.dummy
> +      Type:            STT_SECTION
> +      Section:         .gnu.linkonce.d.dummy
> +    - Name:            bar
> +      Section:         .gnu.linkonce.d.dummy
> +...
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .data
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .bss
> +    Type:            SHT_NOBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .gnu.linkonce.d.dummy
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +  - Name:            .blah
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +  - Name:            .rela.blah
> +    Type:            SHT_RELA
> +    Link:            .symtab
> +    AddressAlign:    0x0000000000000008
> +    Info:            .blah
> +    Relocations:
> +      - Offset:          0x0000000000000000
> +        Symbol:          foo
> +        Type:            R_X86_64_32
> +Symbols:
> +  Local:
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .gnu.linkonce.d.dummy
> +      Type:            STT_SECTION
> +      Section:         .gnu.linkonce.d.dummy
> +    - Name:            foo
> +      Section:         .gnu.linkonce.d.dummy
> +    - Name:            .blah
> +      Type:            STT_SECTION
> +      Section:         .blah
> +...
>
> Added: lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test?rev=230194&view=auto
>
> ==============================================================================
> --- lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test (added)
> +++ lld/trunk/test/elf/gnulinkonce/gnulinkonce-report-undef.test Sun Feb
> 22 18:04:49 2015
> @@ -0,0 +1,129 @@
> +# Tests that the linker is able to read .gnu.linkonce sections and link
> them
> +# appropriately. The testcase has been created by using the following
> source
> +# code. This test checks that the linker produces an undefined error.
> +# linkoncea.s
> +#        .section .gnu.linkonce.d.dummy,"aw"
> +#bar:
> +#        .long    0
> +# linkonceb.s
> +#        .section .gnu.linkonce.d.dummy,"aw"
> +#        .global foo
> +#foo:
> +#        .long    0
> +#        .section .blah, "aw"
> +#        .long    foo
> +#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o
> +#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o
> +#RUN: not lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
> +#RUN:  --output-filetype=yaml -o %t2.out.yaml 2>&1 | FileCheck \
> +#RUN: -check-prefix=UNDEFS %s
> +#RUN: not lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
> +#RUN: -o %t2.out 2>&1 | FileCheck -check-prefix=UNDEFS %s
> +#UNDEFS: Undefined symbol: {{.*}} foo
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .data
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .bss
> +    Type:            SHT_NOBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .gnu.linkonce.d.dummy
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +Symbols:
> +  Local:
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .gnu.linkonce.d.dummy
> +      Type:            STT_SECTION
> +      Section:         .gnu.linkonce.d.dummy
> +    - Name:            bar
> +      Section:         .gnu.linkonce.d.dummy
> +...
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  OSABI:           ELFOSABI_GNU
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .data
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .bss
> +    Type:            SHT_NOBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .gnu.linkonce.d.dummy
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +  - Name:            .blah
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +  - Name:            .rela.blah
> +    Type:            SHT_RELA
> +    Link:            .symtab
> +    AddressAlign:    0x0000000000000008
> +    Info:            .blah
> +    Relocations:
> +      - Offset:          0x0000000000000000
> +        Symbol:          foo
> +        Type:            R_X86_64_32
> +Symbols:
> +  Local:
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .gnu.linkonce.d.dummy
> +      Type:            STT_SECTION
> +      Section:         .gnu.linkonce.d.dummy
> +    - Name:            .blah
> +      Type:            STT_SECTION
> +      Section:         .blah
> +  Global:
> +    - Name:            foo
> +      Section:         .gnu.linkonce.d.dummy
> +...
>
> Added: lld/trunk/test/elf/gnulinkonce/gnulinkonce.test
> URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf/gnulinkonce/gnulinkonce.test?rev=230194&view=auto
>
> ==============================================================================
> --- lld/trunk/test/elf/gnulinkonce/gnulinkonce.test (added)
> +++ lld/trunk/test/elf/gnulinkonce/gnulinkonce.test Sun Feb 22 18:04:49
> 2015
> @@ -0,0 +1,151 @@
> +# Tests that the linker is able to read .gnu.linkonce sections and link
> them
> +# appropriately. The testcase has been created by using the following
> source
> +# code
> +# linkonce1a.s
> +# ------------
> +#        .section .gnu.linkonce.d.dummy,"aw"
> +#bar:
> +#        .long    0
> +# linkonce1b.s
> +# ------------
> +#    .globl main
> +#    .globl start
> +#    .globl _start
> +#    .globl __start
> +#    .text
> +#main:
> +#start:
> +#_start:
> +#__start:
> +#    .long    0
> +#
> +#        .section .gnu.linkonce.d.dummy,"aw"
> +#foo:
> +#        .long    0
> +#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.linkonce1a.o
> +#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.linkonce1b.o
> +#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
> +#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
> +#RUN: lld -flavor gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
> +#RUN: --noinhibit-exec -o %t2.out
> +#RUN: FileCheck %s -check-prefix=CHECKGNULINKONCE < %t2.out.yaml
> +#RUN: llvm-readobj -sections %t2.out | FileCheck %s
> -check-prefix=CHECKGNULINKONCESECTIONS
> +#CHECKGNULINKONCE: - name:            .gnu.linkonce.d.dummy
> +#CHECKGNULINKONCE:   scope:           global
> +#CHECKGNULINKONCE:   type:            gnu-linkonce
> +#CHECKGNULINKONCE:   section-choice:  custom-required
> +#CHECKGNULINKONCE:   section-name:    .gnu.linkonce.d.dummy
> +#CHECKGNULINKONCE:   permissions:     rw-
> +#CHECKGNULINKONCE:   references:
> +#CHECKGNULINKONCE:     - kind:            group-child
> +#CHECKGNULINKONCE:       offset:          0
> +#CHECKGNULINKONCE:       target:          bar
> +#CHECKGNULINKONCE:     - kind:            group-child
> +#CHECKGNULINKONCE:       offset:          0
> +#CHECKGNULINKONCESECTIONS:   Section {
> +#CHECKGNULINKONCESECTIONS:     Name: .gnu.linkonce.d.dummy
> +#CHECKGNULINKONCESECTIONS:     Type: SHT_PROGBITS
> +#CHECKGNULINKONCESECTIONS:     Flags [ (0x3)
> +#CHECKGNULINKONCESECTIONS:       SHF_ALLOC (0x2)
> +#CHECKGNULINKONCESECTIONS:       SHF_WRITE (0x1)
> +#CHECKGNULINKONCESECTIONS:     ]
> +#CHECKGNULINKONCESECTIONS:     Size: 4
> +#CHECKGNULINKONCESECTIONS:   }
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  OSABI:           ELFOSABI_GNU
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .data
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .bss
> +    Type:            SHT_NOBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .gnu.linkonce.d.dummy
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +Symbols:
> +  Local:
> +    - Name:            bar
> +      Section:         .gnu.linkonce.d.dummy
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .gnu.linkonce.d.dummy
> +      Type:            STT_SECTION
> +      Section:         .gnu.linkonce.d.dummy
> +...
> +---
> +FileHeader:
> +  Class:           ELFCLASS64
> +  Data:            ELFDATA2LSB
> +  Type:            ET_REL
> +  Machine:         EM_X86_64
> +Sections:
> +  - Name:            .text
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         '00000000'
> +  - Name:            .data
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .bss
> +    Type:            SHT_NOBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000004
> +    Content:         ''
> +  - Name:            .gnu.linkonce.d.dummy
> +    Type:            SHT_PROGBITS
> +    Flags:           [ SHF_WRITE, SHF_ALLOC ]
> +    AddressAlign:    0x0000000000000001
> +    Content:         '00000000'
> +Symbols:
> +  Local:
> +    - Name:            .text
> +      Type:            STT_SECTION
> +      Section:         .text
> +    - Name:            .data
> +      Type:            STT_SECTION
> +      Section:         .data
> +    - Name:            .bss
> +      Type:            STT_SECTION
> +      Section:         .bss
> +    - Name:            .gnu.linkonce.d.dummy
> +      Type:            STT_SECTION
> +      Section:         .gnu.linkonce.d.dummy
> +    - Name:            foo
> +      Section:         .gnu.linkonce.d.dummy
> +  Global:
> +    - Name:            main
> +      Section:         .text
> +    - Name:            start
> +      Section:         .text
> +    - Name:            _start
> +      Section:         .text
> +    - Name:            __start
> +      Section:         .text
> +...
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150222/dfce8722/attachment.html>


More information about the llvm-commits mailing list