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