Skip to content

Commit f9f6954

Browse files
committedJun 12, 2017
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
1 parent 8c31c2a commit f9f6954

File tree

5 files changed

+62
-11
lines changed

5 files changed

+62
-11
lines changed
 

‎lld/ELF/InputFiles.cpp

+26-9
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,27 @@ template <class ELFT>
205205
StringRef
206206
elf::ObjectFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
207207
const Elf_Shdr &Sec) {
208+
// Group signatures are stored as symbol names in object files.
209+
// sh_info contains a symbol index, so we fetch a symbol and read its name.
208210
if (this->Symbols.empty())
209211
this->initSymtab(
210212
Sections,
211213
check(object::getSection<ELFT>(Sections, Sec.sh_link), toString(this)));
214+
212215
const Elf_Sym *Sym = check(
213216
object::getSymbol<ELFT>(this->Symbols, Sec.sh_info), toString(this));
214-
return check(Sym->getName(this->StringTable), toString(this));
217+
StringRef Signature = check(Sym->getName(this->StringTable), toString(this));
218+
219+
// As a special case, if a symbol is a section symbol and has no name,
220+
// we use a section name as a signature.
221+
//
222+
// Such SHT_GROUP sections are invalid from the perspective of the ELF
223+
// standard, but GNU gold 1.14 (the neweset version as of July 2017) or
224+
// older produce such sections as outputs for the -r option, so we need
225+
// a bug-compatibility.
226+
if (Signature.empty() && Sym->getType() == STT_SECTION)
227+
return getSectionName(Sec);
228+
return Signature;
215229
}
216230

217231
template <class ELFT>
@@ -287,8 +301,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
287301
check(this->getObj().sections(), toString(this));
288302
uint64_t Size = ObjSections.size();
289303
this->Sections.resize(Size);
290-
291-
StringRef SectionStringTable =
304+
this->SectionStringTable =
292305
check(Obj.getSectionStringTable(ObjSections), toString(this));
293306

294307
for (size_t I = 0, E = ObjSections.size(); I < E; I++) {
@@ -318,7 +331,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
318331
// object files, we want to pass through basically everything.
319332
if (IsNew) {
320333
if (Config->Relocatable)
321-
this->Sections[I] = createInputSection(Sec, SectionStringTable);
334+
this->Sections[I] = createInputSection(Sec);
322335
continue;
323336
}
324337

@@ -342,7 +355,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
342355
case SHT_NULL:
343356
break;
344357
default:
345-
this->Sections[I] = createInputSection(Sec, SectionStringTable);
358+
this->Sections[I] = createInputSection(Sec);
346359
}
347360

348361
// .ARM.exidx sections have a reverse dependency on the InputSection they
@@ -386,10 +399,8 @@ InputSectionBase *toRegularSection(MergeInputSection *Sec) {
386399

387400
template <class ELFT>
388401
InputSectionBase *
389-
elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
390-
StringRef SectionStringTable) {
391-
StringRef Name = check(
392-
this->getObj().getSectionName(&Sec, SectionStringTable), toString(this));
402+
elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
403+
StringRef Name = getSectionName(Sec);
393404

394405
switch (Sec.sh_type) {
395406
case SHT_ARM_ATTRIBUTES:
@@ -521,6 +532,12 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
521532
return make<InputSection>(this, &Sec, Name);
522533
}
523534

535+
template <class ELFT>
536+
StringRef elf::ObjectFile<ELFT>::getSectionName(const Elf_Shdr &Sec) {
537+
return check(this->getObj().getSectionName(&Sec, SectionStringTable),
538+
toString(this));
539+
}
540+
524541
template <class ELFT> void elf::ObjectFile<ELFT>::initializeSymbols() {
525542
SymbolBodies.reserve(this->Symbols.size());
526543
for (const Elf_Sym &Sym : this->Symbols)

‎lld/ELF/InputFiles.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -194,15 +194,18 @@ template <class ELFT> class ObjectFile : public ELFFileBase<ELFT> {
194194
void initializeSymbols();
195195
void initializeDwarfLine();
196196
InputSectionBase *getRelocTarget(const Elf_Shdr &Sec);
197-
InputSectionBase *createInputSection(const Elf_Shdr &Sec,
198-
StringRef SectionStringTable);
197+
InputSectionBase *createInputSection(const Elf_Shdr &Sec);
198+
StringRef getSectionName(const Elf_Shdr &Sec);
199199

200200
bool shouldMerge(const Elf_Shdr &Sec);
201201
SymbolBody *createSymbolBody(const Elf_Sym *Sym);
202202

203203
// List of all symbols referenced or defined by this file.
204204
std::vector<SymbolBody *> SymbolBodies;
205205

206+
// .shstrtab contents.
207+
StringRef SectionStringTable;
208+
206209
// Debugging information to retrieve source file and line for error
207210
// reporting. Linker may find reasonable number of errors in a
208211
// single object file, so we cache debugging information in order to
880 Bytes
Binary file not shown.
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# sht-group-gold-r.elf is produced by
2+
#
3+
# llvm-mc -filetype=obj -triple=x86_64-pc-linux sht-group-gold-r.s -o sht-group-gold-r.o
4+
# ld.gold -o sht-group-gold-r.elf -r sht-group-gold-r.o
5+
6+
.global foo, bar
7+
8+
.section .text.foo,"aG",@progbits,group_foo,comdat
9+
foo:
10+
nop
11+
12+
.section .text.bar,"aG",@progbits,group_bar,comdat
13+
bar:
14+
nop

‎lld/test/ELF/sht-group-gold-r.test

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# GNU gold 1.14 (the newest version as of July 2017) seems to create
2+
# non-standard-compliant SHT_GROUP sections when the -r option is given.
3+
#
4+
# Such SHT_GROUP sections use section names as their signatures
5+
# instead of symbols pointed by sh_link field. Since it is prevalent,
6+
# we accept such nonstandard sections.
7+
8+
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
9+
# RUN: ld.lld %p/Inputs/sht-group-gold-r.elf %t.o -o %t.exe
10+
# RUN: llvm-objdump -t %t.exe | FileCheck %s
11+
12+
# CHECK: .text 00000000 bar
13+
# CHECK: .text 00000000 foo
14+
15+
.globl _start
16+
_start:
17+
ret

0 commit comments

Comments
 (0)