[lld] r267065 - ELF: Change how to handle KEEP linker script command.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 21 15:00:51 PDT 2016


Author: ruiu
Date: Thu Apr 21 17:00:51 2016
New Revision: 267065

URL: http://llvm.org/viewvc/llvm-project?rev=267065&view=rev
Log:
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.

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/test/ELF/linkerscript-sections-keep.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=267065&r1=267064&r2=267065&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Apr 21 17:00:51 2016
@@ -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<String
 }
 
 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(Inp
 
 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::readOutputSectionDesc
   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")) {

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=267065&r1=267064&r2=267065&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Apr 21 17:00:51 2016
@@ -30,17 +30,14 @@ template <class ELFT> class OutputSectio
 // 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;

Modified: lld/trunk/test/ELF/linkerscript-sections-keep.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-sections-keep.s?rev=267065&r1=267064&r2=267065&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript-sections-keep.s (original)
+++ lld/trunk/test/ELF/linkerscript-sections-keep.s Thu Apr 21 17:00:51 2016
@@ -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:




More information about the llvm-commits mailing list