forked from OSchip/llvm-project
[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
This commit is contained in:
parent
bbff9c6130
commit
06ae683620
|
@ -215,21 +215,34 @@ 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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue