// 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;
}
// 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;
}
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);
void readAsNeeded();
void readEntry();
void readExtern();
+ std::unique_ptr<InputSectionDescription> readFilePattern();
void readGroup();
void readKeep(OutputSectionCommand *Cmd);
void readInclude();
.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(")");
}
struct InputSectionDescription : BaseCommand {
InputSectionDescription() : BaseCommand(InputSectionKind) {}
static bool classof(const BaseCommand *C);
+ std::vector<StringRef> ExcludedFiles;
std::vector<StringRef> Patterns;
};
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;
--- /dev/null
+# 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