Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -150,6 +150,12 @@ } template +static bool comparePriority(InputSectionBase *A, + InputSectionBase *B) { + return getPriority(A->getSectionName()) < getPriority(B->getSectionName()); +} + +template static std::function *, InputSectionBase *)> getComparator(SortKind K) { if (K == SortByName) @@ -180,6 +186,11 @@ std::stable_sort(Sections.begin(), Sections.end(), getComparator(Cmd->SortOuter)); + if (OutputName == ".init_array" || OutputName == ".fini_array") + std::stable_sort(Sections.begin(), Sections.end(), comparePriority); + else if (OutputName == ".ctors" || OutputName == ".dtors") + std::stable_sort(Sections.begin(), Sections.end(), compCtors); + for (InputSectionBase *S : Sections) addSection(Factory, *OutputSections, S, OutputName); } Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -689,6 +689,11 @@ std::vector>> OwningSections; }; +int getPriority(StringRef S); +template +bool compCtors(const InputSectionBase *A, + const InputSectionBase *B); + template BuildIdSection *Out::BuildId; template DynamicSection *Out::Dynamic; template EhFrameHeader *Out::EhFrameHdr; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -847,7 +847,7 @@ // If an input string is in the form of "foo.N" where N is a number, // return N. Otherwise, returns 65536, which is one greater than the // lowest priority. -static int getPriority(StringRef S) { +int elf::getPriority(StringRef S) { size_t Pos = S.rfind('.'); if (Pos == StringRef::npos) return 65536; @@ -921,8 +921,8 @@ // are too many real-world use cases of .ctors, so we had no choice to // support that with this rather ad-hoc semantics. template -static bool compCtors(const InputSection *A, - const InputSection *B) { +bool elf::compCtors(const InputSectionBase *A, + const InputSectionBase *B) { bool BeginA = isCrtbegin(A->getFile()->getName()); bool BeginB = isCrtbegin(B->getFile()->getName()); if (BeginA != BeginB) @@ -1954,5 +1954,14 @@ template class OutputSectionFactory; template class OutputSectionFactory; template class OutputSectionFactory; + +template bool compCtors(const InputSectionBase *, + const InputSectionBase *); +template bool compCtors(const InputSectionBase *, + const InputSectionBase *); +template bool compCtors(const InputSectionBase *, + const InputSectionBase *); +template bool compCtors(const InputSectionBase *, + const InputSectionBase *); } } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -653,6 +653,14 @@ Sec->addSection(C); } } + + // Sort section contents for __attribute__((init_priority(N)). + sortInitFini( + Factory.lookup(".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC)); + sortInitFini( + Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC)); + sortCtorsDtors(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); + sortCtorsDtors(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); } // Create output section objects and add them to OutputSections. @@ -672,12 +680,6 @@ Out::Dynamic->FiniArraySec = Factory.lookup(".fini_array", SHT_FINI_ARRAY, SHF_WRITE | SHF_ALLOC); - // Sort section contents for __attribute__((init_priority(N)). - sortInitFini(Out::Dynamic->InitArraySec); - sortInitFini(Out::Dynamic->FiniArraySec); - sortCtorsDtors(Factory.lookup(".ctors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); - sortCtorsDtors(Factory.lookup(".dtors", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC)); - // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop // symbols for sections, so that the runtime can get the start and end // addresses of each section by section name. Add such symbols. Index: test/ELF/linkerscript/linkerscript-ctors-dtors.s =================================================================== --- test/ELF/linkerscript/linkerscript-ctors-dtors.s +++ test/ELF/linkerscript/linkerscript-ctors-dtors.s @@ -0,0 +1,43 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +// RUN: %p/../Inputs/ctors_dtors_priority1.s -o %t-crtbegin.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +// RUN: %p/../Inputs/ctors_dtors_priority2.s -o %t2 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +// RUN: %p/../Inputs/ctors_dtors_priority3.s -o %t-crtend.o +// RUN: echo "SECTIONS {.ctors : {*(.ctors*)} \ +// RUN: .dtors : {*(.dtors*)} }" > %t.script +// RUN: ld.lld %t1 %t2 %t-crtend.o %t-crtbegin.o --script %t.script -o %t.exe +// RUN: llvm-objdump -s %t.exe | FileCheck %s +// REQUIRES: x86 + +.globl _start +_start: + nop + +.section .ctors, "aw", @progbits + .byte 1 +.section .ctors.100, "aw", @progbits + .byte 2 +.section .ctors.005, "aw", @progbits + .byte 3 +.section .ctors, "aw", @progbits + .byte 4 +.section .ctors, "aw", @progbits + .byte 5 + +.section .dtors, "aw", @progbits + .byte 0x11 +.section .dtors.100, "aw", @progbits + .byte 0x12 +.section .dtors.005, "aw", @progbits + .byte 0x13 +.section .dtors, "aw", @progbits + .byte 0x14 +.section .dtors, "aw", @progbits + .byte 0x15 + +// CHECK: Contents of section .ctors: +// CHECK-NEXT: a1010405 b10302c1 +// CHECK: Contents of section .dtors: +// CHECK-NEXT: a2111415 b21312c2 Index: test/ELF/linkerscript/linkerscript-init-fini.s =================================================================== --- test/ELF/linkerscript/linkerscript-init-fini.s +++ test/ELF/linkerscript/linkerscript-init-fini.s @@ -0,0 +1,39 @@ +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +// RUN: echo "SECTIONS {.init_array : {*(.init_array*)} \ +// RUN: .fini_array : {*(.fini_array*)} }" > %t.script +// RUN: ld.lld %t --script %t.script -o %t.exe +// RUN: llvm-objdump -s %t.exe | FileCheck %s +// REQUIRES: x86 + +.globl _start +_start: + nop + +.section .init_array, "aw", @init_array + .align 8 + .byte 1 +.section .init_array.100, "aw", @init_array + .long 2 +.section .init_array.5, "aw", @init_array + .byte 3 +.section .init_array, "aw", @init_array + .byte 4 +.section .init_array, "aw", @init_array + .byte 5 + +.section .fini_array, "aw", @fini_array + .align 8 + .byte 0x11 +.section .fini_array.100, "aw", @fini_array + .long 0x12 +.section .fini_array.5, "aw", @fini_array + .byte 0x13 +.section .fini_array, "aw", @fini_array + .byte 0x14 +.section .fini_array, "aw", @fini_array + .byte 0x15 + +// CHECK: Contents of section .init_array: +// CHECK-NEXT: 03020000 00000000 010405 +// CHECK: Contents of section .fini_array: +// CHECK-NEXT: 13120000 00000000 111415