summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2017-06-12 18:46:33 +0000
committerRui Ueyama <ruiu@google.com>2017-06-12 18:46:33 +0000
commitf9f69548a9cc71136655eb9724969ed17e831a2d (patch)
treeacebbbe952419ec4779b6115e513563858e57e6b
parent8c31c2a5467f904ea2a7b1fd39dd7b3c1b17f097 (diff)
downloadbcm5719-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.cpp35
-rw-r--r--lld/ELF/InputFiles.h7
-rw-r--r--lld/test/ELF/Inputs/sht-group-gold-r.elfbin0 -> 880 bytes
-rw-r--r--lld/test/ELF/Inputs/sht-group-gold-r.s14
-rw-r--r--lld/test/ELF/sht-group-gold-r.test17
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
new file mode 100644
index 00000000000..d2309c92217
--- /dev/null
+++ b/lld/test/ELF/Inputs/sht-group-gold-r.elf
Binary files differ
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
OpenPOWER on IntegriCloud