[ELF/LinkerScript] Support EXCLUDE_FILE inside KEEP.
Differential Revision: https://reviews.llvm.org/D22795
llvm-svn: 276825
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 2ca0fde..804d0c9 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -79,15 +79,15 @@
// input sections start with ".foo." or ".bar." should be added to
// ".text" section.
template <class ELFT>
-std::vector<std::pair<StringRef, ArrayRef<StringRef>>>
+std::vector<std::pair<StringRef, const InputSectionDescription *>>
LinkerScript<ELFT>::getSectionMap() {
- std::vector<std::pair<StringRef, ArrayRef<StringRef>>> Ret;
+ std::vector<std::pair<StringRef, const InputSectionDescription *>> Ret;
for (const std::unique_ptr<BaseCommand> &Base1 : Opt.Commands)
if (auto *Cmd1 = dyn_cast<OutputSectionCommand>(Base1.get()))
for (const std::unique_ptr<BaseCommand> &Base2 : Cmd1->Commands)
if (auto *Cmd2 = dyn_cast<InputSectionDescription>(Base2.get()))
- Ret.emplace_back(Cmd1->Name, Cmd2->Patterns);
+ Ret.emplace_back(Cmd1->Name, Cmd2);
return Ret;
}
@@ -95,13 +95,17 @@
// Returns input sections filtered by given glob patterns.
template <class ELFT>
std::vector<InputSectionBase<ELFT> *>
-LinkerScript<ELFT>::getInputSections(ArrayRef<StringRef> Patterns) {
+LinkerScript<ELFT>::getInputSections(const InputSectionDescription *I) {
+ ArrayRef<StringRef> Patterns = I->Patterns;
+ ArrayRef<StringRef> ExcludedFiles = I->ExcludedFiles;
std::vector<InputSectionBase<ELFT> *> Ret;
for (const std::unique_ptr<ObjectFile<ELFT>> &F :
Symtab<ELFT>::X->getObjectFiles())
for (InputSectionBase<ELFT> *S : F->getSections())
if (!isDiscarded(S) && !S->OutSec && match(Patterns, S->getSectionName()))
- Ret.push_back(S);
+ if (ExcludedFiles.empty() ||
+ !match(ExcludedFiles, sys::path::filename(F->getName())))
+ Ret.push_back(S);
return Ret;
}
@@ -123,8 +127,8 @@
for (auto &P : getSectionMap()) {
StringRef OutputName = P.first;
- ArrayRef<StringRef> InputPatterns = P.second;
- for (InputSectionBase<ELFT> *S : getInputSections(InputPatterns)) {
+ const InputSectionDescription *I = P.second;
+ for (InputSectionBase<ELFT> *S : getInputSections(I)) {
if (OutputName == "/DISCARD/") {
S->Live = false;
reportDiscarded(S);
@@ -420,6 +424,7 @@
void readAsNeeded();
void readEntry();
void readExtern();
+ std::unique_ptr<InputSectionDescription> readFilePattern();
void readGroup();
void readKeep(OutputSectionCommand *Cmd);
void readInclude();
@@ -662,16 +667,31 @@
.Default(-1);
}
-void ScriptParser::readKeep(OutputSectionCommand *Cmd) {
- expect("(");
+std::unique_ptr<InputSectionDescription> ScriptParser::readFilePattern() {
expect("*");
expect("(");
- auto *InCmd = new InputSectionDescription();
- Cmd->Commands.emplace_back(InCmd);
- while (!Error && !skip(")")) {
- Opt.KeptSections.push_back(peek());
+
+ auto InCmd = llvm::make_unique<InputSectionDescription>();
+
+ if (skip("EXCLUDE_FILE")) {
+ expect("(");
+ while (!Error && !skip(")"))
+ InCmd->ExcludedFiles.push_back(next());
InCmd->Patterns.push_back(next());
+ expect(")");
+ } else {
+ while (!Error && !skip(")"))
+ InCmd->Patterns.push_back(next());
}
+ return InCmd;
+}
+
+void ScriptParser::readKeep(OutputSectionCommand *Cmd) {
+ expect("(");
+ std::unique_ptr<InputSectionDescription> InCmd = readFilePattern();
+ Opt.KeptSections.insert(Opt.KeptSections.end(), InCmd->Patterns.begin(),
+ InCmd->Patterns.end());
+ Cmd->Commands.push_back(std::move(InCmd));
expect(")");
}