diff options
| -rw-r--r-- | lld/ELF/LinkerScript.cpp | 46 | ||||
| -rw-r--r-- | lld/ELF/LinkerScript.h | 6 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/Inputs/include.s | 5 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/Inputs/notinclude.s | 4 | ||||
| -rw-r--r-- | lld/test/ELF/linkerscript/linkerscript-excludefile.s | 48 |
5 files changed, 94 insertions, 15 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 2ca0fde46df..804d0c94e12 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -79,15 +79,15 @@ static bool match(ArrayRef<StringRef> Patterns, StringRef S) { // 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 @@ LinkerScript<ELFT>::getSectionMap() { // 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 @@ LinkerScript<ELFT>::createSections(OutputSectionFactory<ELFT> &Factory) { 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 @@ private: void readAsNeeded(); void readEntry(); void readExtern(); + std::unique_ptr<InputSectionDescription> readFilePattern(); void readGroup(); void readKeep(OutputSectionCommand *Cmd); void readInclude(); @@ -662,16 +667,31 @@ static int precedence(StringRef Op) { .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(")"); } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 4088cdf6a11..db9559bd0de 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -83,6 +83,7 @@ struct OutputSectionCommand : BaseCommand { struct InputSectionDescription : BaseCommand { InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); + std::vector<StringRef> ExcludedFiles; std::vector<StringRef> Patterns; }; @@ -132,10 +133,11 @@ public: bool hasPhdrsCommands(); private: - std::vector<std::pair<StringRef, ArrayRef<StringRef>>> getSectionMap(); + std::vector<std::pair<StringRef, const InputSectionDescription *>> + getSectionMap(); std::vector<InputSectionBase<ELFT> *> - getInputSections(ArrayRef<StringRef> Patterns); + getInputSections(const InputSectionDescription *); // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; diff --git a/lld/test/ELF/linkerscript/Inputs/include.s b/lld/test/ELF/linkerscript/Inputs/include.s new file mode 100644 index 00000000000..a2f809b522f --- /dev/null +++ b/lld/test/ELF/linkerscript/Inputs/include.s @@ -0,0 +1,5 @@ +.section .text +.globl _potato +_potato: + nop + nop diff --git a/lld/test/ELF/linkerscript/Inputs/notinclude.s b/lld/test/ELF/linkerscript/Inputs/notinclude.s new file mode 100644 index 00000000000..46c0509b56c --- /dev/null +++ b/lld/test/ELF/linkerscript/Inputs/notinclude.s @@ -0,0 +1,4 @@ +.section .text +.globl tomato +tomato: + movl $1, %eax diff --git a/lld/test/ELF/linkerscript/linkerscript-excludefile.s b/lld/test/ELF/linkerscript/linkerscript-excludefile.s new file mode 100644 index 00000000000..7768442c87d --- /dev/null +++ b/lld/test/ELF/linkerscript/linkerscript-excludefile.s @@ -0,0 +1,48 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/include.s -o %t2 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ +# RUN: %p/Inputs/notinclude.s -o %t3.notinclude + +# RUN: echo "SECTIONS {} " > %t.script +# RUN: ld.lld -o %t --script %t.script %t1 %t2 %t3.notinclude +# RUN: llvm-objdump -d %t | \ +# RUN: FileCheck %s + +# CHECK: Disassembly of section .text: +# CHECK: _start: +# CHECK: 120: 48 c7 c0 3c 00 00 00 movq $60, %rax +# CHECK: 127: 48 c7 c7 2a 00 00 00 movq $42, %rdi +# CHECK: 12e: 00 00 addb %al, (%rax) +# CHECK: _potato: +# CHECK: 130: 90 nop +# CHECK: 131: 90 nop +# CHECK: 132: 00 00 addb %al, (%rax) +# CHECK: tomato: +# CHECK: 134: b8 01 00 00 00 movl $1, %eax + +# RUN: echo "SECTIONS { .patatino : \ +# RUN: { KEEP(*(EXCLUDE_FILE(*notinclude) .text)) } }" \ +# RUN: > %t.script +# RUN: ld.lld -o %t2 --script %t.script %t1 %t2 %t3.notinclude +# RUN: llvm-objdump -d %t2 | \ +# RUN: FileCheck %s --check-prefix=EXCLUDE + +# EXCLUDE: Disassembly of section .patatino: +# EXCLUDE: _start: +# EXCLUDE: 120: 48 c7 c0 3c 00 00 00 movq $60, %rax +# EXCLUDE: 127: 48 c7 c7 2a 00 00 00 movq $42, %rdi +# EXCLUDE: 12e: 00 00 addb %al, (%rax) +# EXCLUDE: _potato: +# EXCLUDE: 130: 90 nop +# EXCLUDE: 131: 90 nop +# EXCLUDE: Disassembly of section .text: +# EXCLUDE: tomato: +# EXCLUDE: 134: b8 01 00 00 00 movl $1, %eax + +.section .text +.globl _start +_start: + mov $60, %rax + mov $42, %rdi |

