Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -484,11 +484,35 @@ Opt.Commands = std::move(Commands); } +// Imagine .boo : { *(.foo) *(.bar) } script. Both foo and bar may have +// relocation sections .rela.foo and .rela.bar for example. Most tools does not +// allow to have multiple REL[A] sections for output section. Hence we should +// combine these relocation sections into single output. +static void addRelocationSections(ArrayRef Arr, + OutputSectionFactory &Factory) { + // Each regular output section may have single relocation section referenced + // by. This mapping allows to find relocation section by output section. + DenseMap RelocationSections; + for (InputSection *Sec : Arr) { + OutputSection *Out = Sec->getRelocatedSection()->getOutputSection(); + OutputSection *&RelocationSec = RelocationSections[Out]; + StringRef Name = getOutputSectionName(Sec->Name); + Factory.addInputSec(Sec, Name, RelocationSec); + } +} + // Add sections that didn't match any sections command. void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { + std::vector RelocSections; for (InputSectionBase *S : InputSections) { if (!S->Live || S->Parent) continue; + if (!isa(S) && + (S->Type == SHT_REL || S->Type == SHT_RELA)) { + RelocSections.push_back(cast(S)); + continue; + } + StringRef Name = getOutputSectionName(S->Name); auto I = std::find_if( Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) { @@ -512,6 +536,8 @@ Cmd->Commands.push_back(ISD); } } + + addRelocationSections(RelocSections, Factory); } uint64_t LinkerScript::advance(uint64_t Size, unsigned Align) { Index: test/ELF/linkerscript/emit-relocs-multiple.s =================================================================== --- test/ELF/linkerscript/emit-relocs-multiple.s +++ test/ELF/linkerscript/emit-relocs-multiple.s @@ -0,0 +1,21 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { .foo : { *(.foo) *(.bar) } }" > %t.script +# RUN: ld.lld --emit-relocs --script %t.script %t.o -o %t1 +# RUN: llvm-readobj -s -r %t1 | FileCheck %s + +# CHECK-NOT: .rela.bar +# CHECK: Relocations [ +# CHECK-NEXT: Section {{.*}} .rela.foo { +# CHECK-NEXT: 0x1 R_X86_64_32 .foo 0x0 +# CHECK-NEXT: 0x6 R_X86_64_32 .foo 0x5 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.section .foo,"ax",@progbits +aaa: + movl $aaa, %edx + +.section .bar,"ax",@progbits +bbb: + movl $bbb, %edx