summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2016-04-21 22:00:51 +0000
committerRui Ueyama <ruiu@google.com>2016-04-21 22:00:51 +0000
commit8ec77e64fcd419df30e09989bcba62c5cb9fd172 (patch)
treebf9fa9dc7b90805ff201e4bfae471980150214b3
parent243b71fd8b9171be13cc3279583c1426a532a25c (diff)
downloadbcm5719-llvm-8ec77e64fcd419df30e09989bcba62c5cb9fd172.tar.gz
bcm5719-llvm-8ec77e64fcd419df30e09989bcba62c5cb9fd172.zip
ELF: Change how to handle KEEP linker script command.
You can instruct the linker to not discard sections even if they are unused and --gc-sections option is given. The linker script command for doing that is KEEP. The syntax is KEEP(foo) where foo is a section name. KEEP commands are written in SECTIONS command, so you can specify the order of sections *and* which sections will be kept. Each sub-command in SECTIONS command are translated into SectionRule object. Previously, each SectionRule has `Keep` bit. However, if you think about it, this hid information in too deep in elements of a list. Semantically, KEEP commands aren't really related to SECTIONS subcommands. We can keep the section list for KEEP in a separate list. This patch does that. llvm-svn: 267065
-rw-r--r--lld/ELF/LinkerScript.cpp41
-rw-r--r--lld/ELF/LinkerScript.h11
-rw-r--r--lld/test/ELF/linkerscript-sections-keep.s48
3 files changed, 53 insertions, 47 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index d16559f1a10..6457bc338cf 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -35,6 +35,8 @@ using namespace lld::elf;
ScriptConfiguration *elf::ScriptConfig;
+static bool matchStr(StringRef S, StringRef T);
+
static uint64_t getInteger(StringRef S) {
uint64_t V;
if (S.getAsInteger(0, V)) {
@@ -159,17 +161,11 @@ static uint64_t evaluate(ArrayRef<StringRef> Tokens, uint64_t Dot) {
}
template <class ELFT>
-SectionRule *LinkerScript<ELFT>::find(InputSectionBase<ELFT> *S) {
+StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) {
for (SectionRule &R : Opt.Sections)
if (R.match(S))
- return &R;
- return nullptr;
-}
-
-template <class ELFT>
-StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) {
- SectionRule *R = find(S);
- return R ? R->Dest : "";
+ return R.Dest;
+ return "";
}
template <class ELFT>
@@ -179,8 +175,10 @@ bool LinkerScript<ELFT>::isDiscarded(InputSectionBase<ELFT> *S) {
template <class ELFT>
bool LinkerScript<ELFT>::shouldKeep(InputSectionBase<ELFT> *S) {
- SectionRule *R = find(S);
- return R && R->Keep;
+ for (StringRef Pat : Opt.KeptSections)
+ if (matchStr(Pat, S->getSectionName()))
+ return true;
+ return false;
}
template <class ELFT>
@@ -326,7 +324,7 @@ private:
void readLocationCounterValue();
void readOutputSectionDescription();
- void readSectionPatterns(StringRef OutSec, bool Keep);
+ void readSectionPatterns(StringRef OutSec);
const static StringMap<Handler> Cmd;
ScriptConfiguration &Opt = *ScriptConfig;
@@ -497,10 +495,10 @@ void ScriptParser::readSections() {
}
}
-void ScriptParser::readSectionPatterns(StringRef OutSec, bool Keep) {
+void ScriptParser::readSectionPatterns(StringRef OutSec) {
expect("(");
while (!Error && !skip(")"))
- Opt.Sections.emplace_back(OutSec, next(), Keep);
+ Opt.Sections.emplace_back(OutSec, next());
}
void ScriptParser::readLocationCounterValue() {
@@ -523,19 +521,28 @@ void ScriptParser::readOutputSectionDescription() {
Opt.Commands.push_back({SectionKind, {}, OutSec});
expect(":");
expect("{");
+
while (!Error && !skip("}")) {
StringRef Tok = next();
if (Tok == "*") {
- readSectionPatterns(OutSec, false);
+ expect("(");
+ while (!Error && !skip(")"))
+ Opt.Sections.emplace_back(OutSec, next());
} else if (Tok == "KEEP") {
expect("(");
- next(); // Skip *
- readSectionPatterns(OutSec, true);
+ expect("*");
+ expect("(");
+ while (!Error && !skip(")")) {
+ StringRef Sec = next();
+ Opt.Sections.emplace_back(OutSec, Sec);
+ Opt.KeptSections.push_back(Sec);
+ }
expect(")");
} else {
setError("unknown command " + Tok);
}
}
+
StringRef Tok = peek();
if (Tok.startswith("=")) {
if (!Tok.startswith("=0x")) {
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index d076f357b7c..88bc0ad5ce2 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -30,17 +30,14 @@ template <class ELFT> class OutputSectionBase;
// This class represents each rule in SECTIONS command.
class SectionRule {
public:
- SectionRule(StringRef D, StringRef S, bool Keep)
- : Dest(D), Keep(Keep), SectionPattern(S) {}
+ SectionRule(StringRef D, StringRef S)
+ : Dest(D), SectionPattern(S) {}
// Returns true if S should be in Dest section.
template <class ELFT> bool match(InputSectionBase<ELFT> *S);
StringRef Dest;
- // KEEP command saves unused sections even if --gc-sections is specified.
- bool Keep = false;
-
private:
StringRef SectionPattern;
};
@@ -70,6 +67,10 @@ struct ScriptConfiguration {
bool DoLayout = false;
llvm::BumpPtrAllocator Alloc;
+
+ // List of section patterns specified with KEEP commands. They will
+ // be kept even if they are unused and --gc-sections is specified.
+ std::vector<StringRef> KeptSections;
};
extern ScriptConfiguration *ScriptConfig;
diff --git a/lld/test/ELF/linkerscript-sections-keep.s b/lld/test/ELF/linkerscript-sections-keep.s
index b77ac4c644f..fae6383ca49 100644
--- a/lld/test/ELF/linkerscript-sections-keep.s
+++ b/lld/test/ELF/linkerscript-sections-keep.s
@@ -37,37 +37,35 @@
# RUN: .keep : { KEEP(*(.keep)) } \
# RUN: .nokeep : { *(.keep) }}" > %t.script
# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t
-# RUN: llvm-objdump -section-headers %t1 | \
-# RUN: FileCheck -check-prefix=KEEP-AT-FIRST %s
-# KEEP-AT-FIRST: Sections:
-# KEEP-AT-FIRST-NEXT: Idx Name Size Address Type
-# KEEP-AT-FIRST-NEXT: 0 00000000 0000000000000000
-# KEEP-AT-FIRST-NEXT: 1 .keep 00000004 0000000000000120 DATA
-# KEEP-AT-FIRST-NEXT: 2 .temp 00000004 0000000000000124 DATA
-# KEEP-AT-FIRST-NEXT: 3 .text 00000007 0000000000000128 TEXT DATA
-# KEEP-AT-FIRST-NEXT: 4 .symtab 00000060 0000000000000000
-# KEEP-AT-FIRST-NEXT: 5 .shstrtab 0000002d 0000000000000000
-# KEEP-AT-FIRST-NEXT: 6 .strtab 00000012 0000000000000000
+# RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=MIXED1 %s
+# MIXED1: Sections:
+# MIXED1-NEXT: Idx Name Size Address Type
+# MIXED1-NEXT: 0 00000000 0000000000000000
+# MIXED1-NEXT: 1 .keep 00000004 0000000000000120 DATA
+# MIXED1-NEXT: 2 .temp 00000004 0000000000000124 DATA
+# MIXED1-NEXT: 3 .text 00000007 0000000000000128 TEXT DATA
+# MIXED1-NEXT: 4 .symtab 00000060 0000000000000000
+# MIXED1-NEXT: 5 .shstrtab 0000002d 0000000000000000
+# MIXED1-NEXT: 6 .strtab 00000012 0000000000000000
## The same, but now section without KEEP is at first place.
-## It will be collected then.
-## This test checks that lld behavior is equal to gold linker.
-## ld.bfd has different behavior, it prevents the section .keep
-## from collecting in this case either.
+## gold and bfd linkers disagree here. gold collects .keep while
+## bfd keeps it. Our current behavior is compatible with bfd although
+## we can choose either way.
# RUN: echo "SECTIONS { \
# RUN: .nokeep : { *(.keep) } \
# RUN: .keep : { KEEP(*(.keep)) }}" > %t.script
# RUN: ld.lld --gc-sections -o %t1 --script %t.script %t
-# RUN: llvm-objdump -section-headers %t1 | \
-# RUN: FileCheck -check-prefix=KEEP-AT-SECOND %s
-# KEEP-AT-SECOND: Sections:
-# KEEP-AT-SECOND-NEXT: Idx Name Size Address Type
-# KEEP-AT-SECOND-NEXT: 0 00000000 0000000000000000
-# KEEP-AT-SECOND-NEXT: 1 .temp 00000004 0000000000000120 DATA
-# KEEP-AT-SECOND-NEXT: 2 .text 00000007 0000000000000124 TEXT DATA
-# KEEP-AT-SECOND-NEXT: 3 .symtab 00000048 0000000000000000
-# KEEP-AT-SECOND-NEXT: 4 .shstrtab 00000027 0000000000000000
-# KEEP-AT-SECOND-NEXT: 5 .strtab 0000000d 0000000000000000
+# RUN: llvm-objdump -section-headers %t1 | FileCheck -check-prefix=MIXED2 %s
+# MIXED2: Sections:
+# MIXED2-NEXT: Idx Name Size Address Type
+# MIXED2-NEXT: 0 00000000 0000000000000000
+# MIXED2-NEXT: 1 .nokeep 00000004 0000000000000120 DATA
+# MIXED2-NEXT: 2 .temp 00000004 0000000000000124 DATA
+# MIXED2-NEXT: 3 .text 00000007 0000000000000128 TEXT DATA
+# MIXED2-NEXT: 4 .symtab 00000060 0000000000000000
+# MIXED2-NEXT: 5 .shstrtab 0000002f 0000000000000000
+# MIXED2-NEXT: 6 .strtab 00000012 0000000000000000
.global _start
_start:
OpenPOWER on IntegriCloud