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
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index d16559f..6457bc3 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -35,6 +35,8 @@
 
 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 @@
 }
 
 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 @@
 
 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 @@
 
   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::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 @@
   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")) {