[ELF] - Do not merge relocation sections by name when using --emit-relocs.

Previously we would merge relocation sections by name.
That did not work in some cases, like testcase shows.

Patch implements logic to merge relocation sections if their target
sections were merged into the same output section.

Differential revision: https://reviews.llvm.org/D33824

llvm-svn: 304886
This commit is contained in:
George Rimar 2017-06-07 09:20:35 +00:00
parent 8445858a93
commit 990c9cb2bf
5 changed files with 40 additions and 13 deletions

View File

@ -283,6 +283,20 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
return; return;
} }
// Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have
// relocation sections .rela.foo and .rela.bar for example. Most tools do
// not allow multiple REL[A] sections for output section. Hence we
// should combine these relocation sections into single output.
// We skip synthetic sections because it can be .rela.dyn/.rela.plt or any
// other REL[A] sections created by linker itself.
if (!isa<SyntheticSection>(IS) &&
(IS->Type == SHT_REL || IS->Type == SHT_RELA)) {
auto *Sec = cast<InputSection>(IS);
OutputSection *Out = Sec->getRelocatedSection()->getOutputSection();
addInputSec(IS, OutsecName, Out->RelocationSection);
return;
}
SectionKey Key = createKey(IS, OutsecName); SectionKey Key = createKey(IS, OutsecName);
OutputSection *&Sec = Map[Key]; OutputSection *&Sec = Map[Key];
return addInputSec(IS, OutsecName, Sec); return addInputSec(IS, OutsecName, Sec);

View File

@ -67,6 +67,11 @@ public:
// formula: Off = Off_first + VA - VA_first. // formula: Off = Off_first + VA - VA_first.
OutputSection *FirstInPtLoad = nullptr; OutputSection *FirstInPtLoad = nullptr;
// Pointer to a relocation section for this section. Usually nullptr because
// we consume relocations, but if --emit-relocs is specified (which is rare),
// it may have a non-null value.
OutputSection *RelocationSection = nullptr;
// The following fields correspond to Elf_Shdr members. // The following fields correspond to Elf_Shdr members.
uint64_t Size = 0; uint64_t Size = 0;
uint64_t Offset = 0; uint64_t Offset = 0;

View File

@ -101,18 +101,6 @@ StringRef elf::getOutputSectionName(StringRef Name) {
if (Config->Relocatable) if (Config->Relocatable)
return Name; return Name;
// If -emit-relocs is given (which is rare), we need to copy
// relocation sections to the output. If input section .foo is
// output as .bar, we want to rename .rel.foo .rel.bar as well.
if (Config->EmitRelocs) {
for (StringRef V : {".rel.", ".rela."}) {
if (Name.startswith(V)) {
StringRef Inner = getOutputSectionName(Name.substr(V.size() - 1));
return Saver.save(V.drop_back() + Inner);
}
}
}
for (StringRef V : for (StringRef V :
{".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",

View File

@ -8,7 +8,7 @@
# CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0 # CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0
# CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0 # CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0
# CHECK-NEXT: } # CHECK-NEXT: }
# CHECK-NEXT: Section ({{.*}}) .rela.data { # CHECK-NEXT: Section ({{.*}}) .rela.data.foo {
# CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0 # CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x0
# CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0 # CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x0
# CHECK-NEXT: } # CHECK-NEXT: }

View File

@ -0,0 +1,20 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
# RUN: echo "SECTIONS { .zed : { *(.foo) *(.bar) } }" > %t.script
# RUN: ld.lld --emit-relocs --script %t.script %t.o -o %t1
# RUN: llvm-readobj -r %t1 | FileCheck %s
# CHECK: Relocations [
# CHECK-NEXT: Section {{.*}} .rela.foo {
# CHECK-NEXT: 0x1 R_X86_64_32 .zed 0x0
# CHECK-NEXT: 0x6 R_X86_64_32 .zed 0x5
# CHECK-NEXT: }
# CHECK-NEXT: ]
.section .foo,"ax",@progbits
aaa:
movl $aaa, %edx
.section .bar,"ax",@progbits
bbb:
movl $bbb, %edx