diff options
author | Rui Ueyama <ruiu@google.com> | 2017-06-12 18:46:33 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2017-06-12 18:46:33 +0000 |
commit | f9f69548a9cc71136655eb9724969ed17e831a2d (patch) | |
tree | acebbbe952419ec4779b6115e513563858e57e6b | |
parent | 8c31c2a5467f904ea2a7b1fd39dd7b3c1b17f097 (diff) | |
download | bcm5719-llvm-f9f69548a9cc71136655eb9724969ed17e831a2d.tar.gz bcm5719-llvm-f9f69548a9cc71136655eb9724969ed17e831a2d.zip |
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
-rw-r--r-- | lld/ELF/InputFiles.cpp | 35 | ||||
-rw-r--r-- | lld/ELF/InputFiles.h | 7 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/sht-group-gold-r.elf | bin | 0 -> 880 bytes | |||
-rw-r--r-- | lld/test/ELF/Inputs/sht-group-gold-r.s | 14 | ||||
-rw-r--r-- | lld/test/ELF/sht-group-gold-r.test | 17 |
5 files changed, 62 insertions, 11 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 524246ed1d1..902593b63a7 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -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) diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 6daf2664985..2eec7844483 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -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 diff --git a/lld/test/ELF/Inputs/sht-group-gold-r.elf b/lld/test/ELF/Inputs/sht-group-gold-r.elf Binary files differnew file mode 100644 index 00000000000..d2309c92217 --- /dev/null +++ b/lld/test/ELF/Inputs/sht-group-gold-r.elf diff --git a/lld/test/ELF/Inputs/sht-group-gold-r.s b/lld/test/ELF/Inputs/sht-group-gold-r.s new file mode 100644 index 00000000000..aca262ddaa4 --- /dev/null +++ b/lld/test/ELF/Inputs/sht-group-gold-r.s @@ -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 diff --git a/lld/test/ELF/sht-group-gold-r.test b/lld/test/ELF/sht-group-gold-r.test new file mode 100644 index 00000000000..3a3889eabd8 --- /dev/null +++ b/lld/test/ELF/sht-group-gold-r.test @@ -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 |