[lld] r282078 - [ELF] - Linkerscript: support complex section pattern grammar.
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 21 08:56:44 PDT 2016
Author: grimar
Date: Wed Sep 21 10:56:44 2016
New Revision: 282078
URL: http://llvm.org/viewvc/llvm-project?rev=282078&view=rev
Log:
[ELF] - Linkerscript: support complex section pattern grammar.
This is PR30442.
Previously we were failed to parce complex expressions like:
foo : { *(SORT_BY_NAME(bar) zed) }
Main idea of patch that globs and excludes can be wrapped in a SORT.
There is a difference in semanics of ld/gold:
ld likes:
*(SORT(EXCLUDE_FILE (*file1.o) .foo.1))
gold likes:
*(EXCLUDE_FILE (*file1.o) SORT(.foo.1))
Patch implements ld grammar, complex expressions like
next is not a problem anymore:
.abc : { *(SORT(.foo.* EXCLUDE_FILE (*file1.o) .bar.*) .bar.*) }
Differential revision: https://reviews.llvm.org/D24758
Added:
lld/trunk/test/ELF/linkerscript/sort2.s
Modified:
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/LinkerScript.h
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=282078&r1=282077&r2=282078&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Wed Sep 21 10:56:44 2016
@@ -156,10 +156,10 @@ static bool matchConstraints(ArrayRef<In
});
}
-static void sortSections(std::vector<InputSectionData *> &Sections,
+static void sortSections(InputSectionData **Begin, InputSectionData **End,
SortSectionPolicy K) {
if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None)
- std::stable_sort(Sections.begin(), Sections.end(), getComparator(K));
+ std::stable_sort(Begin, End, getComparator(K));
}
// Compute and remember which sections the InputSectionDescription matches.
@@ -168,6 +168,7 @@ void LinkerScript<ELFT>::computeInputSec
// Collects all sections that satisfy constraints of I
// and attach them to I.
for (SectionPattern &Pat : I->SectionPatterns) {
+ size_t SizeBefore = I->Sections.size();
for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
StringRef Filename = sys::path::filename(F->getName());
if (!I->FileRe.match(Filename) || Pat.ExcludedFileRe.match(Filename))
@@ -179,25 +180,27 @@ void LinkerScript<ELFT>::computeInputSec
if (Pat.SectionRe.match("COMMON"))
I->Sections.push_back(CommonInputSection<ELFT>::X);
}
- }
- // Sort sections as instructed by SORT-family commands and --sort-section
- // option. Because SORT-family commands can be nested at most two depth
- // (e.g. SORT_BY_NAME(SORT_BY_ALIGNMENT(.text.*))) and because the command
- // line option is respected even if a SORT command is given, the exact
- // behavior we have here is a bit complicated. Here are the rules.
- //
- // 1. If two SORT commands are given, --sort-section is ignored.
- // 2. If one SORT command is given, and if it is not SORT_NONE,
- // --sort-section is handled as an inner SORT command.
- // 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
- // 4. If no SORT command is given, sort according to --sort-section.
- if (I->SortOuter != SortSectionPolicy::None) {
- if (I->SortInner == SortSectionPolicy::Default)
- sortSections(I->Sections, Config->SortSection);
- else
- sortSections(I->Sections, I->SortInner);
- sortSections(I->Sections, I->SortOuter);
+ // Sort sections as instructed by SORT-family commands and --sort-section
+ // option. Because SORT-family commands can be nested at most two depth
+ // (e.g. SORT_BY_NAME(SORT_BY_ALIGNMENT(.text.*))) and because the command
+ // line option is respected even if a SORT command is given, the exact
+ // behavior we have here is a bit complicated. Here are the rules.
+ //
+ // 1. If two SORT commands are given, --sort-section is ignored.
+ // 2. If one SORT command is given, and if it is not SORT_NONE,
+ // --sort-section is handled as an inner SORT command.
+ // 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
+ // 4. If no SORT command is given, sort according to --sort-section.
+ InputSectionData **Begin = I->Sections.data() + SizeBefore;
+ InputSectionData **End = I->Sections.data() + I->Sections.size();
+ if (Pat.SortOuter != SortSectionPolicy::None) {
+ if (Pat.SortInner == SortSectionPolicy::Default)
+ sortSections(Begin, End, Config->SortSection);
+ else
+ sortSections(Begin, End, Pat.SortInner);
+ sortSections(Begin, End, Pat.SortOuter);
+ }
}
// We do not add duplicate input sections, so mark them with a dummy output
@@ -769,7 +772,7 @@ private:
std::vector<StringRef> readOutputSectionPhdrs();
InputSectionDescription *readInputSectionDescription(StringRef Tok);
Regex readFilePatterns();
- void readSectionExcludes(InputSectionDescription *Cmd);
+ std::vector<SectionPattern> readInputSectionsList();
InputSectionDescription *readInputSectionRules(StringRef FilePattern);
unsigned readPhdrType();
SortSectionPolicy readSortKind();
@@ -1072,7 +1075,8 @@ SortSectionPolicy ScriptParser::readSort
// * Include .foo.1 from every file.
// * Include .foo.2 from every file but a.o
// * Include .foo.3 from every file but b.o
-void ScriptParser::readSectionExcludes(InputSectionDescription *Cmd) {
+std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
+ std::vector<SectionPattern> Ret;
while (!Error && peek() != ")") {
Regex ExcludeFileRe;
if (skip("EXCLUDE_FILE")) {
@@ -1085,38 +1089,49 @@ void ScriptParser::readSectionExcludes(I
V.push_back(next());
if (!V.empty())
- Cmd->SectionPatterns.push_back(
- {std::move(ExcludeFileRe), compileGlobPatterns(V)});
+ Ret.push_back({std::move(ExcludeFileRe), compileGlobPatterns(V)});
else
setError("section pattern is expected");
}
- expect(")");
+ return Ret;
}
+// Section pattern grammar can have complex expressions, for example:
+// *(SORT(.foo.* EXCLUDE_FILE (*file1.o) .bar.*) .bar.* SORT(.zed.*))
+// Generally is a sequence of globs and excludes that may be wrapped in a SORT()
+// commands, like: SORT(glob0) glob1 glob2 SORT(glob4)
+// This methods handles wrapping sequences of excluded files and section globs
+// into SORT() if that needed and reads them all.
InputSectionDescription *
ScriptParser::readInputSectionRules(StringRef FilePattern) {
auto *Cmd = new InputSectionDescription(FilePattern);
expect("(");
-
- // Read SORT().
- SortSectionPolicy K1 = readSortKind();
- if (K1 != SortSectionPolicy::Default) {
- Cmd->SortOuter = K1;
- expect("(");
- SortSectionPolicy K2 = readSortKind();
- if (K2 != SortSectionPolicy::Default) {
- Cmd->SortInner = K2;
+ while (!HasError && !skip(")")) {
+ SortSectionPolicy Outer = readSortKind();
+ SortSectionPolicy Inner = SortSectionPolicy::Default;
+ std::vector<SectionPattern> V;
+ if (Outer != SortSectionPolicy::Default) {
expect("(");
- Cmd->SectionPatterns.push_back({Regex(), readFilePatterns()});
+ Inner = readSortKind();
+ if (Inner != SortSectionPolicy::Default) {
+ expect("(");
+ V = readInputSectionsList();
+ expect(")");
+ } else {
+ V = readInputSectionsList();
+ }
expect(")");
} else {
- Cmd->SectionPatterns.push_back({Regex(), readFilePatterns()});
+ V = readInputSectionsList();
}
- expect(")");
- return Cmd;
- }
- readSectionExcludes(Cmd);
+ for (SectionPattern &Pat : V) {
+ Pat.SortInner = Inner;
+ Pat.SortOuter = Outer;
+ }
+
+ std::move(V.begin(), V.end(), std::back_inserter(Cmd->SectionPatterns));
+ }
return Cmd;
}
Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=282078&r1=282077&r2=282078&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Wed Sep 21 10:56:44 2016
@@ -99,6 +99,7 @@ struct OutputSectionCommand : BaseComman
// This struct represents one section match pattern in SECTIONS() command.
// It can optionally have negative match pattern for EXCLUDED_FILE command.
+// Also it may be surrounded with SORT() command, so contains sorting rules.
struct SectionPattern {
SectionPattern(llvm::Regex &&Re1, llvm::Regex &&Re2)
: ExcludedFileRe(std::forward<llvm::Regex>(Re1)),
@@ -107,10 +108,14 @@ struct SectionPattern {
SectionPattern(SectionPattern &&Other) {
std::swap(ExcludedFileRe, Other.ExcludedFileRe);
std::swap(SectionRe, Other.SectionRe);
+ std::swap(SortOuter, Other.SortOuter);
+ std::swap(SortInner, Other.SortInner);
}
llvm::Regex ExcludedFileRe;
llvm::Regex SectionRe;
+ SortSectionPolicy SortOuter;
+ SortSectionPolicy SortInner;
};
struct InputSectionDescription : BaseCommand {
@@ -119,8 +124,6 @@ struct InputSectionDescription : BaseCom
FileRe(compileGlobPatterns({FilePattern})) {}
static bool classof(const BaseCommand *C);
llvm::Regex FileRe;
- SortSectionPolicy SortOuter = SortSectionPolicy::Default;
- SortSectionPolicy SortInner = SortSectionPolicy::Default;
// Input sections that matches at least one of SectionPatterns
// will be associated with this InputSectionDescription.
Added: lld/trunk/test/ELF/linkerscript/sort2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/sort2.s?rev=282078&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/sort2.s (added)
+++ lld/trunk/test/ELF/linkerscript/sort2.s Wed Sep 21 10:56:44 2016
@@ -0,0 +1,39 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile1.o
+
+# RUN: echo "SECTIONS { .abc : { *(SORT(.foo.*) .bar.*) } }" > %t1.script
+# RUN: ld.lld -o %t1 --script %t1.script %tfile1.o
+# RUN: llvm-objdump -s %t1 | FileCheck %s
+
+# CHECK: Contents of section .abc:
+# CHECK: 00e8 01000000 00000000 02000000 00000000
+# CHECK: 00f8 03000000 00000000 04000000 00000000
+# CHECK: 0108 06000000 00000000 05000000 00000000
+
+# RUN: echo "SECTIONS { \
+# RUN: .abc : { *(SORT(.foo.* EXCLUDE_FILE (*file1.o) .bar.*) .bar.*) } \
+# RUN: }" > %t2.script
+# RUN: ld.lld -o %t2 --script %t2.script %tfile1.o
+# RUN: llvm-objdump -s %t2 | FileCheck %s
+
+.text
+.globl _start
+_start:
+
+.section .foo.2,"a"
+ .quad 2
+
+.section .foo.3,"a"
+ .quad 3
+
+.section .foo.1,"a"
+ .quad 1
+
+.section .bar.4,"a"
+ .quad 4
+
+.section .bar.6,"a"
+ .quad 6
+
+.section .bar.5,"a"
+ .quad 5
More information about the llvm-commits
mailing list