Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1488,17 +1488,15 @@ this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); } -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(); -} - template void RelocationSection::writeTo(uint8_t *Buf) { + // Sort symbol index then by r_offset. Because we only emit R_*_RELATIVE as + // dynamic relocations with symbol index 0, this essentially places + // R_*_RELATIVE first (required by DT_REL[A]COUNT). if (Sort) - llvm::stable_sort(Relocs, compRelocations); + llvm::stable_sort(Relocs, [](const DynamicReloc &A, const DynamicReloc &B) { + return std::make_tuple(A.getSymIndex(), A.getOffset()) < + std::make_tuple(B.getSymIndex(), B.getOffset()); + }); for (const DynamicReloc &Rel : Relocs) { encodeDynamicReloc(reinterpret_cast(Buf), Rel); Index: test/ELF/combreloc.s =================================================================== --- test/ELF/combreloc.s +++ test/ELF/combreloc.s @@ -0,0 +1,48 @@ +# 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 (SymIndex, r_offset), and +# emit DT_RELACOUNT (except on MIPS) 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 +++ test/ELF/combrelocs.s @@ -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: ] Index: test/ELF/mips-mgot.s =================================================================== --- test/ELF/mips-mgot.s +++ test/ELF/mips-mgot.s @@ -34,14 +34,14 @@ # GOT-NEXT: 0x70024 R_MIPS_REL32 - 0x0 # GOT-NEXT: 0x70028 R_MIPS_REL32 - 0x0 # GOT-NEXT: 0x7002C R_MIPS_REL32 - 0x0 -# GOT-NEXT: 0x70030 R_MIPS_REL32 foo0 0x0 -# GOT-NEXT: 0x70034 R_MIPS_REL32 foo2 0x0 # GOT-NEXT: 0x70044 R_MIPS_TLS_DTPMOD32 - 0x0 # GOT-NEXT: 0x70010 R_MIPS_TLS_TPREL32 tls0 0x0 # GOT-NEXT: 0x70038 R_MIPS_TLS_TPREL32 tls0 0x0 # GOT-NEXT: 0x7003C R_MIPS_TLS_DTPMOD32 tls0 0x0 # GOT-NEXT: 0x70040 R_MIPS_TLS_DTPREL32 tls0 0x0 # GOT-NEXT: 0x70014 R_MIPS_TLS_TPREL32 tls1 0x0 +# GOT-NEXT: 0x70030 R_MIPS_REL32 foo0 0x0 +# GOT-NEXT: 0x70034 R_MIPS_REL32 foo2 0x0 # GOT-NEXT: } # GOT-NEXT: ]