Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -87,11 +87,13 @@ ConstraintKind Constraint = ConstraintKind::NoConstraint; }; +enum class SortKind { None, Name, Align, NameAlign, AlignName }; + struct InputSectionDescription : BaseCommand { InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); StringRef FilePattern; - bool Sort = false; + SortKind Sort = SortKind::None; std::vector ExcludedFiles; std::vector SectionPatterns; }; Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -131,11 +131,27 @@ Sec->addSection(C); } -template -static bool compareByName(InputSectionBase *A, - InputSectionBase *B) { - return A->getSectionName() < B->getSectionName(); -} +template struct SectionsSorter { + SectionsSorter(SortKind Kind) : Kind(Kind) {} + bool operator()(InputSectionBase *A, InputSectionBase *B) { + int AlignmentCmp = A->Alignment - B->Alignment; + if (Kind == SortKind::Align || (Kind == SortKind::AlignName && AlignmentCmp != 0)) + return AlignmentCmp < 0; + + int NameCmp = A->getSectionName().compare(B->getSectionName()); + if (Kind == SortKind::Name || (Kind == SortKind::NameAlign && NameCmp != 0)) + return NameCmp < 0; + + if (Kind == SortKind::NameAlign) + return AlignmentCmp < 0; + if (Kind == SortKind::AlignName) + return NameCmp < 0; + + llvm_unreachable("unknown section sort kind in predicate"); + return false; + } + SortKind Kind; +}; template void LinkerScript::createSections( @@ -155,8 +171,9 @@ } Sections.push_back(S); } - if (I->Sort) - std::stable_sort(Sections.begin(), Sections.end(), compareByName); + if (I->Sort != SortKind::None) + std::stable_sort(Sections.begin(), Sections.end(), + SectionsSorter(I->Sort)); for (InputSectionBase *S : Sections) addSection(Factory, *Out, S, OutputName); } @@ -715,10 +732,32 @@ InCmd->ExcludedFiles.push_back(next()); } - if (skip("SORT")) { + if (skip("SORT") || skip("SORT_BY_NAME")) { expect("("); - InCmd->Sort = true; - readInputFilePattern(InCmd, Keep); + if (skip("SORT_BY_ALIGNMENT")) { + InCmd->Sort = SortKind::NameAlign; + expect("("); + readInputFilePattern(InCmd, Keep); + expect(")"); + } else { + InCmd->Sort = SortKind::Name; + readInputFilePattern(InCmd, Keep); + } + expect(")"); + return; + } + + if (skip("SORT_BY_ALIGNMENT")) { + expect("("); + if (skip("SORT") || skip("SORT_BY_NAME")) { + InCmd->Sort = SortKind::AlignName; + expect("("); + readInputFilePattern(InCmd, Keep); + expect(")"); + } else { + InCmd->Sort = SortKind::Align; + readInputFilePattern(InCmd, Keep); + } expect(")"); return; } Index: lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s =================================================================== --- lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s +++ lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort-nested.s @@ -0,0 +1,7 @@ +.section .aaa.1, "a" +.align 16 +.quad 0x11 + +.section .aaa.2, "a" +.align 4 +.quad 0x22 Index: lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s =================================================================== --- lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s +++ lld/trunk/test/ELF/linkerscript/Inputs/linkerscript-sort.s @@ -1,14 +1,19 @@ .section .aaa.5, "a" +.align 2 .quad 0x55 .section .aaa.1, "a" +.align 32 .quad 0x11 .section .aaa.3, "a" +.align 8 .quad 0x33 .section .aaa.2, "a" +.align 16 .quad 0x22 .section .aaa.4, "a" +.align 4 .quad 0x44 Index: lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s =================================================================== --- lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s +++ lld/trunk/test/ELF/linkerscript/linkerscript-sort-nested.s @@ -0,0 +1,42 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/linkerscript-sort-nested.s -o %t2.o + +## Check sorting first by alignment and then by name. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.aaa.*))) } }" > %t1.script +# RUN: ld.lld -o %t1 --script %t1.script %t1.o %t2.o +# RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=SORTED_AN %s +# SORTED_AN: Contents of section .aaa: +# SORTED_AN-NEXT: 0120 02000000 00000000 22000000 00000000 +# SORTED_AN-NEXT: 0130 11000000 00000000 00000000 00000000 +# SORTED_AN-NEXT: 0140 55000000 00000000 00000000 00000000 +# SORTED_AN-NEXT: 0150 00000000 00000000 00000000 00000000 +# SORTED_AN-NEXT: 0160 01000000 00000000 + +## Check sorting first by name and then by alignment. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(SORT_BY_ALIGNMENT(.aaa.*))) } }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t1.o %t2.o +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SORTED_NA %s +# SORTED_NA: Contents of section .aaa: +# SORTED_NA-NEXT: 0120 11000000 00000000 00000000 00000000 +# SORTED_NA-NEXT: 0130 00000000 00000000 00000000 00000000 +# SORTED_NA-NEXT: 0140 01000000 00000000 02000000 00000000 +# SORTED_NA-NEXT: 0150 22000000 00000000 00000000 00000000 +# SORTED_NA-NEXT: 0160 55000000 00000000 + +.global _start +_start: + nop + +.section .aaa.1, "a" +.align 32 +.quad 1 + +.section .aaa.2, "a" +.align 2 +.quad 2 + +.section .aaa.5, "a" +.align 16 +.quad 0x55 Index: lld/trunk/test/ELF/linkerscript/linkerscript-sort.s =================================================================== --- lld/trunk/test/ELF/linkerscript/linkerscript-sort.s +++ lld/trunk/test/ELF/linkerscript/linkerscript-sort.s @@ -6,12 +6,14 @@ # RUN: echo "SECTIONS { .aaa : { *(.aaa.*) } }" > %t1.script # RUN: ld.lld -o %t1 --script %t1.script %t2.o %t1.o # RUN: llvm-objdump -s %t1 | FileCheck -check-prefix=UNSORTED %s -# UNSORTED: Contents of section .aaa: -# UNSORTED-NEXT: 0120 55000000 00000000 11000000 00000000 -# UNSORTED-NEXT: 0130 33000000 00000000 22000000 00000000 -# UNSORTED-NEXT: 0140 44000000 00000000 05000000 00000000 -# UNSORTED-NEXT: 0150 01000000 00000000 03000000 00000000 -# UNSORTED-NEXT: 0160 02000000 00000000 04000000 00000000 +# UNSORTED: Contents of section .aaa: +# UNSORTED-NEXT: 0120 55000000 00000000 00000000 00000000 +# UNSORTED-NEXT: 0130 00000000 00000000 00000000 00000000 +# UNSORTED-NEXT: 0140 11000000 00000000 33000000 00000000 +# UNSORTED-NEXT: 0150 22000000 00000000 44000000 00000000 +# UNSORTED-NEXT: 0160 05000000 00000000 01000000 00000000 +# UNSORTED-NEXT: 0170 03000000 00000000 02000000 00000000 +# UNSORTED-NEXT: 0180 04000000 00000000 ## Check that SORT works (sorted by name of section). # RUN: echo "SECTIONS { .aaa : { *(SORT(.aaa.*)) } }" > %t2.script @@ -21,8 +23,10 @@ # SORTED_A-NEXT: 0120 11000000 00000000 01000000 00000000 # SORTED_A-NEXT: 0130 22000000 00000000 02000000 00000000 # SORTED_A-NEXT: 0140 33000000 00000000 03000000 00000000 -# SORTED_A-NEXT: 0150 44000000 00000000 04000000 00000000 -# SORTED_A-NEXT: 0160 55000000 00000000 05000000 00000000 +# SORTED_A-NEXT: 0150 44000000 00000000 00000000 00000000 +# SORTED_A-NEXT: 0160 04000000 00000000 55000000 00000000 +# SORTED_A-NEXT: 0170 00000000 00000000 00000000 00000000 +# SORTED_A-NEXT: 0180 05000000 00000000 ## When we switch the order of files, check that sorting by ## section names is stable. @@ -30,32 +34,59 @@ # RUN: ld.lld -o %t3 --script %t3.script %t1.o %t2.o # RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_B %s # SORTED_B: Contents of section .aaa: -# SORTED_B-NEXT: 0120 01000000 00000000 11000000 00000000 -# SORTED_B-NEXT: 0130 02000000 00000000 22000000 00000000 -# SORTED_B-NEXT: 0140 03000000 00000000 33000000 00000000 -# SORTED_B-NEXT: 0150 04000000 00000000 44000000 00000000 -# SORTED_B-NEXT: 0160 05000000 00000000 55000000 00000000 +# SORTED_B-NEXT: 0120 01000000 00000000 00000000 00000000 +# SORTED_B-NEXT: 0130 00000000 00000000 00000000 00000000 +# SORTED_B-NEXT: 0140 11000000 00000000 02000000 00000000 +# SORTED_B-NEXT: 0150 22000000 00000000 03000000 00000000 +# SORTED_B-NEXT: 0160 33000000 00000000 00000000 00000000 +# SORTED_B-NEXT: 0170 04000000 00000000 44000000 00000000 +# SORTED_B-NEXT: 0180 05000000 00000000 55000000 00000000 ## Check that SORT surrounded with KEEP also works. # RUN: echo "SECTIONS { .aaa : { KEEP (*(SORT(.aaa.*))) } }" > %t3.script # RUN: ld.lld -o %t3 --script %t3.script %t2.o %t1.o # RUN: llvm-objdump -s %t3 | FileCheck -check-prefix=SORTED_A %s +## Check that SORT_BY_NAME works (SORT is alias). +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_NAME(.aaa.*)) } }" > %t4.script +# RUN: ld.lld -o %t4 --script %t4.script %t2.o %t1.o +# RUN: llvm-objdump -s %t4 | FileCheck -check-prefix=SORTED_A %s + +## Check that sections ordered by alignment. +# RUN: echo "SECTIONS { .aaa : { *(SORT_BY_ALIGNMENT(.aaa.*)) } }" > %t5.script +# RUN: ld.lld -o %t5 --script %t5.script %t1.o %t2.o +# RUN: llvm-objdump -s %t5 | FileCheck -check-prefix=SORTED_ALIGNMENT %s +# SORTED_ALIGNMENT: Contents of section .aaa: +# SORTED_ALIGNMENT-NEXT: 0120 01000000 00000000 55000000 00000000 +# SORTED_ALIGNMENT-NEXT: 0130 02000000 00000000 44000000 00000000 +# SORTED_ALIGNMENT-NEXT: 0140 03000000 00000000 33000000 00000000 +# SORTED_ALIGNMENT-NEXT: 0150 04000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 0160 22000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 0170 00000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 0180 05000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 0190 00000000 00000000 00000000 00000000 +# SORTED_ALIGNMENT-NEXT: 01a0 11000000 00000000 + .global _start _start: nop .section .aaa.5, "a" +.align 32 .quad 5 .section .aaa.1, "a" +.align 2 .quad 1 .section .aaa.3, "a" +.align 8 .quad 3 .section .aaa.2, "a" +.align 4 .quad 2 .section .aaa.4, "a" +.align 16 .quad 4