ELF: Implement basic support for --version-script.

This patch only implements support for version scripts of the form:
  { [ global: symbol1; symbol2; [...]; symbolN; ] local: *; };
No wildcards are supported, other than for the local entry. Symbol versioning
is also not supported.

It works by introducing a new Symbol flag which tracks whether a symbol
appears in the global section of a version script.

This patch also simplifies the logic in SymbolBody::isPreemptible(), and
teaches it to handle the case where symbols with default visibility in DSOs
do not appear in the dynamic symbol table because of a version script.

Fixes PR27482.

Differential Revision: http://reviews.llvm.org/D19430

llvm-svn: 267208
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 206a523..1b82348 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -115,31 +115,26 @@
   if (isLocal())
     return false;
 
+  // Shared symbols resolve to the definition in the DSO.
   if (isShared())
     return true;
 
-  if (Backref->Visibility != STV_DEFAULT)
-    return false;
-
-  if (isUndefined()) {
-    if (!isWeak())
-      return true;
-
-    // Ideally the static linker should see a definition for every symbol, but
-    // shared object are normally allowed to have undefined references that the
-    // static linker never sees a definition for.
-    if (Config->Shared)
-      return true;
-
-    // Otherwise, just resolve to 0.
-    return false;
-  }
-
+  // That's all that can be preempted in a non-DSO.
   if (!Config->Shared)
     return false;
+
+  // Undefined symbols in DSOs can only be preempted if they are strong.
+  // Weak symbols just resolve to zero.
+  if (isUndefined())
+    return !isWeak();
+
+  // -Bsymbolic means that not even default visibility symbols can be preempted.
   if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc()))
     return false;
-  return true;
+
+  // Only default visibility symbols that appear in the dynamic symbol table can
+  // be preempted.
+  return Backref->Visibility == STV_DEFAULT && Backref->includeInDynsym();
 }
 
 template <class ELFT>
@@ -328,7 +323,7 @@
 bool Symbol::includeInDynsym() const {
   if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
     return false;
-  return ExportDynamic || Body->isShared();
+  return (ExportDynamic && VersionScriptGlobal) || Body->isShared();
 }
 
 template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;