Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -82,6 +82,7 @@ struct InputSectionDescription : BaseCommand { InputSectionDescription() : BaseCommand(InputSectionKind) {} static bool classof(const BaseCommand *C); + std::vector ExcludedFiles; std::vector Patterns; }; @@ -131,10 +132,12 @@ bool hasPhdrsCommands(); private: - std::vector>> getSectionMap(); + std::vector, ArrayRef>> + getSectionMap(); std::vector *> - getInputSections(ArrayRef Patterns); + getInputSections(ArrayRef Patterns, + ArrayRef ExcludedFiles); // "ScriptConfig" is a bit too long, so define a short name for it. ScriptConfiguration &Opt = *ScriptConfig; Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -79,15 +79,16 @@ // input sections start with ".foo." or ".bar." should be added to // ".text" section. template -std::vector>> +std::vector, ArrayRef>> LinkerScript::getSectionMap() { - std::vector>> Ret; + std::vector, ArrayRef>> + Ret; for (const std::unique_ptr &Base1 : Opt.Commands) if (auto *Cmd1 = dyn_cast(Base1.get())) for (const std::unique_ptr &Base2 : Cmd1->Commands) if (auto *Cmd2 = dyn_cast(Base2.get())) - Ret.emplace_back(Cmd1->Name, Cmd2->Patterns); + Ret.emplace_back(Cmd1->Name, Cmd2->Patterns, Cmd2->ExcludedFiles); return Ret; } @@ -95,13 +96,16 @@ // Returns input sections filtered by given glob patterns. template std::vector *> -LinkerScript::getInputSections(ArrayRef Patterns) { +LinkerScript::getInputSections(ArrayRef Patterns, + ArrayRef ExcludedFiles) { std::vector *> Ret; for (const std::unique_ptr> &F : Symtab::X->getObjectFiles()) for (InputSectionBase *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; } @@ -122,9 +126,11 @@ }; for (auto &P : getSectionMap()) { - StringRef OutputName = P.first; - ArrayRef InputPatterns = P.second; - for (InputSectionBase *S : getInputSections(InputPatterns)) { + StringRef OutputName = std::get<0>(P); + ArrayRef InputPatterns = std::get<1>(P); + ArrayRef ExcludedFiles = std::get<2>(P); + for (InputSectionBase *S : + getInputSections(InputPatterns, ExcludedFiles)) { if (OutputName == "/DISCARD/") { S->Live = false; reportDiscarded(S); @@ -681,11 +687,23 @@ expect("("); expect("*"); expect("("); + auto *InCmd = new InputSectionDescription(); Cmd->Commands.emplace_back(InCmd); - while (!Error && !skip(")")) { + + if (peek() == "EXCLUDE_FILE") { + next(); + expect("("); + while (!Error && !skip(")")) + InCmd->ExcludedFiles.push_back(next()); Opt.KeptSections.push_back(peek()); InCmd->Patterns.push_back(next()); + expect(")"); + } else { + while (!Error && !skip(")")) { + Opt.KeptSections.push_back(peek()); + InCmd->Patterns.push_back(next()); + } } expect(")"); } Index: test/ELF/linkerscript/Inputs/include.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/Inputs/include.s @@ -0,0 +1,5 @@ +.section .text +.globl _potato +_potato: + nop + nop Index: test/ELF/linkerscript/Inputs/notinclude.s =================================================================== --- /dev/null +++ test/ELF/linkerscript/Inputs/notinclude.s @@ -0,0 +1,4 @@ +.section .text +.globl tomato +tomato: + movl $1, %eax Index: test/ELF/linkerscript/linkerscript-excludefile.s =================================================================== --- /dev/null +++ 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 + +# CHECK: Disassembly of section .patatino: +# 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: Disassembly of section .text: +# CHECK: tomato: +# CHECK: 134: b8 01 00 00 00 movl $1, %eax + +.section .text +.globl _start +_start: + mov $60, %rax + mov $42, %rdi