Skip to content

Commit 08d6a3f

Browse files
committed
Create only one section symbol per section.
Unfortunately some consumers of our .o files produced with -r expect only one section symbol per section. That is true of at least of go's own linker. Combining them is a somewhat convoluted process. We have to create a symbol for every section since we don't know which ones will be needed. The relocation sections also have to be written first to handle the Elf_Rel addend. I did consider a completely different approach: We could remove the -r special case of relocation sections when reading. We would instead have a copyRelocs function that is used instead of scanRelocs. It would create a DynamicReloc for each relocation and a RelocationSection for each input relocation section. A complication of such change is that DynamicReloc would have to take a section index and a input section instead of a symbol since with -emit-relocs some DynamicReloc would hold relocations referring to the dynamic symbol table and other to the static symbol table. That would be a pretty big change, and if we do it it is probably better to do it as a refactoring. llvm-svn: 294816
1 parent f11ab87 commit 08d6a3f

File tree

7 files changed

+115
-21
lines changed

7 files changed

+115
-21
lines changed

lld/ELF/InputSection.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,22 @@ void InputSection<ELFT>::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
236236
if (Config->Rela)
237237
P->r_addend = getAddend<ELFT>(Rel);
238238

239+
if (Body.Type == STT_SECTION) {
240+
// We combine multiple section symbols into only one per
241+
// section. This means we have to update the addend. That is
242+
// trivial for Elf_Rela, but for Elf_Rel we have to write to the
243+
// section data. We do that by adding to the Relocation vector.
244+
if (Config->Rela) {
245+
P->r_addend += Body.getVA<ELFT>() -
246+
cast<DefinedRegular<ELFT>>(Body).Section->OutSec->Addr;
247+
} else if (Config->Relocatable) {
248+
const uint8_t *BufLoc = RelocatedSection->Data.begin() + Rel.r_offset;
249+
uint64_t Implicit = Target->getImplicitAddend(BufLoc, Type);
250+
RelocatedSection->Relocations.push_back(
251+
{R_ABS, Type, Rel.r_offset, Implicit, &Body});
252+
}
253+
}
254+
239255
// Output section VA is zero for -r, so r_offset is an offset within the
240256
// section, but for --emit-relocs it is an virtual address.
241257
P->r_offset = RelocatedSection->OutSec->Addr +

lld/ELF/SyntheticSections.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,8 +1127,16 @@ template <class ELFT> void SymbolTableSection<ELFT>::addLocal(SymbolBody *B) {
11271127

11281128
template <class ELFT>
11291129
size_t SymbolTableSection<ELFT>::getSymbolIndex(SymbolBody *Body) {
1130-
auto I = llvm::find_if(
1131-
Symbols, [&](const SymbolTableEntry &E) { return E.Symbol == Body; });
1130+
auto I = llvm::find_if(Symbols, [&](const SymbolTableEntry &E) {
1131+
if (E.Symbol == Body)
1132+
return true;
1133+
// This is used for -r, so we have to handle multiple section
1134+
// symbols being combined.
1135+
if (Body->Type == STT_SECTION && E.Symbol->Type == STT_SECTION)
1136+
return cast<DefinedRegular<ELFT>>(Body)->Section->OutSec ==
1137+
cast<DefinedRegular<ELFT>>(E.Symbol)->Section->OutSec;
1138+
return false;
1139+
});
11321140
if (I == Symbols.end())
11331141
return 0;
11341142
return I - Symbols.begin() + 1;

lld/ELF/Writer.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ template <class ELFT> class Writer {
5151
private:
5252
void createSyntheticSections();
5353
void copyLocalSymbols();
54+
void addSectionSymbols();
5455
void addReservedSymbols();
5556
void addInputSec(InputSectionBase<ELFT> *S);
5657
void createSections();
@@ -228,6 +229,9 @@ template <class ELFT> void Writer<ELFT>::run() {
228229
if (Config->Discard != DiscardPolicy::All)
229230
copyLocalSymbols();
230231

232+
if (Config->copyRelocs())
233+
addSectionSymbols();
234+
231235
// Now that we have a complete set of output sections. This function
232236
// completes section contents. For example, we need to add strings
233237
// to the string table, and add entries to .got and .plt.
@@ -446,13 +450,9 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
446450
template <class ELFT>
447451
static bool shouldKeepInSymtab(InputSectionBase<ELFT> *Sec, StringRef SymName,
448452
const SymbolBody &B) {
449-
if (B.isFile())
453+
if (B.isFile() || B.isSection())
450454
return false;
451455

452-
// We keep sections in symtab for relocatable output and --emit-reloc.
453-
if (B.isSection())
454-
return Config->copyRelocs();
455-
456456
// If sym references a section in a discarded group, don't keep it.
457457
if (Sec == &InputSection<ELFT>::Discarded)
458458
return false;
@@ -518,6 +518,27 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
518518
}
519519
}
520520

521+
template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
522+
// Create one STT_SECTION symbol for each output section we might
523+
// have a relocation with.
524+
for (OutputSectionBase *Sec : OutputSections) {
525+
InputSectionData *First = nullptr;
526+
Sec->forEachInputSection([&](InputSectionData *D) {
527+
if (!First)
528+
First = D;
529+
});
530+
auto *IS = dyn_cast_or_null<InputSection<ELFT>>(First);
531+
if (!IS || isa<SyntheticSection<ELFT>>(IS) || IS->Type == SHT_REL ||
532+
IS->Type == SHT_RELA)
533+
continue;
534+
auto *B = new (BAlloc)
535+
DefinedRegular<ELFT>("", /*IsLocal=*/true, /*StOther*/ 0, STT_SECTION,
536+
/*Value*/ 0, /*Size*/ 0, IS, nullptr);
537+
538+
In<ELFT>::SymTab->addLocal(B);
539+
}
540+
}
541+
521542
// PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that
522543
// we would like to make sure appear is a specific order to maximize their
523544
// coverage by a single signed 16-bit offset from the TOC base pointer.
@@ -1782,8 +1803,17 @@ template <class ELFT> void Writer<ELFT>::writeSections() {
17821803

17831804
OutputSectionBase *EhFrameHdr =
17841805
In<ELFT>::EhFrameHdr ? In<ELFT>::EhFrameHdr->OutSec : nullptr;
1806+
1807+
// In -r or -emit-relocs mode, write the relocation sections first as in
1808+
// ELf_Rel targets we might find out that we need to modify the relocated
1809+
// section while doing it.
1810+
for (OutputSectionBase *Sec : OutputSections)
1811+
if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
1812+
Sec->writeTo(Buf + Sec->Offset);
1813+
17851814
for (OutputSectionBase *Sec : OutputSections)
1786-
if (Sec != Out<ELFT>::Opd && Sec != EhFrameHdr)
1815+
if (Sec != Out<ELFT>::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
1816+
Sec->Type != SHT_RELA)
17871817
Sec->writeTo(Buf + Sec->Offset);
17881818

17891819
// The .eh_frame_hdr depends on .eh_frame section contents, therefore

lld/test/ELF/emit-relocs.s

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# CHECK-NEXT: Section ({{.*}}) .rela.text {
1616
# CHECK-NEXT: 0x201002 R_X86_64_32 .text 0x1
1717
# CHECK-NEXT: 0x201007 R_X86_64_PLT32 fn 0xFFFFFFFFFFFFFFFC
18-
# CHECK-NEXT: 0x20100E R_X86_64_32 .text 0x1
18+
# CHECK-NEXT: 0x20100E R_X86_64_32 .text 0xD
1919
# CHECK-NEXT: 0x201013 R_X86_64_PLT32 fn2 0xFFFFFFFFFFFFFFFC
2020
# CHECK-NEXT: }
2121
# CHECK-NEXT: ]
@@ -57,15 +57,6 @@
5757
# CHECK-NEXT: Section: .text
5858
# CHECK-NEXT: }
5959
# CHECK-NEXT: Symbol {
60-
# CHECK-NEXT: Name:
61-
# CHECK-NEXT: Value: 0x20100C
62-
# CHECK-NEXT: Size: 0
63-
# CHECK-NEXT: Binding: Local
64-
# CHECK-NEXT: Type: Section
65-
# CHECK-NEXT: Other: 0
66-
# CHECK-NEXT: Section: .text
67-
# CHECK-NEXT: }
68-
# CHECK-NEXT: Symbol {
6960
# CHECK-NEXT: Name: fn
7061
# CHECK-NEXT: Value: 0x201000
7162
# CHECK-NEXT: Size: 0

lld/test/ELF/mips-sto-pic-flag.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
# CHECK-NEXT: Other: 0
2020
# CHECK-NEXT: Section: .text
2121
# CHECK-NEXT: }
22-
# CHECK-NEXT: Symbol {
23-
# CHECK-NEXT: Name: foo1a
22+
# CHECK: Symbol {
23+
# CHECK: Name: foo1a
2424
# CHECK-NEXT: Value:
2525
# CHECK-NEXT: Size:
2626
# CHECK-NEXT: Binding: Global

lld/test/ELF/relocatable-bss.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# CHECK-NEXT: Version:
2121
# CHECK-NEXT: Entry:
2222
# CHECK-NEXT: ProgramHeaderOffset:
23-
# CHECK-NEXT: SectionHeaderOffset: 0xA8
23+
# CHECK-NEXT: SectionHeaderOffset: 0xD8
2424
# CHECK-NEXT: Flags [
2525
# CHECK-NEXT: ]
2626
# CHECK-NEXT: HeaderSize:
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
2+
# RUN: ld.lld -r -o %t %t.o %t.o
3+
# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELA %s
4+
5+
# RELA: Relocations [
6+
# RELA-NEXT: Section ({{.*}}) .rela.data {
7+
# RELA-NEXT: 0x0 R_X86_64_32 .text 0x1
8+
# RELA-NEXT: 0x4 R_X86_64_32 .text 0x5
9+
# RELA-NEXT: }
10+
# RELA-NEXT: ]
11+
12+
13+
# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
14+
# RUN: ld.lld -r -o %t %t.o %t.o
15+
# RUN: llvm-readobj -r -s -section-data %t | FileCheck --check-prefix=REL %s
16+
17+
18+
# REL: Section {
19+
# REL: Index:
20+
# REL: Name: .data
21+
# REL-NEXT: Type: SHT_PROGBITS
22+
# REL-NEXT: Flags [
23+
# REL-NEXT: SHF_ALLOC
24+
# REL-NEXT: SHF_WRITE
25+
# REL-NEXT: ]
26+
# REL-NEXT: Address:
27+
# REL-NEXT: Offset:
28+
# REL-NEXT: Size:
29+
# REL-NEXT: Link:
30+
# REL-NEXT: Info:
31+
# REL-NEXT: AddressAlignment:
32+
# REL-NEXT: EntrySize:
33+
# REL-NEXT: SectionData (
34+
# REL-NEXT: 0000: 01000000 05000000 |
35+
# REL-NEXT: )
36+
# REL-NEXT: }
37+
38+
39+
# REL: Relocations [
40+
# REL-NEXT: Section ({{.*}}) .rel.data {
41+
# REL-NEXT: 0x0 R_386_32 .text 0x0
42+
# REL-NEXT: 0x4 R_386_32 .text 0x0
43+
# REL-NEXT: }
44+
# REL-NEXT: ]
45+
46+
47+
.long 42
48+
.data
49+
.long .text + 1

0 commit comments

Comments
 (0)