From a14b13d86767703cfd0b9cce3ca5edd157ad28fd Mon Sep 17 00:00:00 2001 From: George Rimar Date: Wed, 7 Sep 2016 10:46:07 +0000 Subject: [PATCH] [ELF] - Linkerscript: create multiple output sections for inputs with different attributes. Previously we combined sections by name if linkerscript was used. For that we had to disable SHF_MERGE handling temporarily, but then found that implementing it properly will require additional complexity layers like subsections or something. At the same time looks we can live with multiple output sections approach for now. That patch do this change. Differential revision: https://reviews.llvm.org/D24127 llvm-svn: 280801 --- lld/ELF/LinkerScript.cpp | 80 +++++++++++++++--------------- lld/test/ELF/linkerscript/merge-sections.s | 28 ----------- lld/test/ELF/linkerscript/phdrs.s | 3 +- lld/test/ELF/linkerscript/repsection-va.s | 5 +- 4 files changed, 45 insertions(+), 71 deletions(-) delete mode 100644 lld/test/ELF/linkerscript/merge-sections.s diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 8e0016a..a6fbe64 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -242,14 +242,15 @@ void LinkerScript::createSections(OutputSectionFactory &Factory) { if (V.empty()) continue; - OutputSectionBase *OutSec; - bool IsNew; - std::tie(OutSec, IsNew) = Factory.create(V.front(), Cmd->Name); - if (IsNew) - OutputSections->push_back(OutSec); - - uint32_t Subalign = Cmd->SubalignExpr ? Cmd->SubalignExpr(0) : 0; for (InputSectionBase *Sec : V) { + OutputSectionBase *OutSec; + bool IsNew; + std::tie(OutSec, IsNew) = Factory.create(Sec, Cmd->Name); + if (IsNew) + OutputSections->push_back(OutSec); + + uint32_t Subalign = Cmd->SubalignExpr ? Cmd->SubalignExpr(0) : 0; + if (Subalign) Sec->Alignment = Subalign; OutSec->addSection(Sec); @@ -368,16 +369,15 @@ void assignOffsets(OutputSectionCommand *Cmd, OutputSectionBase *Sec) { } template -static OutputSectionBase * -findSection(OutputSectionCommand &Cmd, - ArrayRef *> Sections) { - for (OutputSectionBase *Sec : Sections) { - if (Sec->getName() != Cmd.Name) - continue; - if (checkConstraint(Sec->getFlags(), Cmd.Constraint)) - return Sec; - } - return nullptr; +static std::vector *> +findSections(OutputSectionCommand &Cmd, + ArrayRef *> Sections) { + std::vector *> Ret; + for (OutputSectionBase *Sec : Sections) + if (Sec->getName() == Cmd.Name && + checkConstraint(Sec->getFlags(), Cmd.Constraint)) + Ret.push_back(Sec); + return Ret; } template void LinkerScript::assignAddresses() { @@ -413,35 +413,35 @@ template void LinkerScript::assignAddresses() { } auto *Cmd = cast(Base.get()); - OutputSectionBase *Sec = findSection(*Cmd, *OutputSections); - if (!Sec) - continue; + for (OutputSectionBase *Sec : + findSections(*Cmd, *OutputSections)) { - if (Cmd->AddrExpr) - Dot = Cmd->AddrExpr(Dot); + if (Cmd->AddrExpr) + Dot = Cmd->AddrExpr(Dot); - if (Cmd->AlignExpr) - Sec->updateAlignment(Cmd->AlignExpr(Dot)); + if (Cmd->AlignExpr) + Sec->updateAlignment(Cmd->AlignExpr(Dot)); - if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { - uintX_t TVA = Dot + ThreadBssOffset; - TVA = alignTo(TVA, Sec->getAlignment()); - Sec->setVA(TVA); - assignOffsets(Cmd, Sec); - ThreadBssOffset = TVA - Dot + Sec->getSize(); - continue; - } + if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) { + uintX_t TVA = Dot + ThreadBssOffset; + TVA = alignTo(TVA, Sec->getAlignment()); + Sec->setVA(TVA); + assignOffsets(Cmd, Sec); + ThreadBssOffset = TVA - Dot + Sec->getSize(); + continue; + } - if (!(Sec->getFlags() & SHF_ALLOC)) { + if (!(Sec->getFlags() & SHF_ALLOC)) { + assignOffsets(Cmd, Sec); + continue; + } + + Dot = alignTo(Dot, Sec->getAlignment()); + Sec->setVA(Dot); assignOffsets(Cmd, Sec); - continue; + MinVA = std::min(MinVA, Dot); + Dot += Sec->getSize(); } - - Dot = alignTo(Dot, Sec->getAlignment()); - Sec->setVA(Dot); - assignOffsets(Cmd, Sec); - MinVA = std::min(MinVA, Dot); - Dot += Sec->getSize(); } // ELF and Program headers need to be right before the first section in diff --git a/lld/test/ELF/linkerscript/merge-sections.s b/lld/test/ELF/linkerscript/merge-sections.s deleted file mode 100644 index bb3849a..0000000 --- a/lld/test/ELF/linkerscript/merge-sections.s +++ /dev/null @@ -1,28 +0,0 @@ -# REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t - -# RUN: echo "SECTIONS { .foo : { *(.foo.*) } }" > %t.script -# RUN: ld.lld -o %t1 --script %t.script %t -# RUN: llvm-objdump -s %t1 | FileCheck %s -# CHECK: Contents of section .foo: -# CHECK-NEXT: 0158 01000000 02000000 00000000 73686f72 ............shor -# CHECK-NEXT: 0168 7420756e 7369676e 65642069 6e7400 t unsigned int. - -.global _start -_start: - nop - -.section .foo.1, "aw" -writable: - .long 1 - -.section .foo.2, "aM",@progbits,1 -readable: - .long 2 - -.section .foo.3, "awx" - .long 0 - -.section .foo.4, "MS",@progbits,1 -.LASF2: - .string "short unsigned int" diff --git a/lld/test/ELF/linkerscript/phdrs.s b/lld/test/ELF/linkerscript/phdrs.s index 775e002..cd6bf82 100644 --- a/lld/test/ELF/linkerscript/phdrs.s +++ b/lld/test/ELF/linkerscript/phdrs.s @@ -17,8 +17,9 @@ # CHECK-NEXT: PhysicalAddress: 0x10000000 # CHECK-NEXT: FileSize: 521 # CHECK-NEXT: MemSize: 521 -# CHECK-NEXT: Flags [ (0x5) +# CHECK-NEXT: Flags [ (0x7) # CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) # CHECK-NEXT: PF_X (0x1) # CHECK-NEXT: ] diff --git a/lld/test/ELF/linkerscript/repsection-va.s b/lld/test/ELF/linkerscript/repsection-va.s index 29ecdf8..4feeaa0 100644 --- a/lld/test/ELF/linkerscript/repsection-va.s +++ b/lld/test/ELF/linkerscript/repsection-va.s @@ -7,8 +7,9 @@ # CHECK: Sections: # CHECK-NEXT: Idx Name Size Address Type # CHECK-NEXT: 0 00000000 0000000000000000 -# CHECK-NEXT: 1 .foo 00000008 0000000000000120 DATA -# CHECK-NEXT: 2 .text 00000001 0000000000000128 TEXT DATA +# CHECK-NEXT: 1 .foo 00000004 0000000000000158 DATA +# CHECK-NEXT: 2 .foo 00000004 000000000000015c DATA +# CHECK-NEXT: 3 .text 00000001 0000000000000160 TEXT DATA .global _start _start: -- 2.7.4