Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -101,6 +101,7 @@ std::string MemoryRegionName; std::string LMARegionName; bool Noload = false; + bool InsertAfter = false; template void finalize(); template void writeTo(uint8_t *Buf); Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -457,6 +457,18 @@ } Script->SectionCommands.push_back(Cmd); } + + // This is used to implement INSERT AFTER .section sequence. + // In this case we let out orphans placement algorithm to find + // room for output sections specified. It does it after placing + // all other sections at first. + if (!atEOF() && consume("INSERT")) { + expect("AFTER"); + skip(); + for (BaseCommand *Base : Script->SectionCommands) + if (auto *Sec = dyn_cast(Base)) + Sec->InsertAfter = true; + } } static int precedence(StringRef Op) { Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -807,6 +807,8 @@ static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { const OutputSection *A = cast(ACmd); const OutputSection *B = cast(BCmd); + if (A->InsertAfter != B->InsertAfter) + return B->InsertAfter; if (A->SortRank != B->SortRank) return A->SortRank < B->SortRank; if (!(A->SortRank & RF_NOT_ADDR_SET)) @@ -1111,10 +1113,10 @@ auto I = Script->SectionCommands.begin(); auto E = Script->SectionCommands.end(); - auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) { + auto NonScriptI = std::stable_partition(I, E, [](BaseCommand *Base) { if (auto *Sec = dyn_cast(Base)) - return Sec->Live && Sec->SectionIndex == INT_MAX; - return false; + return Sec->SectionIndex != INT_MAX && !Sec->InsertAfter; + return true; }); // Sort the orphan sections. Index: test/ELF/linkerscript/insert-after.s =================================================================== --- test/ELF/linkerscript/insert-after.s +++ test/ELF/linkerscript/insert-after.s @@ -0,0 +1,36 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: echo "SECTIONS { \ +# RUN: .bar1 : { __start_bar1 = .; *(.foo1) __end_bar1 = .; } \ +# RUN: } INSERT AFTER .data; \ +# RUN: SECTIONS { \ +# RUN: .bar2 : { __start_bar2 = .; *(.foo2) __end_bar2 = .; } \ +# RUN: } INSERT AFTER .text;" > %t.script + +# RUN: ld.lld %t1.o -o %t1 --script %t.script +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000001 0000000000000000 TEXT DATA +# CHECK-NEXT: 2 .bar2 00000008 0000000000000001 TEXT DATA +# CHECK-NEXT: 3 .data 00000008 0000000000000009 DATA +# CHECK-NEXT: 4 .bar1 00000008 0000000000000011 DATA +# CHECK-NEXT: 5 .comment 00000008 0000000000000000 +# CHECK-NEXT: 6 .symtab 00000090 0000000000000000 +# CHECK-NEXT: 7 .shstrtab 0000003c 0000000000000000 +# CHECK-NEXT: 8 .strtab 00000038 0000000000000000 + +.global _start +_start: + nop + +.section .data,"aw" +.quad 0 + +.section .foo1,"aw" +.quad 1 + +.section .foo2,"ax" +.quad 1