diff options
author | George Rimar <grimar@accesssoftek.com> | 2016-08-12 09:07:57 +0000 |
---|---|---|
committer | George Rimar <grimar@accesssoftek.com> | 2016-08-12 09:07:57 +0000 |
commit | 06ae68362060928fdc391bea8061cf9d8dc622eb (patch) | |
tree | e9290d7116ede30f835e9d5017ff216cb759b325 | |
parent | bbff9c6130ed0b3f16e6f78d703c3191d5331808 (diff) | |
download | bcm5719-llvm-06ae68362060928fdc391bea8061cf9d8dc622eb.tar.gz bcm5719-llvm-06ae68362060928fdc391bea8061cf9d8dc622eb.zip |
[ELF] - Linkerscript: reimplemented output sections constrains matching functionality.
Previously filtering that was used worked incorrectly.
For example for next script it would just remove both sections completely:
SECTIONS {
. = 0x1000;
.aaa : ONLY_IF_RW { *(.aaa.*) }
. = 0x2000;
.aaa : ONLY_IF_RO { *(.aaa.*) }
}
Patch fixes above issues and adds testcase showing the issue. Testcase is a subset of
FreeBSD script which has:
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
...
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
Differential revision: https://reviews.llvm.org/D23326
llvm-svn: 278486
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 57 | ||||
-rw-r--r-- | lld/ELF/LinkerScript.h | 2 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/linkerscript-multi-sections-constraint.s | 26 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/linkerscript-sections-constraint.s | 30 |
4 files changed, 59 insertions, 56 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 64918d79c55..1c24614ce88 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -216,20 +216,33 @@ void LinkerScript<ELFT>::discard(OutputSectionCommand &Cmd) { } template <class ELFT> +static bool matchConstraints(ArrayRef<InputSectionBase<ELFT> *> Sections, + ConstraintKind Kind) { + bool RO = (Kind == ConstraintKind::ReadOnly); + bool RW = (Kind == ConstraintKind::ReadWrite); + return !llvm::any_of(Sections, [=](InputSectionBase<ELFT> *Sec) { + bool Writable = Sec->getSectionHdr()->sh_flags & SHF_WRITE; + return (RO && Writable) || (RW && !Writable); + }); +} + +template <class ELFT> std::vector<InputSectionBase<ELFT> *> -LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &Cmd) { +LinkerScript<ELFT>::createInputSectionList(OutputSectionCommand &OutCmd) { std::vector<InputSectionBase<ELFT> *> Ret; - for (const std::unique_ptr<BaseCommand> &Base : Cmd.Commands) { - if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) { - if (shouldDefine<ELFT>(Cmd)) - addSynthetic<ELFT>(Cmd); - Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(Cmd)); + for (const std::unique_ptr<BaseCommand> &Base : OutCmd.Commands) { + if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base.get())) { + if (shouldDefine<ELFT>(OutCmd)) + addSynthetic<ELFT>(OutCmd); + Ret.push_back(new (LAlloc.Allocate()) LayoutInputSection<ELFT>(OutCmd)); continue; } auto *Cmd = cast<InputSectionDescription>(Base.get()); std::vector<InputSectionBase<ELFT> *> V = getInputSections(Cmd); + if (!matchConstraints<ELFT>(V, OutCmd.Constraint)) + continue; if (Cmd->SortInner) std::stable_sort(V.begin(), V.end(), getComparator<ELFT>(Cmd->SortInner)); if (Cmd->SortOuter) @@ -283,38 +296,6 @@ void LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) { OutSec->addSection(S); } } - - // Remove from the output all the sections which did not meet - // the optional constraints. - filter(); -} - -template <class R, class T> -static inline void removeElementsIf(R &Range, const T &Pred) { - Range.erase(std::remove_if(Range.begin(), Range.end(), Pred), Range.end()); -} - -// Process ONLY_IF_RO and ONLY_IF_RW. -template <class ELFT> void LinkerScript<ELFT>::filter() { - // In this loop, we remove output sections if they don't satisfy - // requested properties. - for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) { - auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get()); - if (!Cmd || Cmd->Name == "/DISCARD/") - continue; - - if (Cmd->Constraint == ConstraintKind::NoConstraint) - continue; - - bool RO = (Cmd->Constraint == ConstraintKind::ReadOnly); - bool RW = (Cmd->Constraint == ConstraintKind::ReadWrite); - - removeElementsIf(*OutputSections, [&](OutputSectionBase<ELFT> *S) { - bool Writable = (S->getFlags() & SHF_WRITE); - return S->getName() == Cmd->Name && - ((RO && Writable) || (RW && !Writable)); - }); - } } template <class ELFT> void assignOffsets(OutputSectionBase<ELFT> *Sec) { diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index ecf9f5c2985..53a6db5632a 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -167,8 +167,6 @@ private: // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; - void filter(); - int getSectionIndex(StringRef Name); std::vector<size_t> getPhdrIndices(StringRef SectionName); size_t getPhdrIndex(StringRef PhdrName); diff --git a/lld/test/ELF/linkerscript/linkerscript-multi-sections-constraint.s b/lld/test/ELF/linkerscript/linkerscript-multi-sections-constraint.s new file mode 100644 index 00000000000..c9d09438f80 --- /dev/null +++ b/lld/test/ELF/linkerscript/linkerscript-multi-sections-constraint.s @@ -0,0 +1,26 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: echo "SECTIONS { \ +# RUN: . = 0x1000; .aaa : ONLY_IF_RO { *(.aaa.*) } \ +# RUN: . = 0x2000; .aaa : ONLY_IF_RW { *(.aaa.*) } } " > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-objdump -section-headers %t1 | FileCheck %s + +# CHECK: Sections: +# CHECK-NEXT: Idx Name Size Address Type +# CHECK-NEXT: 0 00000000 0000000000000000 +# CHECK-NEXT: 1 .aaa 00000010 0000000000002000 DATA +# CHECK-NEXT: 2 .text 00000001 0000000000002010 TEXT DATA +# CHECK-NEXT: 3 .symtab 00000030 0000000000000000 +# CHECK-NEXT: 4 .shstrtab 00000026 0000000000000000 +# CHECK-NEXT: 5 .strtab 00000008 0000000000000000 + +.global _start +_start: + nop + +.section .aaa.1, "aw" +.quad 1 + +.section .aaa.2, "aw" +.quad 1 diff --git a/lld/test/ELF/linkerscript/linkerscript-sections-constraint.s b/lld/test/ELF/linkerscript/linkerscript-sections-constraint.s index cceba92adcc..75c192c32a5 100644 --- a/lld/test/ELF/linkerscript/linkerscript-sections-constraint.s +++ b/lld/test/ELF/linkerscript/linkerscript-sections-constraint.s @@ -13,22 +13,20 @@ # BASE-NEXT: 2 .readable 00000004 0000000000000204 DATA # RUN: echo "SECTIONS { \ -# RUN: .writable : ONLY_IF_RO { *(.writable) } \ -# RUN: .readable : ONLY_IF_RW { *(.readable) }}" > %t.script -# RUN: ld.lld -o %t1 --script %t.script %t -# RUN: llvm-objdump -section-headers %t1 | \ -# RUN: FileCheck -check-prefix=NOSECTIONS %s -# NOSECTIONS: Sections: -# NOSECTIONS-NOT: .writable -# NOSECTIONS-NOT: .readable - -# RUN: echo "SECTIONS { \ -# RUN: .foo : ONLY_IF_RO { *(.foo.*) }}" > %t.script -# RUN: ld.lld -o %t1 --script %t.script %t -# RUN: llvm-objdump -section-headers %t1 | \ -# RUN: FileCheck -check-prefix=NOSECTIONS2 %s -# NOSECTIONS2: Sections: -# NOSECTIONS2-NOT: .foo +# RUN: .foo : ONLY_IF_RO { *(.foo.*) } \ +# RUN: .writable : ONLY_IF_RW { *(.writable) } \ +# RUN: .readable : ONLY_IF_RO { *(.readable) }}" > %t2.script +# RUN: ld.lld -o %t2 --script %t2.script %t +# RUN: llvm-objdump -section-headers %t2 | \ +# RUN: FileCheck -check-prefix=NO1 %s +# 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 .global _start _start: |