Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -88,6 +88,7 @@ bool Verbose; bool VersionScript = false; bool WarnCommon; + bool ZCombreloc; bool ZExecStack; bool ZNodelete; bool ZNow; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -352,6 +352,7 @@ if (Config->LtoJobs == 0) error("number of threads must be > 0"); + Config->ZCombreloc = !hasZOption(Args, "nocombreloc"); Config->ZExecStack = hasZOption(Args, "execstack"); Config->ZNodelete = hasZOption(Args, "nodelete"); Config->ZNow = hasZOption(Args, "now"); Index: lld/trunk/ELF/OutputSections.h =================================================================== --- lld/trunk/ELF/OutputSections.h +++ lld/trunk/ELF/OutputSections.h @@ -274,7 +274,7 @@ typedef typename ELFT::uint uintX_t; public: - RelocationSection(StringRef Name); + RelocationSection(StringRef Name, bool Sort); void addReloc(const DynamicReloc &Reloc); unsigned getRelocOffset(); void finalize() override; @@ -284,6 +284,7 @@ bool Static = false; private: + bool Sort; std::vector> Relocs; }; Index: lld/trunk/ELF/OutputSections.cpp =================================================================== --- lld/trunk/ELF/OutputSections.cpp +++ lld/trunk/ELF/OutputSections.cpp @@ -301,9 +301,10 @@ } template -RelocationSection::RelocationSection(StringRef Name) +RelocationSection::RelocationSection(StringRef Name, bool Sort) : OutputSectionBase(Name, Config->Rela ? SHT_RELA : SHT_REL, - SHF_ALLOC) { + SHF_ALLOC), + Sort(Sort) { this->Header.sh_entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); this->Header.sh_addralign = sizeof(uintX_t); } @@ -313,7 +314,13 @@ Relocs.push_back(Reloc); } +template +static bool compRelocations(const RelTy &A, const RelTy &B) { + return A.getSymbol(Config->Mips64EL) < B.getSymbol(Config->Mips64EL); +} + template void RelocationSection::writeTo(uint8_t *Buf) { + uint8_t *BufBegin = Buf; for (const DynamicReloc &Rel : Relocs) { auto *P = reinterpret_cast(Buf); Buf += Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); @@ -325,6 +332,16 @@ uint32_t SymIdx = (!Rel.UseSymVA && Sym) ? Sym->DynsymIndex : 0; P->setSymbolAndType(SymIdx, Rel.Type, Config->Mips64EL); } + + if (Sort) { + if (Config->Rela) + std::stable_sort((Elf_Rela *)BufBegin, + (Elf_Rela *)BufBegin + Relocs.size(), + compRelocations); + else + std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(), + compRelocations); + } } template unsigned RelocationSection::getRelocOffset() { Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -129,7 +129,8 @@ GotSection Got; InterpSection Interp; PltSection Plt; - RelocationSection RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn"); + RelocationSection RelaDyn(Config->Rela ? ".rela.dyn" : ".rel.dyn", + Config->ZCombreloc); StringTableSection DynStrTab(".dynstr", true); StringTableSection ShStrTab(".shstrtab", false); SymbolTableSection DynSymTab(*Symtab, DynStrTab); @@ -165,7 +166,7 @@ if (Target->UseLazyBinding) { StringRef S = Config->Rela ? ".rela.plt" : ".rel.plt"; GotPlt.reset(new GotPltSection); - RelaPlt.reset(new RelocationSection(S)); + RelaPlt.reset(new RelocationSection(S, false /*Sort*/)); } if (!Config->StripAll) { StrTab.reset(new StringTableSection(".strtab", false)); Index: lld/trunk/test/ELF/aarch64-abs64-dyn.s =================================================================== --- lld/trunk/test/ELF/aarch64-abs64-dyn.s +++ lld/trunk/test/ELF/aarch64-abs64-dyn.s @@ -17,8 +17,8 @@ // RUN: llvm-readobj -symbols -dyn-relocations %t.so | FileCheck %s // CHECK: Dynamic Relocations { -// CHECK-NEXT: {{.*}} R_AARCH64_ABS64 foo 0x0 // CHECK-NEXT: {{.*}} R_AARCH64_RELATIVE - [[BAR_ADDR:.*]] +// CHECK-NEXT: {{.*}} R_AARCH64_ABS64 foo 0x0 // CHECK-NEXT: } // CHECK: Symbols [ Index: lld/trunk/test/ELF/aarch64-tls-ie.s =================================================================== --- lld/trunk/test/ELF/aarch64-tls-ie.s +++ lld/trunk/test/ELF/aarch64-tls-ie.s @@ -24,8 +24,8 @@ #RELOC-NEXT: } #RELOC: Relocations [ #RELOC-NEXT: Section ({{.*}}) .rela.dyn { -#RELOC-NEXT: 0x120B0 R_AARCH64_TLS_TPREL64 foo 0x0 #RELOC-NEXT: 0x120B8 R_AARCH64_TLS_TPREL64 bar 0x0 +#RELOC-NEXT: 0x120B0 R_AARCH64_TLS_TPREL64 foo 0x0 #RELOC-NEXT: } #RELOC-NEXT:] Index: lld/trunk/test/ELF/combrelocs.s =================================================================== --- lld/trunk/test/ELF/combrelocs.s +++ lld/trunk/test/ELF/combrelocs.s @@ -0,0 +1,92 @@ +# 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 + +# 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: lld/trunk/test/ELF/gotpcrelx.s =================================================================== --- lld/trunk/test/ELF/gotpcrelx.s +++ lld/trunk/test/ELF/gotpcrelx.s @@ -24,7 +24,7 @@ // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.dyn { -// CHECK-NEXT: 0x2090 R_X86_64_GLOB_DAT foo 0x0 // CHECK-NEXT: 0x2098 R_X86_64_GLOB_DAT bar 0x0 +// CHECK-NEXT: 0x2090 R_X86_64_GLOB_DAT foo 0x0 // CHECK-NEXT: } // CHECK-NEXT: ] Index: lld/trunk/test/ELF/i386-tls-ie-shared.s =================================================================== --- lld/trunk/test/ELF/i386-tls-ie-shared.s +++ lld/trunk/test/ELF/i386-tls-ie-shared.s @@ -24,16 +24,16 @@ // GOTRELSHARED: Relocations [ // GOTRELSHARED-NEXT: Section ({{.*}}) .rel.dyn { // GOTRELSHARED-NEXT: 0x2002 R_386_RELATIVE - 0x0 -// GOTRELSHARED-NEXT: 0x1050 R_386_TLS_TPOFF tlslocal0 0x0 // GOTRELSHARED-NEXT: 0x200A R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x2013 R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x201C R_386_RELATIVE - 0x0 -// GOTRELSHARED-NEXT: 0x1054 R_386_TLS_TPOFF tlslocal1 0x0 // GOTRELSHARED-NEXT: 0x2024 R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x202D R_386_RELATIVE - 0x0 // GOTRELSHARED-NEXT: 0x2036 R_386_RELATIVE - 0x0 -// GOTRELSHARED-NEXT: 0x1058 R_386_TLS_TPOFF tlsshared0 0x0 // GOTRELSHARED-NEXT: 0x203F R_386_RELATIVE - 0x0 +// GOTRELSHARED-NEXT: 0x1050 R_386_TLS_TPOFF tlslocal0 0x0 +// GOTRELSHARED-NEXT: 0x1054 R_386_TLS_TPOFF tlslocal1 0x0 +// GOTRELSHARED-NEXT: 0x1058 R_386_TLS_TPOFF tlsshared0 0x0 // GOTRELSHARED-NEXT: 0x105C R_386_TLS_TPOFF tlsshared1 0x0 // GOTRELSHARED-NEXT: } // GOTRELSHARED-NEXT: ] Index: lld/trunk/test/ELF/mips-32.s =================================================================== --- lld/trunk/test/ELF/mips-32.s +++ lld/trunk/test/ELF/mips-32.s @@ -47,8 +47,8 @@ # REL: Relocations [ # REL-NEXT: Section (7) .rel.dyn { -# REL-NEXT: 0x30004 R_MIPS_REL32 v2 0x0 # REL-NEXT: 0x30008 R_MIPS_REL32 - 0x0 +# REL-NEXT: 0x30004 R_MIPS_REL32 v2 0x0 # REL-NEXT: } # REL-NEXT: ] Index: lld/trunk/test/ELF/mips-64.s =================================================================== --- lld/trunk/test/ELF/mips-64.s +++ lld/trunk/test/ELF/mips-64.s @@ -36,8 +36,8 @@ # CHECK: Relocations [ # CHECK-NEXT: Section (7) .rela.dyn { -# CHECK-NEXT: 0x30008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE v2 0x8 # CHECK-NEXT: 0x30010 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE - 0x30000 +# CHECK-NEXT: 0x30008 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE v2 0x8 # CHECK-NEXT: } # CHECK-NEXT: ] Index: lld/trunk/test/ELF/tls-dynamic-i686.s =================================================================== --- lld/trunk/test/ELF/tls-dynamic-i686.s +++ lld/trunk/test/ELF/tls-dynamic-i686.s @@ -67,12 +67,12 @@ // CHECK: Relocations [ // CHECK: Section ({{.+}}) .rel.dyn { +// CHECK-NEXT: 0x2078 R_386_TLS_DTPMOD32 - 0x0 // CHECK-NEXT: 0x2068 R_386_TLS_DTPMOD32 tls0 0x0 // CHECK-NEXT: 0x206C R_386_TLS_DTPOFF32 tls0 0x0 +// CHECK-NEXT: 0x2080 R_386_TLS_TPOFF tls0 0x0 // CHECK-NEXT: 0x2070 R_386_TLS_DTPMOD32 tls1 0x0 // CHECK-NEXT: 0x2074 R_386_TLS_DTPOFF32 tls1 0x0 -// CHECK-NEXT: 0x2078 R_386_TLS_DTPMOD32 - 0x0 -// CHECK-NEXT: 0x2080 R_386_TLS_TPOFF tls0 0x0 // CHECK-NEXT: 0x2084 R_386_TLS_TPOFF tls1 0x0 // CHECK-NEXT: } Index: lld/trunk/test/ELF/tls-got.s =================================================================== --- lld/trunk/test/ELF/tls-got.s +++ lld/trunk/test/ELF/tls-got.s @@ -24,8 +24,8 @@ // CHECK: Relocations [ // CHECK-NEXT: Section (4) .rela.dyn { -// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0 // CHECK-NEXT: 0x120B8 R_X86_64_TPOFF64 tls0 0x0 +// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0 // CHECK-NEXT: } // CHECK-NEXT: ] Index: lld/trunk/test/ELF/tls-i686.s =================================================================== --- lld/trunk/test/ELF/tls-i686.s +++ lld/trunk/test/ELF/tls-i686.s @@ -62,8 +62,8 @@ // RELOCSHARED: Relocations [ // RELOCSHARED-NEXT: Section (4) .rel.dyn { // RELOCSHARED-NEXT: 0x2001 R_386_TLS_TPOFF32 var 0x0 -// RELOCSHARED-NEXT: 0x200F R_386_TLS_TPOFF32 var1 0x0 // RELOCSHARED-NEXT: 0x2025 R_386_TLS_TPOFF var 0x0 +// RELOCSHARED-NEXT: 0x200F R_386_TLS_TPOFF32 var1 0x0 // RELOCSHARED-NEXT: 0x2032 R_386_TLS_TPOFF var1 0x0 // RELOCSHARED-NEXT: } // RELOCSHARED-NEXT: ]