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;
if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
return scopeLinkageUnit;
else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
Interposable interposable() const override { return interposeNo; }
Merge merge() const override {
+ if (!_symbol)
+ return mergeNo;
+
if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
return mergeAsWeak;
ContentType ret = typeUnknown;
uint64_t flags = _section->sh_flags;
+ if (!_symbol && _sectionName.startswith(".gnu.linkonce"))
+ return typeGnuLinkOnce;
+
if (!(flags & llvm::ELF::SHF_ALLOC))
return _contentType = typeNoAlloc;
}
Alignment alignment() const override {
+ if (!_symbol)
+ return Alignment(0);
+
// Obtain proper value of st_value field.
const auto symValue = getSymbolValue(_symbol);
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;
}
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);
}
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) {
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 {
return mergeAtom;
}
+ /// Does the atom need to be redirected using a separate undefined atom ?
+ 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;
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;
/// \brief Atoms that are created for a section that has the merge property
/// set
}
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;
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;
}
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;
}
// 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(
+ 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();
// 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);
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;
+}
+
} // end namespace elf
} // end namespace lld
_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.");
- Section Groups.
-- Gnu linkonce sections.
-
- Fix section flags as they appear in input (update content permissions)
--- /dev/null
+# 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
+...
--- /dev/null
+# 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
+...
--- /dev/null
+# 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
+...