[ELF] Support PROVIDE and PROVIDE_HIDDEN inside SECTIONS

llvm-svn: 276398
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 33ccf71..7c1a0ca 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -338,7 +338,7 @@
   uint64_t Val = evalExpr(Cmd->Expr, Dot);
   if (Cmd->Name == ".") {
     Dot = Val;
-  } else {
+  } else if (!Cmd->Ignore) {
     auto *D = cast<DefinedRegular<ELFT>>(Symtab<ELFT>::X->find(Cmd->Name));
     D->Value = Val;
   }
@@ -528,10 +528,19 @@
 }
 
 template <class ELFT> void LinkerScript<ELFT>::addScriptedSymbols() {
-  for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands)
-    if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get()))
-      if (Cmd->Name != "." && Symtab<ELFT>::X->find(Cmd->Name) == nullptr)
-        Symtab<ELFT>::X->addAbsolute(Cmd->Name, STV_DEFAULT);
+  for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
+    auto *Cmd = dyn_cast<SymbolAssignment>(Base.get());
+    if (!Cmd || Cmd->Name == ".")
+      continue;
+
+    if (Symtab<ELFT>::X->find(Cmd->Name) == nullptr)
+      Symtab<ELFT>::X->addAbsolute(Cmd->Name,
+                                   Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT);
+    else
+      // Symbol already exists in symbol table. If it is provided
+      // then we can't override its value.
+      Cmd->Ignore = Cmd->Provide;
+  }
 }
 
 template <class ELFT> bool LinkerScript<ELFT>::hasPhdrsCommands() {
@@ -592,7 +601,8 @@
   void readOutputSectionDescription(StringRef OutSec);
   std::vector<StringRef> readOutputSectionPhdrs();
   unsigned readPhdrType();
-  void readSymbolAssignment(StringRef Name);
+  void readProvide(bool Hidden);
+  SymbolAssignment *readSymbolAssignment(StringRef Name);
   std::vector<StringRef> readSectionsCommandExpr();
 
   const static StringMap<Handler> Cmd;
@@ -789,7 +799,11 @@
       continue;
     }
     next();
-    if (peek() == "=")
+    if (Tok == "PROVIDE")
+      readProvide(false);
+    else if (Tok == "PROVIDE_HIDDEN")
+      readProvide(true);
+    else if (peek() == "=")
       readSymbolAssignment(Tok);
     else
       readOutputSectionDescription(Tok);
@@ -855,19 +869,42 @@
   }
 }
 
-void ScriptParser::readSymbolAssignment(StringRef Name) {
-  expect("=");
-  std::vector<StringRef> Expr = readSectionsCommandExpr();
-  if (Expr.empty())
-    error("error in symbol assignment expression");
-  else
-    Opt.Commands.push_back(llvm::make_unique<SymbolAssignment>(Name, Expr));
+void ScriptParser::readProvide(bool Hidden) {
+  expect("(");
+  if (SymbolAssignment *Assignment = readSymbolAssignment(next())) {
+    Assignment->Provide = true;
+    Assignment->Hidden = Hidden;
+  }
+  expect(")");
+  expect(";");
 }
 
+SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) {
+  expect("=");
+  std::vector<StringRef> Expr = readSectionsCommandExpr();
+  if (Expr.empty()) {
+    error("error in symbol assignment expression");
+  } else {
+    Opt.Commands.push_back(llvm::make_unique<SymbolAssignment>(Name, Expr));
+    return static_cast<SymbolAssignment *>(Opt.Commands.back().get());
+  }
+  return nullptr;
+}
+
+// This function reads balanced expression until semicolon is seen.
 std::vector<StringRef> ScriptParser::readSectionsCommandExpr() {
+  int Braces = 0;
   std::vector<StringRef> Expr;
   while (!Error) {
-    StringRef Tok = next();
+    StringRef Tok = peek();
+
+    if (Tok == "(")
+      Braces++;
+    else if (Tok == ")")
+      if (--Braces < 0)
+        break;
+
+    next();
     if (Tok == ";")
       break;
     Expr.push_back(Tok);