Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -200,7 +200,7 @@ private: void computeInputSections(InputSectionDescription *); - void addSection(OutputSectionFactory &Factory, + bool addSection(OutputSectionFactory &Factory, InputSectionBase *Sec, StringRef Name); void discard(ArrayRef *> V); @@ -223,6 +223,8 @@ void process(BaseCommand &Base); llvm::DenseSet *> AlreadyOutputOS; llvm::DenseSet AlreadyOutputIS; + + std::vector SectionsOrder; }; // Variable template is a C++14 feature, so we can't template Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -254,7 +254,7 @@ } template -void LinkerScript::addSection(OutputSectionFactory &Factory, +bool LinkerScript::addSection(OutputSectionFactory &Factory, InputSectionBase *Sec, StringRef Name) { OutputSectionBase *OutSec; @@ -263,6 +263,7 @@ if (IsNew) OutputSections->push_back(OutSec); OutSec->addSection(Sec); + return IsNew; } template @@ -319,13 +320,50 @@ } template +static typename ELFT::uint getPermissions(OutputSectionBase *Sec) { + return Sec->getFlags() & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); +} + +template void LinkerScript::createSections(OutputSectionFactory &Factory) { processCommands(Factory); - // Add orphan sections. - for (ObjectFile *F : Symtab::X->getObjectFiles()) - for (InputSectionBase *S : F->getSections()) - if (!isDiscarded(S) && !S->OutSec) - addSection(Factory, S, getOutputSectionName(S)); + + // 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. + // Returns output section where input section was landed. + for (ObjectFile *F : Symtab::X->getObjectFiles()) { + for (InputSectionBase *S : F->getSections()) { + if (isDiscarded(S) || S->OutSec) + continue; + + // Add the orphan section and check if it is newly created. + // If so, we need to move it inside OutputSections list, + // we are placing orphans after the last output sections + // with the same attributes. Or at the end if no such one found. + bool New = addSection(Factory, S, getOutputSectionName(S)); + if (!New) + continue; + + OutputSectionBase *Orphan = OutputSections->back(); + OutputSections->pop_back(); + auto R = + std::find_if(OutputSections->rbegin(), OutputSections->rend(), + [&](OutputSectionBase *S) { + if (S->getType() == SHT_NOBITS) + return false; + return getPermissions(S) == getPermissions(Orphan); + }); + auto Pos = R != OutputSections->rend() ? R.base() : OutputSections->end(); + OutputSections->emplace(Pos, Orphan); + } + } + + // Finally we can build the sections order list. We need it because + // do not create the commands for orphans here, though getSectionIndex() + // needs to know section index. + for (OutputSectionBase *Sec : *OutputSections) + SectionsOrder.push_back(Sec->getName()); } // Sets value of a section-defined symbol. Two kinds of @@ -619,14 +657,10 @@ // were in the script. If a given name did not appear in the script, // it returns INT_MAX, so that it will be laid out at end of file. template int LinkerScript::getSectionIndex(StringRef Name) { - int I = 0; - for (std::unique_ptr &Base : Opt.Commands) { - if (auto *Cmd = dyn_cast(Base.get())) - if (Cmd->Name == Name) - return I; - ++I; - } - return INT_MAX; + auto I = llvm::find(SectionsOrder, Name); + if (I == SectionsOrder.end()) + return INT_MAX; + return std::distance(SectionsOrder.begin(), I); } // A compartor to sort output sections. Returns -1 or 1 if Index: test/ELF/linkerscript/data-segment-relro.s =================================================================== --- test/ELF/linkerscript/data-segment-relro.s +++ test/ELF/linkerscript/data-segment-relro.s @@ -24,7 +24,7 @@ # RUN: llvm-readobj -s %t2 | FileCheck %s # CHECK: Section { -# CHECK: Index: 4 +# CHECK: Index: 12 # CHECK-NEXT: Name: .got # CHECK-NEXT: Type: SHT_PROGBITS # CHECK-NEXT: Flags [ @@ -40,7 +40,7 @@ # CHECK-NEXT: EntrySize: # CHECK-NEXT: } # CHECK-NEXT: Section { -# CHECK-NEXT: Index: 5 +# CHECK-NEXT: Index: 13 # CHECK-NEXT: Name: .got.plt # CHECK-NEXT: Type: SHT_PROGBITS # CHECK-NEXT: Flags [ Index: test/ELF/linkerscript/eh-frame-hdr.s =================================================================== --- test/ELF/linkerscript/eh-frame-hdr.s +++ test/ELF/linkerscript/eh-frame-hdr.s @@ -7,8 +7,8 @@ # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t # RUN: llvm-objdump -s -section=".eh_frame_hdr" %t1 | FileCheck %s -# CHECK: 0158 011b033b 14000000 01000000 49000000 -# CHECK-NEXT: 0168 30000000 +# CHECK: 01c8 011b033b ccffffff 01000000 c9ffffff +# CHECK-NEXT: 01d8 e8ffffff .global _start _start: Index: test/ELF/linkerscript/merge-sections.s =================================================================== --- test/ELF/linkerscript/merge-sections.s +++ test/ELF/linkerscript/merge-sections.s @@ -12,8 +12,8 @@ # CHECK-NEXT: SHF_MERGE # CHECK-NEXT: SHF_STRINGS # CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x1C8 -# CHECK-NEXT: Offset: 0x1C8 +# CHECK-NEXT: Address: 0x200 +# CHECK-NEXT: Offset: 0x200 # CHECK-NEXT: Size: 4 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -28,8 +28,8 @@ # CHECK-NEXT: SHF_ALLOC # CHECK-NEXT: SHF_MERGE # CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x1CC -# CHECK-NEXT: Offset: 0x1CC +# CHECK-NEXT: Address: 0x204 +# CHECK-NEXT: Offset: 0x204 # CHECK-NEXT: Size: 1 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -44,8 +44,8 @@ # CHECK-NEXT: SHF_ALLOC # CHECK-NEXT: SHF_MERGE # CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x1CE -# CHECK-NEXT: Offset: 0x1CE +# CHECK-NEXT: Address: 0x206 +# CHECK-NEXT: Offset: 0x206 # CHECK-NEXT: Size: 2 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -54,10 +54,10 @@ # CHECK: Name: begin -# CHECK-NEXT: Value: 0x1C8 +# CHECK-NEXT: Value: 0x200 # CHECK: Name: end -# CHECK-NEXT: Value: 0x1D0 +# CHECK-NEXT: Value: 0x208 .section .foo.1a,"aMS",@progbits,1 .asciz "foo" Index: test/ELF/linkerscript/non-alloc.s =================================================================== --- test/ELF/linkerscript/non-alloc.s +++ test/ELF/linkerscript/non-alloc.s @@ -13,14 +13,16 @@ # CHECK-NEXT: PHDR # CHECK-NEXT: LOAD {{.*}} R # CHECK-NEXT: LOAD {{.*}} R E +# CHECK-NEXT: LOAD {{.*}} R # CHECK-NEXT: LOAD {{.*}} RW # CHECK: Section to Segment mapping: # CHECK-NEXT: Segment Sections... # CHECK-NEXT: 00 -# CHECK-NEXT: 01 .dynsym .hash .dynstr +# CHECK-NEXT: 01 # CHECK-NEXT: 02 .text -# CHECK-NEXT: 03 .dynamic +# CHECK-NEXT: 03 .dynsym .hash .dynstr +# CHECK-NEXT: 04 .dynamic nop .section foo Index: test/ELF/linkerscript/sections-constraint.s =================================================================== --- test/ELF/linkerscript/sections-constraint.s +++ test/ELF/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/sections-orphans.s =================================================================== --- test/ELF/linkerscript/sections-orphans.s +++ test/ELF/linkerscript/sections-orphans.s @@ -0,0 +1,51 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { \ +# RUN: .text : { *(.text) } \ +# RUN: .foo1 : { *(.foo1) } \ +# RUN: .bar1 : { *(.bar1) } \ +# RUN: .bss : { *(.bss) } } " > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -section-headers %t.out | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .text 00000001 0000000000000190 TEXT DATA +# CHECK-NEXT: 2 .foo1 00000004 0000000000000191 DATA +# CHECK-NEXT: 3 .foo2 00000004 0000000000000195 DATA +# CHECK-NEXT: 4 .foo3 00000004 0000000000000199 DATA +# CHECK-NEXT: 5 .bar1 00000004 000000000000019d DATA +# CHECK-NEXT: 6 .bar2 00000004 00000000000001a1 DATA +# CHECK-NEXT: 7 .bss 00000002 00000000000001a5 BSS +# CHECK-NEXT: 8 .symtab 000000a8 0000000000000000 +# CHECK-NEXT: 9 .shstrtab 00000044 0000000000000000 +# CHECK-NEXT: 10 .strtab 00000021 0000000000000000 + +.global _start +_start: + nop + +.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 + +.section .bss,"",@nobits +.short 0 Index: test/ELF/linkerscript/sections.s =================================================================== --- test/ELF/linkerscript/sections.s +++ test/ELF/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, other than alloc @@ -63,8 +63,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. @@ -100,8 +100,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/symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/symbols-synthetic.s +++ test/ELF/linkerscript/symbols-synthetic.s @@ -40,22 +40,22 @@ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t -# SIMPLE: 0000000000000160 .foo 00000000 .hidden _end_sec -# SIMPLE-NEXT: 0000000000000158 .foo 00000000 _begin_sec -# SIMPLE-NEXT: 0000000000000160 *ABS* 00000000 _end_sec_abs -# SIMPLE-NEXT: 0000000000001048 .text 00000000 _start -# SIMPLE-NEXT: 0000000000000158 .foo 00000000 begin_foo -# SIMPLE-NEXT: 0000000000000160 .foo 00000000 end_foo +# SIMPLE: 0000000000000198 .foo 00000000 .hidden _end_sec +# SIMPLE-NEXT: 0000000000000190 .foo 00000000 _begin_sec +# SIMPLE-NEXT: 0000000000000198 *ABS* 00000000 _end_sec_abs +# SIMPLE-NEXT: 0000000000001004 .text 00000000 _start +# SIMPLE-NEXT: 0000000000000190 .foo 00000000 begin_foo +# SIMPLE-NEXT: 0000000000000198 .foo 00000000 end_foo # SIMPLE-NEXT: 0000000000000008 .foo 00000000 size_foo_1 # SIMPLE-NEXT: 0000000000000008 *ABS* 00000000 size_foo_1_abs # SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar # SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar -# SIMPLE-NEXT: 0000000000000eac .foo 00000000 size_foo_2 -# SIMPLE-NEXT: 0000000000000eac *ABS* 00000000 size_foo_3 -# SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start -# SIMPLE-NEXT: 0000000000001010 *ABS* 00000000 __eh_frame_hdr_start2 -# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end -# SIMPLE-NEXT: 0000000000001020 *ABS* 00000000 __eh_frame_hdr_end2 +# SIMPLE-NEXT: 0000000000000e74 .foo 00000000 size_foo_2 +# SIMPLE-NEXT: 0000000000000e74 *ABS* 00000000 size_foo_3 +# SIMPLE-NEXT: 0000000000001038 .eh_frame_hdr 00000000 __eh_frame_hdr_start +# SIMPLE-NEXT: 0000000000001040 *ABS* 00000000 __eh_frame_hdr_start2 +# SIMPLE-NEXT: 000000000000104c .eh_frame_hdr 00000000 __eh_frame_hdr_end +# SIMPLE-NEXT: 0000000000001050 *ABS* 00000000 __eh_frame_hdr_end2 .global _start _start: Index: test/ELF/linkerscript/va.s =================================================================== --- test/ELF/linkerscript/va.s +++ test/ELF/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: