[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 § : 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