Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -159,6 +159,7 @@ void addSymbol(SymbolAssignment *Cmd) { PendingSymbols.emplace_back(new LayoutInputSection(Cmd)); } + void addOrphan(StringRef OutputName, InputSectionBase *I); void flushSymbols(); void flushSection(); void finalize(); @@ -205,6 +206,47 @@ Current->addSection(C); } +template +static typename ELFT::uint getAccessFlags(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 OutputSectionBuilder::addOrphan(StringRef OutputName, + InputSectionBase *I) { + bool IsNew; + std::tie(Current, IsNew) = Factory.create(I, OutputName); + Current->addSection(I); + if (!IsNew) + return; + + auto R = std::find_if(OutputSections->rbegin(), OutputSections->rend(), + [&](OutputSectionBase *S) { + return getAccessFlags(S) == getAccessFlags(Current); + }); + + OutputSectionCommand *Cmd = new OutputSectionCommand(OutputName); + if (R == OutputSections->rend()) { + OutputSections->push_back(Current); + ScriptConfig->Commands.emplace_back(Cmd); + } else { + StringRef InsertAfter = (*R)->getName(); + OutputSections->insert(R.base(), Current); + + 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 OutputSectionBuilder::flushSymbols() { for (std::unique_ptr> &I : PendingSymbols) if (I->Cmd->Name == "." || addSymbolToSymtab(*I->Cmd, 0, Current)) { @@ -297,7 +339,7 @@ Symtab::X->getObjectFiles()) for (InputSectionBase *S : F->getSections()) if (!isDiscarded(S) && !S->OutSec) - Builder.addSection(getOutputSectionName(S), S); + Builder.addOrphan(getOutputSectionName(S), S); // Remove from the output all the sections which did not meet // the optional constraints. @@ -355,7 +397,7 @@ I->OutSecOff = Off; Off += I->getSize(); } - // Update section size inside for-loop, so that SIZEOF + // Update section size inside for-loop, so that SIZEOF // works correctly in the case below: // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) } Sec->setSize(Off); 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: .writable : ONLY_IF_RO { *(.writable) } \ 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: