Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -91,6 +91,7 @@ std::vector Phdrs; std::vector Filler; ConstraintKind Constraint = ConstraintKind::NoConstraint; + void *OutputSection = nullptr; }; enum SortKind { SortNone, SortByName, SortByAlignment }; @@ -176,6 +177,10 @@ std::vector *> createInputSectionList(OutputSectionCommand &Cmd); + OutputSectionBase *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 @@ -218,6 +218,57 @@ } template +static typename ELFT::uint getPermissions(OutputSectionBase *Sec) { + return Sec->getFlags() & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR); +} + +template +static OutputSectionBase * +getOutputSection(const std::unique_ptr &Base) { + if (auto *Cmd = dyn_cast(Base.get())) + if (Cmd->OutputSection) + return reinterpret_cast *>(Cmd->OutputSection); + return nullptr; +} + +// 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. +template +OutputSectionBase * +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 OutSec; + + auto R = std::find_if( + ScriptConfig->Commands.rbegin(), ScriptConfig->Commands.rend(), + [&](std::unique_ptr &Base) { + OutputSectionBase *S = getOutputSection(Base); + if (!S || S->getType() == SHT_NOBITS) + return false; + return getPermissions(S) == getPermissions(OutSec); + }); + + // We want to place orphan section somewhere. Default position (in the case + // if we did not find some section with the same flags) is end. + // Otherwise we just add orphan section after the last section + // with the same attributes we found earlier. + auto Pos = R != ScriptConfig->Commands.rend() ? R.base() + : ScriptConfig->Commands.end(); + OutputSectionCommand* OutSecCmd = new OutputSectionCommand(OutputName); + OutSecCmd->OutputSection = OutSec; + ScriptConfig->Commands.emplace(Pos, OutSecCmd); + + return OutSec; +} + +template void LinkerScript::createSections(OutputSectionFactory &Factory) { for (const std::unique_ptr &Base1 : Opt.Commands) { if (auto *Cmd = dyn_cast(Base1.get())) { @@ -240,7 +291,7 @@ bool IsNew; std::tie(OutSec, IsNew) = Factory.create(V.front(), Cmd->Name); if (IsNew) - OutputSections->push_back(OutSec); + Cmd->OutputSection = OutSec; uint32_t Subalign = Cmd->SubalignExpr ? Cmd->SubalignExpr(0) : 0; for (InputSectionBase *Sec : V) { @@ -253,18 +304,15 @@ // 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); - } - } + Symtab::X->getObjectFiles()) + for (InputSectionBase *S : F->getSections()) + if (!isDiscarded(S) && !S->OutSec) + addOrphan(Factory, getOutputSectionName(S), S); + + // Add created output sections to the OutputSections list. + for (const std::unique_ptr &Base : Opt.Commands) + if (OutputSectionBase *S = getOutputSection(Base)) + OutputSections->push_back(S); } // Linker script may define start and end symbols for special section types, 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.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. @@ -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/symbols-synthetic.s =================================================================== --- test/ELF/linkerscript/symbols-synthetic.s +++ test/ELF/linkerscript/symbols-synthetic.s @@ -50,19 +50,19 @@ # RUN: }" > %t.script # RUN: ld.lld -o %t1 --eh-frame-hdr --script %t.script %t -# SIMPLE: 0000000000000160 .foo 00000000 .hidden _end_sec -# SIMPLE: 0000000000000158 .foo 00000000 _begin_sec -# SIMPLE-NEXT: 0000000000000158 .foo 00000000 begin_foo -# SIMPLE-NEXT: 0000000000000160 .foo 00000000 end_foo -# SIMPLE-NEXT: 0000000000000008 .foo 00000000 size_foo_1 -# 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 .eh_frame_hdr 00000000 __eh_frame_hdr_start2 -# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end -# SIMPLE-NEXT: 0000000000001020 .eh_frame_hdr 00000000 __eh_frame_hdr_end2 +# SIMPLE: 0000000000000198 .foo 00000000 .hidden _end_sec +# SIMPLE: 0000000000000190 .foo 00000000 _begin_sec +# SIMPLE-NEXT: 0000000000000190 .foo 00000000 begin_foo +# SIMPLE-NEXT: 0000000000000198 .foo 00000000 end_foo +# SIMPLE-NEXT: 0000000000000008 .foo 00000000 size_foo_1 +# SIMPLE-NEXT: 0000000000001000 .foo 00000000 begin_bar +# SIMPLE-NEXT: 0000000000001004 .foo 00000000 end_bar +# SIMPLE-NEXT: 0000000000000e74 .foo 00000000 size_foo_2 +# SIMPLE-NEXT: 0000000000000e74 *ABS* 00000000 size_foo_3 +# SIMPLE-NEXT: 0000000000001004 .eh_frame_hdr 00000000 __eh_frame_hdr_start +# SIMPLE-NEXT: 0000000000001010 .eh_frame_hdr 00000000 __eh_frame_hdr_start2 +# SIMPLE-NEXT: 0000000000001018 .eh_frame_hdr 00000000 __eh_frame_hdr_end +# SIMPLE-NEXT: 0000000000001020 .eh_frame_hdr 00000000 __eh_frame_hdr_end2 # ERROR: section '.eh_frame_hdr' supports only start and end symbols .global _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: