Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -164,6 +164,9 @@ std::vector *> createInputSectionList(OutputSectionCommand &Cmd); + void addOrphan(OutputSectionFactory &Factory, StringRef OutputName, + InputSectionBase *I); + // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -259,6 +259,50 @@ } template +static typename ELFT::uint getPermissions(OutputSectionBase *Sec) { + return Sec->getFlags() & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); +} + +// Places orphan section to desired position. Which is place after +// the last section with the same access attributes. +// If there is no such section - just adds ophan to the end. Also +// updates the command queue with new output section entry. +template +void LinkerScript::addOrphan(OutputSectionFactory &Factory, + StringRef OutputName, + InputSectionBase *C) { + bool IsNew; + OutputSectionBase *OutSec; + std::tie(OutSec, IsNew) = Factory.create(C, OutputName); + OutSec->addSection(C); + if (!IsNew) + return; + + auto R = std::find_if(OutputSections->rbegin(), OutputSections->rend(), + [&](OutputSectionBase *S) { + return getPermissions(S) == getPermissions(OutSec); + }); + + OutputSectionCommand *Cmd = new OutputSectionCommand(OutputName); + if (R == OutputSections->rend()) { + OutputSections->push_back(OutSec); + ScriptConfig->Commands.emplace_back(Cmd); + return; + } + + StringRef InsertAfter = (*R)->getName(); + OutputSections->insert(R.base(), OutSec); + + auto I = llvm::find_if( + ScriptConfig->Commands, [&](std::unique_ptr &Base) { + if (auto *O = dyn_cast(Base.get())) + return O->Name == InsertAfter; + return false; + }); + ScriptConfig->Commands.emplace(I + 1, Cmd); +} + +template void LinkerScript::createSections(OutputSectionFactory &Factory) { for (const std::unique_ptr &Base1 : Opt.Commands) { if (auto *Cmd = dyn_cast(Base1.get())) { @@ -291,16 +335,9 @@ // Add orphan sections. for (const std::unique_ptr> &F : Symtab::X->getObjectFiles()) { - for (InputSectionBase *S : F->getSections()) { - if (isDiscarded(S) || S->OutSec) - continue; - OutputSectionBase *OutSec; - bool IsNew; - std::tie(OutSec, IsNew) = Factory.create(S, getOutputSectionName(S)); - if (IsNew) - OutputSections->push_back(OutSec); - OutSec->addSection(S); - } + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec) + addOrphan(Factory, getOutputSectionName(S), S); } } Index: test/ELF/linkerscript/linkerscript-orphans.s =================================================================== --- test/ELF/linkerscript/linkerscript-orphans.s +++ test/ELF/linkerscript/linkerscript-orphans.s @@ -1,31 +1,46 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t -# RUN: echo "SECTIONS { .writable : { *(.writable) } }" > %t.script +# RUN: echo "SECTIONS { \ +# RUN: .foo1 : { *(.foo1) } \ +# RUN: .foo2 : { *(.foo2) } \ +# RUN: .bar1 : { *(.bar1) } }" > %t.script # RUN: ld.lld -o %t.out --script %t.script %t -# RUN: llvm-objdump -section-headers %t.out | \ -# RUN: FileCheck -check-prefix=TEXTORPHAN %s +# RUN: llvm-objdump -section-headers %t.out | FileCheck %s -# RUN: echo "SECTIONS { .text : { *(.text) } }" > %t.script -# RUN: ld.lld -o %t.out --script %t.script %t -# RUN: llvm-objdump -section-headers %t.out | \ -# RUN: FileCheck -check-prefix=WRITABLEORPHAN %s - -# TEXTORPHAN: Sections: -# TEXTORPHAN-NEXT: Idx Name -# TEXTORPHAN-NEXT: 0 -# TEXTORPHAN-NEXT: 1 .writable -# TEXTORPHAN-NEXT: 2 .text - -# WRITABLEORPHAN: Sections: -# WRITABLEORPHAN-NEXT: Idx Name -# WRITABLEORPHAN-NEXT: 0 -# WRITABLEORPHAN-NEXT: 1 .text -# WRITABLEORPHAN-NEXT: 2 .writable +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .foo1 00000004 0000000000000158 DATA +# CHECK-NEXT: 2 .foo2 00000004 000000000000015c DATA +# CHECK-NEXT: 3 .foo3 00000004 0000000000000160 DATA +# CHECK-NEXT: 4 .bar1 00000004 0000000000000164 DATA +# CHECK-NEXT: 5 .bar2 00000004 0000000000000168 DATA +# CHECK-NEXT: 6 .text 00000001 000000000000016c TEXT DATA +# CHECK-NEXT: 7 .symtab 000000a8 0000000000000000 +# CHECK-NEXT: 8 .shstrtab 0000003f 0000000000000000 +# CHECK-NEXT: 9 .strtab 00000021 0000000000000000 .global _start _start: - nop + nop -.section .writable,"aw" - .zero 4 +.section .foo1, "a" +foo1: + .long 1 + +.section .foo2, "a" +foo2: + .long 1 + +.section .foo3, "a" +foo3: + .long 1 + +.section .bar1, "aw" +bar1: + .long 1 + +.section .bar2, "aw" +bar2: + .long 1 Index: test/ELF/linkerscript/linkerscript-sections-constraint.s =================================================================== --- test/ELF/linkerscript/linkerscript-sections-constraint.s +++ test/ELF/linkerscript/linkerscript-sections-constraint.s @@ -7,10 +7,8 @@ # RUN: llvm-objdump -section-headers %t1 | \ # RUN: FileCheck -check-prefix=BASE %s # BASE: Sections: -# BASE-NEXT: Idx Name Size Address Type -# BASE-NEXT: 0 00000000 0000000000000000 -# BASE-NEXT: 1 .writable 00000004 0000000000000200 DATA -# BASE-NEXT: 2 .readable 00000004 0000000000000204 DATA +# BASE: .writable +# BASE: .readable # RUN: echo "SECTIONS { \ # RUN: .foo : ONLY_IF_RO { *(.foo.*) } \ @@ -22,11 +20,11 @@ # NO1: Sections: # NO1-NEXT: Idx Name Size Address Type # NO1-NEXT: 0 00000000 0000000000000000 -# NO1-NEXT: 1 .writable 00000004 0000000000000200 DATA -# NO1-NEXT: 2 .readable 00000004 0000000000000204 DATA -# NO1-NEXT: 3 .text 00000001 0000000000000208 TEXT DATA -# NO1-NEXT: 4 .foo.2 00000004 0000000000000209 DATA -# NO1-NEXT: 5 .foo.1 00000004 000000000000020d TEXT DATA +# NO1-NEXT: 1 .writable 00000004 00000000000001c8 DATA +# NO1-NEXT: 2 .foo.2 00000004 00000000000001cc DATA +# NO1-NEXT: 3 .readable 00000004 00000000000001d0 DATA +# NO1-NEXT: 4 .text 00000001 00000000000001d4 TEXT DATA +# NO1-NEXT: 5 .foo.1 00000004 00000000000001d5 TEXT DATA .global _start _start: Index: test/ELF/linkerscript/linkerscript-sections.s =================================================================== --- test/ELF/linkerscript/linkerscript-sections.s +++ test/ELF/linkerscript/linkerscript-sections.s @@ -21,8 +21,8 @@ # SEC-DEFAULT: 3 other 00000003 {{[0-9a-f]*}} DATA # SEC-DEFAULT: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-DEFAULT: 5 .shstrtab 00000002 {{[0-9a-f]*}} -# SEC-DEFAULT: 6 .symtab 00000030 {{[0-9a-f]*}} -# SEC-DEFAULT: 7 .shstrtab 00000032 {{[0-9a-f]*}} +# SEC-DEFAULT: 6 .shstrtab 00000032 {{[0-9a-f]*}} +# SEC-DEFAULT: 7 .symtab 00000030 {{[0-9a-f]*}} # SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}} # Sections are put in order specified in linker script. @@ -62,8 +62,8 @@ # SEC-SWAP-NAMES: 3 other 00000003 {{[0-9a-f]*}} DATA # SEC-SWAP-NAMES: 4 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-SWAP-NAMES: 5 .shstrtab 00000002 {{[0-9a-f]*}} -# SEC-SWAP-NAMES: 6 .symtab 00000030 {{[0-9a-f]*}} -# SEC-SWAP-NAMES: 7 .shstrtab 00000032 {{[0-9a-f]*}} +# SEC-SWAP-NAMES: 6 .shstrtab 00000032 {{[0-9a-f]*}} +# SEC-SWAP-NAMES: 7 .symtab 00000030 {{[0-9a-f]*}} # SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}} # .shstrtab from the input object file is discarded. @@ -99,8 +99,8 @@ # SEC-MULTI: 2 .data 00000023 {{[0-9a-f]*}} DATA # SEC-MULTI: 3 .bss 00000002 {{[0-9a-f]*}} BSS # SEC-MULTI: 4 .shstrtab 00000002 {{[0-9a-f]*}} -# SEC-MULTI: 5 .symtab 00000030 {{[0-9a-f]*}} -# SEC-MULTI: 6 .shstrtab 0000002c {{[0-9a-f]*}} +# SEC-MULTI: 5 .shstrtab 0000002c {{[0-9a-f]*}} +# SEC-MULTI: 6 .symtab 00000030 {{[0-9a-f]*}} # SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}} .globl _start Index: test/ELF/linkerscript/linkerscript-va.s =================================================================== --- test/ELF/linkerscript/linkerscript-va.s +++ test/ELF/linkerscript/linkerscript-va.s @@ -7,9 +7,9 @@ # CHECK: Sections: # CHECK-NEXT: Idx Name Size Address Type # CHECK-NEXT: 0 00000000 0000000000000000 -# CHECK-NEXT: 1 .foo 00000004 0000000000000120 DATA -# CHECK-NEXT: 2 .boo 00000004 0000000000000124 DATA -# CHECK-NEXT: 3 .text 00000001 0000000000000128 TEXT DATA +# CHECK-NEXT: 1 .text 00000001 0000000000000158 TEXT DATA +# CHECK-NEXT: 2 .foo 00000004 0000000000000159 DATA +# CHECK-NEXT: 3 .boo 00000004 000000000000015d DATA .global _start _start: