[ELF] Add section group/COMDAT support.

SHF_GROUP: Group Member Sections
----------------------------------
A section which is part of a group, and is to be retained or discarded with the
group as a whole, is identified by a new section header attribute: SHF_GROUP
This section is a member (perhaps the only one) of a group of sections, and the
linker should retain or discard all or none of the members. This section must be
referenced in a SHT_GROUP section. This attribute flag may be set in any section
header, and no other modification or indication is made in the grouped sections.
All additional information is contained in the associated SHT_GROUP section.

SHT_GROUP: Section Group Definition
-------------------------------------
Represents a group section.

The section group's sh_link field identifies a symbol table section, and its
sh_info field the index of a symbol in that section. The name of that symbol is
treated as the identifier of the section group.

More information: https://mentorembedded.github.io/cxx-abi/abi/prop-72-comdat.html

Added a lot of extensive tests, that tests functionality.

llvm-svn: 230195
This commit is contained in:
Shankar Easwaran 2015-02-23 00:30:00 +00:00
parent de4a31909f
commit 9e07346679
15 changed files with 1459 additions and 30 deletions

View File

@ -221,6 +221,9 @@ public:
ContentType ret = typeUnknown;
uint64_t flags = _section->sh_flags;
if (_section->sh_type == llvm::ELF::SHT_GROUP)
return typeGroupComdat;
if (!_symbol && _sectionName.startswith(".gnu.linkonce"))
return typeGnuLinkOnce;

View File

@ -196,7 +196,7 @@ public:
static bool hasOutputSegment(Section<ELFT> *section);
// Adds an atom to the section
ErrorOr<const lld::AtomLayout &> addAtom(const Atom *atom) override;
ErrorOr<const lld::AtomLayout *> addAtom(const Atom *atom) override;
/// \brief Find an output Section given a section name.
OutputSection<ELFT> *findOutputSection(StringRef name) {
@ -553,7 +553,8 @@ DefaultLayout<ELFT>::getSection(StringRef sectionName, int32_t contentType,
}
template <class ELFT>
ErrorOr<const lld::AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom) {
ErrorOr<const lld::AtomLayout *>
DefaultLayout<ELFT>::addAtom(const Atom *atom) {
if (const DefinedAtom *definedAtom = dyn_cast<DefinedAtom>(atom)) {
// HACK: Ignore undefined atoms. We need to adjust the interface so that
// undefined atoms can still be included in the output symbol table for
@ -600,7 +601,7 @@ ErrorOr<const lld::AtomLayout &> DefaultLayout<ELFT>::addAtom(const Atom *atom)
// link
_absoluteAtoms.push_back(new (_allocator)
lld::AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
return *_absoluteAtoms.back();
return _absoluteAtoms.back();
} else {
llvm_unreachable("Only absolute / defined atoms can be added here");
}

View File

@ -50,6 +50,7 @@ template <class ELFT> class ELFFile : public File {
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Iter Elf_Sym_Iter;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela_Iter Elf_Rela_Iter;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter;
typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
// A Map is used to hold the atoms that have been divided up
// after reading the section that contains Merge String attributes
@ -171,6 +172,7 @@ public:
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);
StringRef targetSymbolName = targetAtom->name();
if (targetAtom->definition() != Atom::definitionRegular)
return targetAtom;
if ((llvm::dyn_cast<DefinedAtom>(targetAtom))->scope() ==
@ -178,13 +180,13 @@ public:
return targetAtom;
if (!redirectReferenceUsingUndefAtom(sourceSymbol, targetSymbol))
return targetAtom;
auto undefForGroupchild = _undefAtomsForgroupChild.find(targetAtom->name());
auto undefForGroupchild = _undefAtomsForgroupChild.find(targetSymbolName);
if (undefForGroupchild != _undefAtomsForgroupChild.end())
return undefForGroupchild->getValue();
auto undefGroupChildAtom =
new (_readerStorage) SimpleUndefinedAtom(*this, targetAtom->name());
new (_readerStorage) SimpleUndefinedAtom(*this, targetSymbolName);
_undefinedAtoms._atoms.push_back(undefGroupChildAtom);
return (_undefAtomsForgroupChild[targetAtom->name()] = undefGroupChildAtom);
return (_undefAtomsForgroupChild[targetSymbolName] = undefGroupChildAtom);
}
protected:
@ -279,6 +281,13 @@ protected:
llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
const Elf_Shdr *shdr);
// Handle Section groups/COMDAT scetions.
std::error_code handleSectionGroup(
StringRef signature, StringRef groupSectionName,
llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
llvm::DenseMap<const Elf_Shdr *, std::vector<StringRef>> &comdatSections,
const Elf_Shdr *shdr);
/// Process the Undefined symbol and create an atom for it.
ErrorOr<ELFUndefinedAtom<ELFT> *>
handleUndefinedSymbol(StringRef symName, const Elf_Sym *sym) {
@ -312,6 +321,16 @@ protected:
return sectionName.startswith(".gnu.linkonce");
}
/// Returns true if the section is a COMDAT group section.
bool isGroupSection(const Elf_Shdr *shdr) const {
return (shdr->sh_type == llvm::ELF::SHT_GROUP);
}
/// Returns true if the section is a member of some group.
bool isSectionMemberOfGroup(const Elf_Shdr *shdr) const {
return (shdr->sh_flags & llvm::ELF::SHF_GROUP);
}
/// 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 {
@ -661,8 +680,12 @@ 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;
// group sections have a mapping of the section header to the
// signature/section.
llvm::DenseMap<const Elf_Shdr *, std::pair<StringRef, StringRef>>
groupSections;
// Contains a list of comdat sections for a group.
llvm::DenseMap<const Elf_Shdr *, std::vector<StringRef>> comdatSections;
for (auto &i : _sectionSymbols) {
const Elf_Shdr *section = i.first;
std::vector<Elf_Sym_Iter> &symbols = i.second;
@ -683,11 +706,49 @@ template <class ELFT> std::error_code ELFFile<ELFT>::createAtoms() {
bool addAtoms = true;
// A section of type SHT_GROUP defines a grouping of sections. The name of a
// symbol from one of the containing object's symbol tables provides a
// signature
// for the section group. The section header of the SHT_GROUP section
// specifies
// the identifying symbol entry, as described : the sh_link member contains
// the section header index of the symbol table section that contains the
// entry.
// The sh_info member contains the symbol table index of the identifying
// entry.
// The sh_flags member of the section header contains 0. The name of the
// section
// (sh_name) is not specified.
if (isGroupSection(section)) {
const Elf_Word *groupMembers =
reinterpret_cast<const Elf_Word *>(sectionContents->data());
const long count = (section->sh_size) / sizeof(Elf_Word);
for (int i = 1; i < count; i++) {
const Elf_Shdr *sHdr = _objFile->getSection(groupMembers[i]);
ErrorOr<StringRef> sectionName = _objFile->getSectionName(sHdr);
if (std::error_code ec = sectionName.getError())
return ec;
comdatSections[section].push_back(*sectionName);
}
const Elf_Sym *symbol = _objFile->getSymbol(section->sh_info);
const Elf_Shdr *symtab = _objFile->getSection(section->sh_link);
ErrorOr<StringRef> symbolName = _objFile->getSymbolName(symtab, symbol);
if (std::error_code ec = symbolName.getError())
return ec;
groupSections.insert(
std::make_pair(section, std::make_pair(*symbolName, *sectionName)));
continue;
}
if (isGnuLinkOnceSection(*sectionName)) {
groupSections.insert(std::make_pair(section, *sectionName));
groupSections.insert(
std::make_pair(section, std::make_pair(*sectionName, *sectionName)));
addAtoms = false;
}
if (isSectionMemberOfGroup(section))
addAtoms = false;
if (handleSectionWithNoSymbols(section, symbols)) {
ELFDefinedAtom<ELFT> *newAtom =
createSectionAtom(section, *sectionName, *sectionContents);
@ -812,9 +873,13 @@ template <class ELFT> std::error_code ELFFile<ELFT>::createAtoms() {
// Iterate over all the group sections to create parent atoms pointing to
// group-child atoms.
for (auto &sect : groupSections) {
StringRef signature = sect.second;
StringRef signature = sect.second.first;
StringRef groupSectionName = sect.second.second;
if (isGnuLinkOnceSection(signature))
handleGnuLinkOnceSection(signature, atomsForSection, sect.first);
else if (isGroupSection(sect.first))
handleSectionGroup(signature, groupSectionName, atomsForSection,
comdatSections, sect.first);
}
updateReferences();
@ -847,6 +912,36 @@ std::error_code ELFFile<ELFT>::handleGnuLinkOnceSection(
return std::error_code();
}
template <class ELFT>
std::error_code ELFFile<ELFT>::handleSectionGroup(
StringRef signature, StringRef groupSectionName,
llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
llvm::DenseMap<const Elf_Shdr *, std::vector<StringRef>> &comdatSections,
const Elf_Shdr *shdr) {
unsigned int referenceStart = _references.size();
std::vector<ELFReference<ELFT> *> refs;
auto sectionNamesInGroup = comdatSections[shdr];
for (auto sectionName : sectionNamesInGroup) {
for (auto ha : atomsForSection[sectionName]) {
_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[sectionName].clear();
}
// Create a gnu linkonce atom.
auto sectionGroupAtom = handleDefinedSymbol(
signature, groupSectionName, nullptr, shdr, ArrayRef<uint8_t>(),
referenceStart, _references.size(), _references);
(*sectionGroupAtom)->setOrdinal(++_ordinal);
_definedAtoms._atoms.push_back(*sectionGroupAtom);
for (auto reference : refs)
(*sectionGroupAtom)->addReference(reference);
return std::error_code();
}
template <class ELFT> std::error_code ELFFile<ELFT>::createAtomsFromContext() {
if (!_useWrap)
return std::error_code();
@ -1052,18 +1147,27 @@ void ELFFile<ELFT>::createEdge(ELFDefinedAtom<ELFT> *from,
template <class ELFT>
bool ELFFile<ELFT>::redirectReferenceUsingUndefAtom(
const Elf_Sym *sourceSymbol, const Elf_Sym *targetSymbol) const {
auto groupChild = _groupChild.find(targetSymbol);
auto groupChildTarget = _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())
// using a undefined atom. Its also not needed if the source and target are
// from the same section.
if ((groupChildTarget == _groupChild.end()) ||
(sourceSymbol->st_shndx == targetSymbol->st_shndx))
return false;
if (sourceSymbol->st_shndx != targetSymbol->st_shndx) {
return true;
}
auto groupChildSource = _groupChild.find(sourceSymbol);
return false;
// If the source symbol is not in a group, use a undefined symbol too.
if (groupChildSource == _groupChild.end())
return true;
// If the source and child are from the same group, we dont need the
// relocation to go through a undefined symbol.
if (groupChildSource->second.second == groupChildTarget->second.second)
return false;
return true;
}
} // end namespace elf

View File

@ -35,7 +35,7 @@ public:
/// \brief Does this section have an output segment.
virtual bool hasOutputSegment() { return true; }
const lld::AtomLayout &appendAtom(const Atom *atom) {
const lld::AtomLayout *appendAtom(const Atom *atom) {
const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
DefinedAtom::Alignment atomAlign = definedAtom->alignment();
uint64_t alignment = 1u << atomAlign.powerOf2;
@ -44,7 +44,7 @@ public:
// std::max doesn't support uint64_t
if (this->_alignment < alignment)
this->_alignment = alignment;
return *(this->_atoms.back());
return (this->_atoms.back());
}
}; // SDataSection

View File

@ -40,7 +40,7 @@ public:
/// \brief Append the Atom to the layout and create appropriate sections.
/// \returns A reference to the atom layout or an error. The atom layout will
/// be updated as linking progresses.
virtual ErrorOr<const lld::AtomLayout &> addAtom(const Atom *atom) = 0;
virtual ErrorOr<const lld::AtomLayout *> addAtom(const Atom *atom) = 0;
/// find the Atom in the current layout
virtual const AtomLayout *findAtomLayoutByName(StringRef name) const = 0;
/// associates a section to a segment

View File

@ -49,7 +49,7 @@ public:
return ia == _posMap.end() && ib != _posMap.end();
}
const lld::AtomLayout &appendAtom(const Atom *atom) override {
const lld::AtomLayout *appendAtom(const Atom *atom) override {
const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
for (const auto &r : *da) {
@ -105,8 +105,8 @@ public:
return it != _pltLayoutMap.end() ? it->second : nullptr;
}
const lld::AtomLayout &appendAtom(const Atom *atom) override {
const auto &layout = AtomSection<ELFType>::appendAtom(atom);
const lld::AtomLayout *appendAtom(const Atom *atom) override {
const auto *layout = AtomSection<ELFType>::appendAtom(atom);
const DefinedAtom *da = cast<DefinedAtom>(atom);
@ -115,7 +115,7 @@ public:
continue;
assert(r->kindArch() == Reference::KindArch::Mips);
if (r->kindValue() == LLD_R_MIPS_STO_PLT) {
_pltLayoutMap[r->target()] = &layout;
_pltLayoutMap[r->target()] = layout;
break;
}
}

View File

@ -162,6 +162,13 @@ template <class ELFT>
void OutputELFWriter<ELFT>::buildChunks(const File &file) {
ScopedTask task(getDefaultDomain(), "buildChunks");
for (const DefinedAtom *definedAtom : file.defined()) {
DefinedAtom::ContentType contentType = definedAtom->contentType();
// Dont add COMDAT group atoms and GNU linkonce atoms, as they are used for
// symbol resolution.
// TODO: handle partial linking.
if (contentType == DefinedAtom::typeGroupComdat ||
contentType == DefinedAtom::typeGnuLinkOnce)
continue;
_layout.addAtom(definedAtom);
}
for (const AbsoluteAtom *absoluteAtom : file.absolute())

View File

@ -218,7 +218,7 @@ public:
// \brief Append an atom to a Section. The atom gets pushed into a vector
// contains the atom, the atom file offset, the atom virtual address
// the atom file offset is aligned appropriately as set by the Reader
virtual const lld::AtomLayout &appendAtom(const Atom *atom);
virtual const lld::AtomLayout *appendAtom(const Atom *atom);
/// \brief Set the virtual address of each Atom in the Section. This
/// routine gets called after the linker fixes up the virtual address
@ -318,7 +318,7 @@ uint64_t AtomSection<ELFT>::alignOffset(uint64_t offset,
// contains the atom, the atom file offset, the atom virtual address
// the atom file offset is aligned appropriately as set by the Reader
template <class ELFT>
const lld::AtomLayout &AtomSection<ELFT>::appendAtom(const Atom *atom) {
const lld::AtomLayout *AtomSection<ELFT>::appendAtom(const Atom *atom) {
const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
DefinedAtom::Alignment atomAlign = definedAtom->alignment();
@ -361,9 +361,6 @@ const lld::AtomLayout &AtomSection<ELFT>::appendAtom(const Atom *atom) {
_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.");
@ -373,7 +370,9 @@ const lld::AtomLayout &AtomSection<ELFT>::appendAtom(const Atom *atom) {
if (this->_alignment < alignment)
this->_alignment = alignment;
return *_atoms.back();
if (_atoms.size())
return _atoms.back();
return nullptr;
}
/// \brief convert the segment type to a String for diagnostics

View File

@ -0,0 +1,153 @@
# Checks that the linker picks the first group in the output file when the file
# have some members dont appear in the first group.
# 1a.s
# ------
#
# .section .text,"axG",%progbits,foo_group,comdat
# .weak foo
#foo:
# .word 0
# 1b.s
# -----
# .section .text,"axG",%progbits,foo_group,comdat
# .global foo
# .global bar
#foo:
# .word 0
#bar:
#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
#RUN: lld -flavor gnu -target x86_64 %t.group1a.o %t.group1b.o \
#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
#RUN: lld -flavor gnu -target x86_64 %t.group1a.o %t.group1b.o \
#RUN: --noinhibit-exec -o %t2.out
#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
#CHECKGROUP: - name: foo
#CHECKGROUP: scope: global
#CHECKGROUP: merge: as-weak
#CHECKGROUP: section-name: .text
#CHECKGROUP: - name: foo_group
#CHECKGROUP: scope: global
#CHECKGROUP: type: group-comdat
#CHECKGROUP: section-choice: custom-required
#CHECKGROUP: section-name: .group
#CHECKGROUP: permissions: ---
#CHECKGROUP: references:
#CHECKGROUP: - kind: group-child
#CHECKGROUP: offset: 0
#CHECKGROUP: target: foo
#CHECKGROUPSECTIONS: Section {
#CHECKGROUPSECTIONS: Name: .text
#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
#CHECKGROUPSECTIONS: Flags [ (0x6)
#CHECKGROUPSECTIONS: SHF_ALLOC (0x2)
#CHECKGROUPSECTIONS: SHF_EXECINSTR (0x4)
#CHECKGROUPSECTIONS: ]
#CHECKGROUPSECTIONS: Size: 2
#CHECKGROUPSECTIONS: AddressAlignment: 1
#CHECKGROUPSECTIONS: }
#CHECKSYMBOLS: Name: foo
#CHECKSYMBOLS: Type: Function
#CHECKSYMBOLS: Section: .text
#CHECKSYMBOLS-NOT: Name: bar
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: foo_group
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .text
- 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: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '0000'
Symbols:
Local:
- Name: foo_group
Section: .group
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
Weak:
- Name: foo
Section: .text
...
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: foo_group
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .text
- 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: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '0000'
Symbols:
Local:
- Name: foo_group
Section: .group
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
Global:
- Name: bar
Section: .text
Value: 0x0000000000000002
- Name: foo
Section: .text
...

View File

@ -0,0 +1,146 @@
# Checks that the linker picks the first group in the output file when the file
# have some members dont appear in the first group.
# 1a.s
# ------
# .section .text,"axG",%progbits,foo_group,comdat
# .weak foo
#foo:
# .word 0
# 1b.s
# -----
# .section .text,"axG",%progbits,foo_group,comdat
# .global bar
#bar:
#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
#RUN: lld -flavor gnu -target x86_64 %t.group1a.o %t.group1b.o \
#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
#RUN: lld -flavor gnu -target x86_64 %t.group1a.o %t.group1b.o \
#RUN: --noinhibit-exec -o %t2.out
#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
#CHECKGROUP: - name: foo
#CHECKGROUP: scope: global
#CHECKGROUP: merge: as-weak
#CHECKGROUP: section-name: .text
#CHECKGROUP: - name: foo_group
#CHECKGROUP: scope: global
#CHECKGROUP: type: group-comdat
#CHECKGROUP: section-choice: custom-required
#CHECKGROUP: section-name: .group
#CHECKGROUP: permissions: ---
#CHECKGROUP: references:
#CHECKGROUP: - kind: group-child
#CHECKGROUP: offset: 0
#CHECKGROUP: target: foo
#CHECKGROUPSECTIONS: Section {
#CHECKGROUPSECTIONS: Name: .text
#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
#CHECKGROUPSECTIONS: Flags [ (0x6)
#CHECKGROUPSECTIONS: SHF_ALLOC (0x2)
#CHECKGROUPSECTIONS: SHF_EXECINSTR (0x4)
#CHECKGROUPSECTIONS: ]
#CHECKGROUPSECTIONS: Size: 2
#CHECKGROUPSECTIONS: AddressAlignment: 1
#CHECKGROUPSECTIONS: }
#CHECKSYMBOLS: Name: foo
#CHECKSYMBOLS: Type: Function
#CHECKSYMBOLS: Section: .text
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: foo_group
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .text
- 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: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '0000'
Symbols:
Local:
- Name: foo_group
Section: .group
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
Weak:
- Name: foo
Section: .text
...
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: foo_group
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .text
- 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: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: ''
Symbols:
Local:
- Name: foo_group
Section: .group
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
Global:
- Name: bar
Section: .text
...

View File

@ -0,0 +1,158 @@
# Tests that linker throws an error for an undefined symbol in the section
# group, which is the same as the signature in the next input file.
# comdat1.s
# ------------
# .section .foo,"axG",@progbits,g1,comdat
# .word g1
#comdat2.s
#-----------
# .global g1
# .section .bar,"axG",@progbits,g1,comdat
#g2:
# nop
# .section .car,"axG",@progbits,g1,comdat
#g3:
# nop
#
#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
#RUN: lld -flavor gnu -target x86_64 %t.group1a.o %t.group1b.o \
#RUN: --noinhibit-exec -o %t2.out 2>&1 | FileCheck %s
#CHECK: Undefined symbol: {{.*}} g1
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- SectionOrType: .rela.foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '0000'
- Name: .rela.foo
Type: SHT_RELA
Flags: [ SHF_GROUP ]
Link: .symtab
AddressAlign: 0x0000000000000008
Info: .foo
Relocations:
- Offset: 0x0000000000000000
Symbol: g1
Type: R_X86_64_16
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
- Name: .group
Type: STT_SECTION
Section: .group
Global:
- Name: g1
...
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .bar
- SectionOrType: .car
- 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: .bar
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '90'
- Name: .car
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '90'
Symbols:
Local:
- Name: g2
Section: .bar
- Name: g3
Section: .car
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .bar
Type: STT_SECTION
Section: .bar
- Name: .car
Type: STT_SECTION
Section: .car
- Name: .group
Type: STT_SECTION
Section: .group
Global:
- Name: g1
Section: .group
...

View File

@ -0,0 +1,144 @@
# Tests that linker throws an error for an undefined symbol in the section
# group.
#
#comdata.s
#------------
# .section .foo,"axG",@progbits,g1,comdat
# .word g1
#
#comdatb.s
#------------
# .global g1
# .section .foo,"axG",@progbits,g1,comdat
#g1:
# nop
#
#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.group1a.o
#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.group1b.o
#RUN: lld -flavor gnu -target x86_64 %t.group1a.o %t.group1b.o \
#RUN: --noinhibit-exec -o %t2.out 2>&1 | FileCheck %s
#CHECK: Undefined symbol: {{.*}} g1
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- SectionOrType: .rela.foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '0000'
- Name: .rela.foo
Type: SHT_RELA
Flags: [ SHF_GROUP ]
Link: .symtab
AddressAlign: 0x0000000000000008
Info: .foo
Relocations:
- Offset: 0x0000000000000000
Symbol: g1
Type: R_X86_64_16
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
- Name: .group
Type: STT_SECTION
Section: .group
Global:
- Name: g1
...
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '90'
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
- Name: .group
Type: STT_SECTION
Section: .group
Global:
- Name: g1
Section: .foo
...

View File

@ -0,0 +1,253 @@
# This tests that comdat weak symbol can be overridden by a global symbol.
# comdat1.s
#------------------------
# .weak g1
# .section .foo,"axG",@progbits,g1,comdat
#g1:
# nop
# .global g2
#g2:
# nop
#!
#
#comdat2.s << \!
#-----------------
# .global g1
# .section .foo,"axG",@progbits,g1,comdat
#g1:
# nop
# .global g2
#g2:
# nop
#
#cat > g1.c << \!
#int g1() {
# return 0;
#}
#
#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.comdat1.o
#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.comdat2.o
#RUN: yaml2obj -format=elf -docnum 3 %s -o %t.g1.o
#RUN: lld -flavor gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
#RUN: %t.g1.o --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
#RUN: lld -flavor gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
#RUN: %t.g1.o --noinhibit-exec -o %t2.out
#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
#CHECKGROUP: - name: g2
#CHECKGROUP: content: [ 90 ]
#CHECKGROUP: section-choice: custom-required
#CHECKGROUP: section-name: .foo
#CHECKGROUP: - name: g1
#CHECKGROUP: scope: global
#CHECKGROUP: content: [ 55, 48, 89, E5, 31, C0, 5D, C3 ]
#CHECKGROUP: alignment: 2^4
#CHECKGROUP: section-name: .text
#CHECKGROUPSECTIONS: Name: .text
#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
#CHECKGROUPSECTIONS: Flags [
#CHECKGROUPSECTIONS: SHF_ALLOC
#CHECKGROUPSECTIONS: SHF_EXECINSTR
#CHECKGROUPSECTIONS: ]
#CHECKGROUPSECTIONS: Size: 8
#CHECKGROUPSECTIONS: Name: .foo
#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
#CHECKGROUPSECTIONS: Flags [
#CHECKGROUPSECTIONS: SHF_ALLOC
#CHECKGROUPSECTIONS: SHF_EXECINSTR
#CHECKGROUPSECTIONS: ]
#CHECKGROUPSECTIONS: Size: 2
#CHECKSYMBOLS: Name: g2
#CHECKSYMBOLS: Section: .foo
#CHECKSYMBOLS: Name: g1
#CHECKSYMBOLS: Section: .text
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '9090'
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
Global:
- Name: g2
Section: .foo
Value: 0x0000000000000001
Weak:
- Name: g1
Section: .foo
...
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '9090'
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
Global:
- Name: g1
Section: .foo
- Name: g2
Section: .foo
Value: 0x0000000000000001
...
---
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: 0x0000000000000010
Content: 554889E531C05DC3
- 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: .comment
Type: SHT_PROGBITS
Flags: [ SHF_MERGE, SHF_STRINGS ]
AddressAlign: 0x0000000000000001
Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232393535372920286C6C766D2F7472756E6B203232393536332900
- Name: .note.GNU-stack
Type: SHT_PROGBITS
AddressAlign: 0x0000000000000001
Content: ''
- Name: .eh_frame
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
AddressAlign: 0x0000000000000008
Content: 1400000000000000037A5200017810011B0C0708900100001C0000001C000000000000000800000000410E108602430D0600000000000000
- Name: .rela.eh_frame
Type: SHT_RELA
Link: .symtab
AddressAlign: 0x0000000000000008
Info: .eh_frame
Relocations:
- Offset: 0x0000000000000020
Symbol: .text
Type: R_X86_64_PC32
Symbols:
Local:
- Name: g1.c
Type: STT_FILE
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .comment
Type: STT_SECTION
Section: .comment
- Name: .note.GNU-stack
Type: STT_SECTION
Section: .note.GNU-stack
- Name: .eh_frame
Type: STT_SECTION
Section: .eh_frame
Global:
- Name: g1
Type: STT_FUNC
Section: .text
Size: 0x0000000000000008
...

View File

@ -0,0 +1,239 @@
# This tests that comdat undef symbol is overridden by a global symbol.
# comdat1.s
#------------------------
# .global g1
# .section .foo,"axG",@progbits,g1,comdat
#g1:
# .word 5
#
#comdat2.s << \!
#-----------------
# .global g1
# .section .foo,"axG",@progbits,g1,comdat
#g1:
# nop
#
#g1.c
#-----------
#extern int g1;
#int fn() { return g1;}
#
#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.comdat1.o
#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.comdat2.o
#RUN: yaml2obj -format=elf -docnum 3 %s -o %t.g1.o
#RUN: lld -flavor gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
#RUN: %t.g1.o --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
#RUN: lld -flavor gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
#RUN: %t.g1.o --noinhibit-exec -o %t2.out
#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
#CHECKGROUP: - name: g1
#CHECKGROUP: scope: global
#CHECKGROUP: content: [ 05, 00 ]
#CHECKGROUP: section-name: .foo
#CHECKGROUPSECTIONS: Section {
#CHECKGROUPSECTIONS: Name: .foo
#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
#CHECKGROUPSECTIONS: Flags [
#CHECKGROUPSECTIONS: SHF_ALLOC
#CHECKGROUPSECTIONS: SHF_EXECINSTR
#CHECKGROUPSECTIONS: ]
#CHECKGROUPSECTIONS: Size: 2
#CHECKGROUPSECTIONS: }
#CHECKSYMBOLS: Name: g1
#CHECKSYMBOLS: Section: .foo
#CHECKSYMBOLS: Name: fn
#CHECKSYMBOLS: Section: .text
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '0500'
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
Global:
- Name: g1
Section: .foo
...
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '90'
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
Global:
- Name: g1
Section: .foo
...
---
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: 0x0000000000000010
Content: 554889E58B0425000000005DC3
- Name: .rela.text
Type: SHT_RELA
Link: .symtab
AddressAlign: 0x0000000000000008
Info: .text
Relocations:
- Offset: 0x0000000000000007
Symbol: g1
Type: R_X86_64_32S
- 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: .comment
Type: SHT_PROGBITS
Flags: [ SHF_MERGE, SHF_STRINGS ]
AddressAlign: 0x0000000000000001
Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232393535372920286C6C766D2F7472756E6B203232393536332900
- Name: .note.GNU-stack
Type: SHT_PROGBITS
AddressAlign: 0x0000000000000001
Content: ''
- Name: .eh_frame
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC ]
AddressAlign: 0x0000000000000008
Content: 1400000000000000037A5200017810011B0C0708900100001C0000001C000000000000000D00000000410E108602430D0600000000000000
- Name: .rela.eh_frame
Type: SHT_RELA
Link: .symtab
AddressAlign: 0x0000000000000008
Info: .eh_frame
Relocations:
- Offset: 0x0000000000000020
Symbol: .text
Type: R_X86_64_PC32
Symbols:
Local:
- Name: global-g1.c
Type: STT_FILE
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .comment
Type: STT_SECTION
Section: .comment
- Name: .note.GNU-stack
Type: STT_SECTION
Section: .note.GNU-stack
- Name: .eh_frame
Type: STT_SECTION
Section: .eh_frame
Global:
- Name: fn
Type: STT_FUNC
Section: .text
Size: 0x000000000000000D
- Name: g1
...

View File

@ -0,0 +1,222 @@
# This tests that comdat undef symbol is overridden by a global symbol.
# comdat1.s
#------------------------
# .section .foo,"axG",@progbits,g1,comdat
# word g1
#
#comdat2.s << \!
#-----------------
# .global g1
# .section .foo,"axG",@progbits,g1,comdat
#g1:
# nop
#
#global-g1.c
#-----------
#int g1=10;
#
#RUN: yaml2obj -format=elf -docnum 1 %s -o %t.comdat1.o
#RUN: yaml2obj -format=elf -docnum 2 %s -o %t.comdat2.o
#RUN: yaml2obj -format=elf -docnum 3 %s -o %t.g1.o
#RUN: lld -flavor gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
#RUN: %t.g1.o --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
#RUN: lld -flavor gnu -target x86_64 %t.comdat1.o %t.comdat2.o \
#RUN: %t.g1.o --noinhibit-exec -o %t2.out
#RUN: FileCheck %s -check-prefix=CHECKGROUP < %t2.out.yaml
#RUN: llvm-readobj -sections %t2.out | FileCheck %s -check-prefix=CHECKGROUPSECTIONS
#RUN: llvm-readobj -symbols %t2.out | FileCheck %s -check-prefix=CHECKSYMBOLS
#CHECKGROUP: - name: g1
#CHECKGROUP: scope: global
#CHECKGROUP: content: [ 0A, 00, 00, 00 ]
#CHECKGROUP: section-name: .data
#CHECKGROUPSECTIONS: Name: .foo
#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
#CHECKGROUPSECTIONS: Flags [
#CHECKGROUPSECTIONS: SHF_ALLOC
#CHECKGROUPSECTIONS: SHF_EXECINSTR
#CHECKGROUPSECTIONS: ]
#CHECKGROUPSECTIONS: Size: 2
#CHECKGROUPSECTIONS: Name: .data
#CHECKGROUPSECTIONS: Type: SHT_PROGBITS
#CHECKGROUPSECTIONS: Flags [
#CHECKGROUPSECTIONS: SHF_ALLOC
#CHECKGROUPSECTIONS: SHF_WRITE
#CHECKGROUPSECTIONS: ]
#CHECKGROUPSECTIONS: Size: 4
#CHECKSYMBOLS: Name: g1
#CHECKSYMBOLS: Section: .data
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- SectionOrType: .rela.foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '0000'
- Name: .rela.foo
Type: SHT_RELA
Flags: [ SHF_GROUP ]
Link: .symtab
AddressAlign: 0x0000000000000008
Info: .foo
Relocations:
- Offset: 0x0000000000000000
Symbol: g1
Type: R_X86_64_16
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
Global:
- Name: g1
...
---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_X86_64
Sections:
- Name: .group
Type: SHT_GROUP
Link: .symtab
AddressAlign: 0x0000000000000004
Info: g1
Members:
- SectionOrType: GRP_COMDAT
- SectionOrType: .foo
- 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: .foo
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ]
AddressAlign: 0x0000000000000001
Content: '90'
Symbols:
Local:
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .foo
Type: STT_SECTION
Section: .foo
Global:
- Name: g1
Section: .foo
...
---
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: 0A000000
- Name: .bss
Type: SHT_NOBITS
Flags: [ SHF_WRITE, SHF_ALLOC ]
AddressAlign: 0x0000000000000004
Content: ''
- Name: .comment
Type: SHT_PROGBITS
Flags: [ SHF_MERGE, SHF_STRINGS ]
AddressAlign: 0x0000000000000001
Content: 00636C616E672076657273696F6E20332E372E3020287472756E6B203232393535372920286C6C766D2F7472756E6B203232393536332900
- Name: .note.GNU-stack
Type: SHT_PROGBITS
AddressAlign: 0x0000000000000001
Content: ''
Symbols:
Local:
- Name: global-g1.c
Type: STT_FILE
- Name: .text
Type: STT_SECTION
Section: .text
- Name: .data
Type: STT_SECTION
Section: .data
- Name: .bss
Type: STT_SECTION
Section: .bss
- Name: .comment
Type: STT_SECTION
Section: .comment
- Name: .note.GNU-stack
Type: STT_SECTION
Section: .note.GNU-stack
Global:
- Name: g1
Type: STT_OBJECT
Section: .data
Size: 0x0000000000000004
...