Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -281,6 +282,9 @@ // A list of symbols referenced by the script. std::vector ReferencedSymbols; + + // Used to implement INSERT AFTER sequence. + llvm::SetVector InsertAfter; }; extern LinkerScript *Script; Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -457,6 +457,14 @@ } Script->SectionCommands.push_back(Cmd); } + + if (!atEOF() && consume("INSERT")) { + expect("AFTER"); + skip(); + for (BaseCommand *Base : Script->SectionCommands) + if (auto *Sec = dyn_cast(Base)) + Script->InsertAfter.insert(Sec); + } } static int precedence(StringRef Op) { Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1070,6 +1070,22 @@ return; } + // This is used to implement INSERT AFTER .section sequence. + // In this case we let our orphans placement algorithm to find + // and place sections from sequence. We move them to the end so + // them are placed after all other sections. + if (!Script->InsertAfter.empty()) { + std::stable_partition(Script->SectionCommands.begin(), + Script->SectionCommands.end(), [](BaseCommand *Base) { + if (auto *Sec = dyn_cast(Base)) + return !Script->InsertAfter.count(Sec); + return true; + }); + // Orphan sections assumed to have no valid section index below. + for (OutputSection *Sec : Script->InsertAfter) + Sec->SectionIndex = INT_MAX; + } + // Orphan sections are sections present in the input files which are // not explicitly placed into the output file by the linker script. // 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