forked from OSchip/llvm-project
Allow the GNU gold-style nonstandard SHT_GROUP section.
The ELF standard defines that the SHT_GROUP section as follows: - its sh_link has the symbol index, and - the symbol name is used to uniquify section groups. Object files created by GNU gold does not seem to comply with the standard. They have this additional rule: - if the symbol has no name and a STT_SECTION symbol, a section name is used instead of a symbol name. If we don't do anything for this, the linker fails with a mysterious error message if input files are generated by gas. It is unfortunate but I think we need to support it. Differential Revision: https://reviews.llvm.org/D34064 llvm-svn: 305218
This commit is contained in:
parent
8c31c2a546
commit
f9f69548a9
|
@ -205,13 +205,27 @@ template <class ELFT>
|
|||
StringRef
|
||||
elf::ObjectFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
|
||||
const Elf_Shdr &Sec) {
|
||||
// Group signatures are stored as symbol names in object files.
|
||||
// sh_info contains a symbol index, so we fetch a symbol and read its name.
|
||||
if (this->Symbols.empty())
|
||||
this->initSymtab(
|
||||
Sections,
|
||||
check(object::getSection<ELFT>(Sections, Sec.sh_link), toString(this)));
|
||||
|
||||
const Elf_Sym *Sym = check(
|
||||
object::getSymbol<ELFT>(this->Symbols, Sec.sh_info), toString(this));
|
||||
return check(Sym->getName(this->StringTable), toString(this));
|
||||
StringRef Signature = check(Sym->getName(this->StringTable), toString(this));
|
||||
|
||||
// As a special case, if a symbol is a section symbol and has no name,
|
||||
// we use a section name as a signature.
|
||||
//
|
||||
// Such SHT_GROUP sections are invalid from the perspective of the ELF
|
||||
// standard, but GNU gold 1.14 (the neweset version as of July 2017) or
|
||||
// older produce such sections as outputs for the -r option, so we need
|
||||
// a bug-compatibility.
|
||||
if (Signature.empty() && Sym->getType() == STT_SECTION)
|
||||
return getSectionName(Sec);
|
||||
return Signature;
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -287,8 +301,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
|
|||
check(this->getObj().sections(), toString(this));
|
||||
uint64_t Size = ObjSections.size();
|
||||
this->Sections.resize(Size);
|
||||
|
||||
StringRef SectionStringTable =
|
||||
this->SectionStringTable =
|
||||
check(Obj.getSectionStringTable(ObjSections), toString(this));
|
||||
|
||||
for (size_t I = 0, E = ObjSections.size(); I < E; I++) {
|
||||
|
@ -318,7 +331,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
|
|||
// object files, we want to pass through basically everything.
|
||||
if (IsNew) {
|
||||
if (Config->Relocatable)
|
||||
this->Sections[I] = createInputSection(Sec, SectionStringTable);
|
||||
this->Sections[I] = createInputSection(Sec);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -342,7 +355,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
|
|||
case SHT_NULL:
|
||||
break;
|
||||
default:
|
||||
this->Sections[I] = createInputSection(Sec, SectionStringTable);
|
||||
this->Sections[I] = createInputSection(Sec);
|
||||
}
|
||||
|
||||
// .ARM.exidx sections have a reverse dependency on the InputSection they
|
||||
|
@ -386,10 +399,8 @@ InputSectionBase *toRegularSection(MergeInputSection *Sec) {
|
|||
|
||||
template <class ELFT>
|
||||
InputSectionBase *
|
||||
elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
|
||||
StringRef SectionStringTable) {
|
||||
StringRef Name = check(
|
||||
this->getObj().getSectionName(&Sec, SectionStringTable), toString(this));
|
||||
elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
|
||||
StringRef Name = getSectionName(Sec);
|
||||
|
||||
switch (Sec.sh_type) {
|
||||
case SHT_ARM_ATTRIBUTES:
|
||||
|
@ -521,6 +532,12 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
|
|||
return make<InputSection>(this, &Sec, Name);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
StringRef elf::ObjectFile<ELFT>::getSectionName(const Elf_Shdr &Sec) {
|
||||
return check(this->getObj().getSectionName(&Sec, SectionStringTable),
|
||||
toString(this));
|
||||
}
|
||||
|
||||
template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() {
|
||||
SymbolBodies.reserve(this->Symbols.size());
|
||||
for (const Elf_Sym &Sym : this->Symbols)
|
||||
|
|
|
@ -194,8 +194,8 @@ private:
|
|||
void initializeSymbols();
|
||||
void initializeDwarfLine();
|
||||
InputSectionBase *getRelocTarget(const Elf_Shdr &Sec);
|
||||
InputSectionBase *createInputSection(const Elf_Shdr &Sec,
|
||||
StringRef SectionStringTable);
|
||||
InputSectionBase *createInputSection(const Elf_Shdr &Sec);
|
||||
StringRef getSectionName(const Elf_Shdr &Sec);
|
||||
|
||||
bool shouldMerge(const Elf_Shdr &Sec);
|
||||
SymbolBody *createSymbolBody(const Elf_Sym *Sym);
|
||||
|
@ -203,6 +203,9 @@ private:
|
|||
// List of all symbols referenced or defined by this file.
|
||||
std::vector<SymbolBody *> SymbolBodies;
|
||||
|
||||
// .shstrtab contents.
|
||||
StringRef SectionStringTable;
|
||||
|
||||
// Debugging information to retrieve source file and line for error
|
||||
// reporting. Linker may find reasonable number of errors in a
|
||||
// single object file, so we cache debugging information in order to
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
|||
# sht-group-gold-r.elf is produced by
|
||||
#
|
||||
# llvm-mc -filetype=obj -triple=x86_64-pc-linux sht-group-gold-r.s -o sht-group-gold-r.o
|
||||
# ld.gold -o sht-group-gold-r.elf -r sht-group-gold-r.o
|
||||
|
||||
.global foo, bar
|
||||
|
||||
.section .text.foo,"aG",@progbits,group_foo,comdat
|
||||
foo:
|
||||
nop
|
||||
|
||||
.section .text.bar,"aG",@progbits,group_bar,comdat
|
||||
bar:
|
||||
nop
|
|
@ -0,0 +1,17 @@
|
|||
# GNU gold 1.14 (the newest version as of July 2017) seems to create
|
||||
# non-standard-compliant SHT_GROUP sections when the -r option is given.
|
||||
#
|
||||
# Such SHT_GROUP sections use section names as their signatures
|
||||
# instead of symbols pointed by sh_link field. Since it is prevalent,
|
||||
# we accept such nonstandard sections.
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
|
||||
# RUN: ld.lld %p/Inputs/sht-group-gold-r.elf %t.o -o %t.exe
|
||||
# RUN: llvm-objdump -t %t.exe | FileCheck %s
|
||||
|
||||
# CHECK: .text 00000000 bar
|
||||
# CHECK: .text 00000000 foo
|
||||
|
||||
.globl _start
|
||||
_start:
|
||||
ret
|
Loading…
Reference in New Issue