Recommit r281721 "[ELF] - Linkerscript: implement EXCLUDE_FILE in the middle of a input section description."
With fix for 2 bots. Details about the fix performed is on a review page.
Initial commit message:
This is PR30387:
From PR description:
We fail to parse
SECTIONS
{
foo :
{
*(sec0 EXCLUDE_FILE (zed1.o) sec1 EXCLUDE_FILE (zed2.o) sec2 )
}
}
The semantics according to bfd are:
Include sec1 from every file but zed1.o
Include sec2 from every file but zed2.o
Include sec0 from every file
Patch implements the support.
Differential revision: https://reviews.llvm.org/D24650
llvm-svn: 281754
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 175ec5f..d676d38 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -109,10 +109,10 @@
return false;
}
-static bool fileMatches(const InputSectionDescription *Desc,
- StringRef Filename) {
- return const_cast<Regex &>(Desc->FileRe).match(Filename) &&
- !const_cast<Regex &>(Desc->ExcludedFileRe).match(Filename);
+static bool fileMatches(const llvm::Regex &FileRe,
+ const llvm::Regex &ExcludedFileRe, StringRef Filename) {
+ return const_cast<Regex &>(FileRe).match(Filename) &&
+ !const_cast<Regex &>(ExcludedFileRe).match(Filename);
}
static bool comparePriority(InputSectionData *A, InputSectionData *B) {
@@ -161,16 +161,19 @@
template <class ELFT>
void LinkerScript<ELFT>::computeInputSections(InputSectionDescription *I,
ConstraintKind Constraint) {
- const Regex &Re = I->SectionRe;
- for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
- if (fileMatches(I, sys::path::filename(F->getName())))
- for (InputSectionBase<ELFT> *S : F->getSections())
- if (!isDiscarded(S) && !S->OutSec &&
- const_cast<Regex &>(Re).match(S->Name))
- I->Sections.push_back(S);
+ for (const std::pair<llvm::Regex, llvm::Regex> &V : I->SectionsVec) {
+ for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
+ if (fileMatches(I->FileRe, V.first, sys::path::filename(F->getName()))) {
+ Regex &Re = const_cast<Regex &>(V.second);
+ for (InputSectionBase<ELFT> *S : F->getSections())
+ if (!isDiscarded(S) && !S->OutSec && Re.match(S->Name))
+ I->Sections.push_back(S);
- if (const_cast<Regex &>(Re).match("COMMON"))
- I->Sections.push_back(CommonInputSection<ELFT>::X);
+ if (Re.match("COMMON"))
+ I->Sections.push_back(CommonInputSection<ELFT>::X);
+ }
+ }
+ }
if (!matchConstraints<ELFT>(I->Sections, Constraint)) {
I->Sections.clear();
@@ -698,6 +701,7 @@
std::vector<StringRef> readOutputSectionPhdrs();
InputSectionDescription *readInputSectionDescription(StringRef Tok);
Regex readFilePatterns();
+ void readSectionExcludes(InputSectionDescription *Cmd);
InputSectionDescription *readInputSectionRules(StringRef FilePattern);
unsigned readPhdrType();
SortKind readSortKind();
@@ -991,17 +995,41 @@
return SortNone;
}
+// Method reads a list of sequence of excluded files and section globs given in
+// a following form: ((EXCLUDE_FILE(file_pattern+))? section_pattern+)+
+// Example: *(.foo.1 EXCLUDE_FILE (*a.o) .foo.2 EXCLUDE_FILE (*b.o) .foo.3)
+void ScriptParser::readSectionExcludes(InputSectionDescription *Cmd) {
+ llvm::Regex ExcludeFileRe;
+ std::vector<StringRef> V;
+
+ while (!Error) {
+ if (skip(")")) {
+ Cmd->SectionsVec.push_back(
+ {std::move(ExcludeFileRe), compileGlobPatterns(V)});
+ return;
+ }
+
+ if (skip("EXCLUDE_FILE")) {
+ if (!V.empty()) {
+ Cmd->SectionsVec.push_back(
+ {std::move(ExcludeFileRe), compileGlobPatterns(V)});
+ V.clear();
+ }
+
+ expect("(");
+ ExcludeFileRe = readFilePatterns();
+ continue;
+ }
+
+ V.push_back(next());
+ }
+}
+
InputSectionDescription *
ScriptParser::readInputSectionRules(StringRef FilePattern) {
auto *Cmd = new InputSectionDescription(FilePattern);
expect("(");
- // Read EXCLUDE_FILE().
- if (skip("EXCLUDE_FILE")) {
- expect("(");
- Cmd->ExcludedFileRe = readFilePatterns();
- }
-
// Read SORT().
if (SortKind K1 = readSortKind()) {
Cmd->SortOuter = K1;
@@ -1009,16 +1037,16 @@
if (SortKind K2 = readSortKind()) {
Cmd->SortInner = K2;
expect("(");
- Cmd->SectionRe = readFilePatterns();
+ Cmd->SectionsVec.push_back({llvm::Regex(), readFilePatterns()});
expect(")");
} else {
- Cmd->SectionRe = readFilePatterns();
+ Cmd->SectionsVec.push_back({llvm::Regex(), readFilePatterns()});
}
expect(")");
return Cmd;
}
- Cmd->SectionRe = readFilePatterns();
+ readSectionExcludes(Cmd);
return Cmd;
}
@@ -1031,7 +1059,8 @@
StringRef FilePattern = next();
InputSectionDescription *Cmd = readInputSectionRules(FilePattern);
expect(")");
- Opt.KeptSections.push_back(&Cmd->SectionRe);
+ for (std::pair<llvm::Regex, llvm::Regex> &Regex : Cmd->SectionsVec)
+ Opt.KeptSections.push_back(&Regex.second);
return Cmd;
}
return readInputSectionRules(Tok);
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index d9fc117..159cac3 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -20,6 +20,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Regex.h"
#include <functional>
+#include <list>
namespace lld {
namespace elf {
@@ -106,8 +107,8 @@
llvm::Regex FileRe;
SortKind SortOuter = SortNone;
SortKind SortInner = SortNone;
- llvm::Regex ExcludedFileRe;
- llvm::Regex SectionRe;
+ // Pairs of section regex and files excluded.
+ std::list<std::pair<llvm::Regex, llvm::Regex>> SectionsVec;
std::vector<InputSectionData *> Sections;
};
diff --git a/lld/test/ELF/linkerscript/Inputs/exclude-multiple1.s b/lld/test/ELF/linkerscript/Inputs/exclude-multiple1.s
new file mode 100644
index 0000000..1e0f741
--- /dev/null
+++ b/lld/test/ELF/linkerscript/Inputs/exclude-multiple1.s
@@ -0,0 +1,8 @@
+.section .foo.1,"a"
+ .quad 4
+
+.section .foo.2,"a"
+ .quad 5
+
+.section .foo.3,"a"
+ .quad 6
diff --git a/lld/test/ELF/linkerscript/Inputs/exclude-multiple2.s b/lld/test/ELF/linkerscript/Inputs/exclude-multiple2.s
new file mode 100644
index 0000000..60f790f
--- /dev/null
+++ b/lld/test/ELF/linkerscript/Inputs/exclude-multiple2.s
@@ -0,0 +1,8 @@
+.section .foo.1,"a"
+ .quad 7
+
+.section .foo.2,"a"
+ .quad 8
+
+.section .foo.3,"a"
+ .quad 9
diff --git a/lld/test/ELF/linkerscript/exclude-multiple.s b/lld/test/ELF/linkerscript/exclude-multiple.s
new file mode 100644
index 0000000..24c7f2f
--- /dev/null
+++ b/lld/test/ELF/linkerscript/exclude-multiple.s
@@ -0,0 +1,28 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tfile1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/exclude-multiple1.s -o %tfile2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/exclude-multiple2.s -o %tfile3.o
+# RUN: echo "SECTIONS { \
+# RUN: .foo : { *(.foo.1 EXCLUDE_FILE (*file1.o) .foo.2 EXCLUDE_FILE (*file2.o) .foo.3) } \
+# RUN: }" > %t1.script
+# RUN: ld.lld -script %t1.script %tfile1.o %tfile2.o %tfile3.o -o %t1.o
+# RUN: llvm-objdump -s %t1.o | FileCheck %s
+
+# CHECK: Contents of section .foo:
+# CHECK-NEXT: 0120 01000000 00000000 04000000 00000000
+# CHECK-NEXT: 0130 07000000 00000000 05000000 00000000
+# CHECK-NEXT: 0140 08000000 00000000 03000000 00000000
+# CHECK-NEXT: 0150 09000000 00000000
+# CHECK-NEXT: Contents of section .foo.2:
+# CHECK-NEXT: 0158 02000000 00000000
+# CHECK-NEXT: Contents of section .foo.3:
+# CHECK-NEXT: 0160 06000000 00000000
+
+.section .foo.1,"a"
+ .quad 1
+
+.section .foo.2,"a"
+ .quad 2
+
+.section .foo.3,"a"
+ .quad 3