Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -91,6 +91,7 @@ InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); StringRef FilePattern; + bool Sort = false; std::vector ExcludedFiles; std::vector SectionPatterns; }; Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -132,11 +132,18 @@ } template +static bool compareByName(InputSectionBase *A, + InputSectionBase *B) { + return A->getSectionName() < B->getSectionName(); +} + +template std::vector *> LinkerScript::createSections(OutputSectionFactory &Factory) { std::vector *> Ret; for (auto &P : getSectionMap()) { + std::vector *> Sections; StringRef OutputName = P.first; const InputSectionDescription *I = P.second; for (InputSectionBase *S : getInputSections(I)) { @@ -145,8 +152,12 @@ reportDiscarded(S); continue; } - addSection(Factory, Ret, S, OutputName); + Sections.push_back(S); } + if (I->Sort) + std::stable_sort(Sections.begin(), Sections.end(), compareByName); + for (InputSectionBase *S : Sections) + addSection(Factory, Ret, S, OutputName); } // Add all other input sections, which are not listed in script. @@ -444,6 +455,7 @@ std::vector readOutputSectionFiller(); std::vector readOutputSectionPhdrs(); std::unique_ptr readInputSectionDescription(); + void readInputFilePattern(InputSectionDescription *InCmd, bool Keep); void readInputSectionRules(InputSectionDescription *InCmd, bool Keep); unsigned readPhdrType(); void readProvide(bool Hidden); @@ -674,7 +686,17 @@ .Default(-1); } -void ScriptParser::readInputSectionRules(InputSectionDescription *InCmd, bool Keep) { +void ScriptParser::readInputFilePattern(InputSectionDescription *InCmd, + bool Keep) { + while (!Error && !skip(")")) { + if (Keep) + Opt.KeptSections.push_back(peek()); + InCmd->SectionPatterns.push_back(next()); + } +} + +void ScriptParser::readInputSectionRules(InputSectionDescription *InCmd, + bool Keep) { InCmd->FilePattern = next(); expect("("); @@ -684,11 +706,15 @@ InCmd->ExcludedFiles.push_back(next()); } - while (!Error && !skip(")")) { - if (Keep) - Opt.KeptSections.push_back(peek()); - InCmd->SectionPatterns.push_back(next()); + if (skip("SORT")) { + expect("("); + InCmd->Sort = true; + readInputFilePattern(InCmd, Keep); + expect(")"); + return; } + + readInputFilePattern(InCmd, Keep); } std::unique_ptr 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 @@ -0,0 +1,14 @@ +.section .aaa.5, "a" +.quad 0x55 + +.section .aaa.1, "a" +.quad 0x11 + +.section .aaa.3, "a" +.quad 0x33 + +.section .aaa.2, "a" +.quad 0x22 + +.section .aaa.4, "a" +.quad 0x44 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 @@ -0,0 +1,61 @@ +# 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.s -o %t2.o + +# 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 + +## Check that SORT works (sorted by name of section). +# RUN: echo "SECTIONS { .aaa : { *(SORT(.aaa.*)) } }" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t2.o %t1.o +# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=SORTED_A %s +# SORTED_A: Contents of section .aaa: +# 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 + +## When we switch the order of files, check that sorting by +## section names is stable. +# RUN: echo "SECTIONS { .aaa : { *(SORT(.aaa.*)) } }" > %t3.script +# 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 + +## 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 + +.global _start +_start: + nop + +.section .aaa.5, "a" +.quad 5 + +.section .aaa.1, "a" +.quad 1 + +.section .aaa.3, "a" +.quad 3 + +.section .aaa.2, "a" +.quad 2 + +.section .aaa.4, "a" +.quad 4