[ELF/LinkerScript] Support EXCLUDE_FILE inside KEEP.

Differential Revision:	https://reviews.llvm.org/D22795

llvm-svn: 276825
This commit is contained in:
Davide Italiano 2016-07-27 01:44:01 +00:00
parent f990fa5f7b
commit e7282797aa
5 changed files with 94 additions and 15 deletions

View File

@ -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(")");
}

View File

@ -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;

View File

@ -0,0 +1,5 @@
.section .text
.globl _potato
_potato:
nop
nop

View File

@ -0,0 +1,4 @@
.section .text
.globl tomato
tomato:
movl $1, %eax

View File

@ -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