Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1488,12 +1488,16 @@ this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } +// Place R_*_RELATIVE first (required by DT_REL[A]COUNT). The second key is the +// symbol index - the locality optimizes dynamic loader performance. The third +// key is r_offset - relative relocations ordered by r_offset facilitate +// debugging. It also breaks ties for non-relative relocations of the same +// symbol. static bool compRelocations(const DynamicReloc &A, const DynamicReloc &B) { - bool AIsRel = A.Type == Target->RelativeRel; - bool BIsRel = B.Type == Target->RelativeRel; - if (AIsRel != BIsRel) - return AIsRel; - return A.getSymIndex() < B.getSymIndex(); + return std::make_tuple(A.Type != Target->RelativeRel, A.getSymIndex(), + A.getOffset()) < + std::make_tuple(B.Type != Target->RelativeRel, B.getSymIndex(), + B.getOffset()); } template void RelocationSection::writeTo(uint8_t *Buf) { Index: test/ELF/combreloc.s =================================================================== --- /dev/null +++ test/ELF/combreloc.s @@ -0,0 +1,47 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o +# RUN: echo 'mov aaa@gotpcrel(%rip), %rax' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o + +# RUN: ld.lld -shared %t.o %t1.o -o %t.so +# RUN: llvm-readobj -r --dynamic-table %t.so | FileCheck %s +# RUN: ld.lld -shared %t.o %t1.o -o %t.so -z combreloc +# RUN: llvm-readobj -r --dynamic-table %t.so | FileCheck %s + +# -z combreloc is the default: sort relocations by (!IsRelative, SymIndex, r_offset). +# and emit DT_RELACOUNT to indicate the number of relative relocations. + +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.dyn { +# CHECK-NEXT: 0x3020 R_X86_64_RELATIVE - 0x3028 +# CHECK-NEXT: 0x20B0 R_X86_64_GLOB_DAT aaa 0x0 +# CHECK-NEXT: 0x3000 R_X86_64_64 aaa 0x0 +# CHECK-NEXT: 0x3018 R_X86_64_64 aaa 0x0 +# CHECK-NEXT: 0x3010 R_X86_64_64 bbb 0x0 +# CHECK-NEXT: 0x3008 R_X86_64_64 ccc 0x0 +# CHECK-NEXT: } +# CHECK: DynamicSection [ +# CHECK: RELACOUNT 1 + +# RUN: ld.lld -z nocombreloc -shared %t.o %t1.o -o %t.so +# RUN: llvm-readobj -r --dynamic-table %t.so | FileCheck --check-prefix=NOCOMB %s + +# NOCOMB: Relocations [ +# NOCOMB-NEXT: Section ({{.*}}) .rela.dyn { +# NOCOMB-NEXT: 0x3000 R_X86_64_64 aaa 0x0 +# NOCOMB-NEXT: 0x3008 R_X86_64_64 ccc 0x0 +# NOCOMB-NEXT: 0x3010 R_X86_64_64 bbb 0x0 +# NOCOMB-NEXT: 0x3018 R_X86_64_64 aaa 0x0 +# NOCOMB-NEXT: 0x3020 R_X86_64_RELATIVE - 0x3028 +# NOCOMB-NEXT: 0x20A0 R_X86_64_GLOB_DAT aaa 0x0 +# NOCOMB-NEXT: } +# NOCOMB: DynamicSection [ +# NOCOMB-NOT: RELACOUNT + +.data + .quad aaa + .quad ccc + .quad bbb + .quad aaa + .quad relative +relative: Index: test/ELF/combrelocs.s =================================================================== --- test/ELF/combrelocs.s +++ /dev/null @@ -1,95 +0,0 @@ -# REQUIRES: x86 - -# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o -# RUN: ld.lld -shared %t.o -o %t.out -# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | FileCheck %s - -# RUN: ld.lld -shared %t.o -o %t.out -z combreloc -# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | FileCheck %s - -# CHECK: Relocations [ -# CHECK-NEXT: Section ({{.*}}) .rela.dyn { -# CHECK-NEXT: Relocation { -# CHECK-NEXT: Offset: 0x2000 -# CHECK-NEXT: Type: R_X86_64_64 -# CHECK-NEXT: Symbol: aaa (1) -# CHECK-NEXT: Addend: 0x0 -# CHECK-NEXT: } -# CHECK-NEXT: Relocation { -# CHECK-NEXT: Offset: 0x2018 -# CHECK-NEXT: Type: R_X86_64_64 -# CHECK-NEXT: Symbol: aaa (1) -# CHECK-NEXT: Addend: 0x0 -# CHECK-NEXT: } -# CHECK-NEXT: Relocation { -# CHECK-NEXT: Offset: 0x2010 -# CHECK-NEXT: Type: R_X86_64_64 -# CHECK-NEXT: Symbol: bbb (2) -# CHECK-NEXT: Addend: 0x0 -# CHECK-NEXT: } -# CHECK-NEXT: Relocation { -# CHECK-NEXT: Offset: 0x2008 -# CHECK-NEXT: Type: R_X86_64_64 -# CHECK-NEXT: Symbol: ccc (3) -# CHECK-NEXT: Addend: 0x0 -# CHECK-NEXT: } -# CHECK-NEXT: Relocation { -# CHECK-NEXT: Offset: 0x2020 -# CHECK-NEXT: Type: R_X86_64_64 -# CHECK-NEXT: Symbol: ddd (4) -# CHECK-NEXT: Addend: 0x0 -# CHECK-NEXT: } -# CHECK-NEXT: } -# CHECK-NEXT: ] -# CHECK: DynamicSection [ -# CHECK-NEXT: Tag -# CHECK-NOT: RELACOUNT - -# RUN: ld.lld -z nocombreloc -shared %t.o -o %t.out -# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | \ -# RUN: FileCheck --check-prefix=NOCOMB %s - -# NOCOMB: Relocations [ -# NOCOMB-NEXT: Section ({{.*}}) .rela.dyn { -# NOCOMB-NEXT: Relocation { -# NOCOMB-NEXT: Offset: 0x2000 -# NOCOMB-NEXT: Type: R_X86_64_64 -# NOCOMB-NEXT: Symbol: aaa (1) -# NOCOMB-NEXT: Addend: 0x0 -# NOCOMB-NEXT: } -# NOCOMB-NEXT: Relocation { -# NOCOMB-NEXT: Offset: 0x2008 -# NOCOMB-NEXT: Type: R_X86_64_64 -# NOCOMB-NEXT: Symbol: ccc (3) -# NOCOMB-NEXT: Addend: 0x0 -# NOCOMB-NEXT: } -# NOCOMB-NEXT: Relocation { -# NOCOMB-NEXT: Offset: 0x2010 -# NOCOMB-NEXT: Type: R_X86_64_64 -# NOCOMB-NEXT: Symbol: bbb (2) -# NOCOMB-NEXT: Addend: 0x0 -# NOCOMB-NEXT: } -# NOCOMB-NEXT: Relocation { -# NOCOMB-NEXT: Offset: 0x2018 -# NOCOMB-NEXT: Type: R_X86_64_64 -# NOCOMB-NEXT: Symbol: aaa (1) -# NOCOMB-NEXT: Addend: 0x0 -# NOCOMB-NEXT: } -# NOCOMB-NEXT: Relocation { -# NOCOMB-NEXT: Offset: 0x2020 -# NOCOMB-NEXT: Type: R_X86_64_64 -# NOCOMB-NEXT: Symbol: ddd (4) -# NOCOMB-NEXT: Addend: 0x0 -# NOCOMB-NEXT: } -# NOCOMB-NEXT: } -# NOCOMB-NEXT: ] -# NOCOMB: DynamicSection [ -# NOCOMB-NEXT: Tag -# NOCOMB-NOT: RELACOUNT - -.data - .quad aaa - .quad ccc - .quad bbb - .quad aaa - .quad ddd Index: test/ELF/i386-got-and-copy.s =================================================================== --- test/ELF/i386-got-and-copy.s +++ test/ELF/i386-got-and-copy.s @@ -14,8 +14,8 @@ # CHECK: Relocations [ # CHECK-NEXT: Section (4) .rel.dyn { -# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_COPY foo # CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_GLOB_DAT foo +# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_COPY foo # CHECK-NEXT: } # CHECK-NEXT: ]