Return has_DT_SYMBOLIC flag.

This reverts commit 8f61d991831f0ea515fa50a5c38dbbcfbab0dd28

 Despite the fact that static linker does all the work while linking
 -Bsymbolic executables, according to the SCO doc following DT_SYMBOLIC
 and DF_SYMBOLIC flags is still a requirement for the dynamic linker
 as well.

 (see http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html)

Change-Id: I23f6a5e9b662e40cdbc462b64feff912431e800c
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 09ffa23..5b39668 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -485,14 +485,34 @@
   unsigned elf_hash = elfhash(name);
   ElfW(Sym)* s = nullptr;
 
-  if (somain != nullptr) {
-    DEBUG("%s: looking up %s in executable %s",
-          si->name, name, somain->name);
-
-    // 1. Look for it in the main executable
-    s = soinfo_elf_lookup(somain, elf_hash, name);
+  /* "This element's presence in a shared object library alters the dynamic linker's
+   * symbol resolution algorithm for references within the library. Instead of starting
+   * a symbol search with the executable file, the dynamic linker starts from the shared
+   * object itself. If the shared object fails to supply the referenced symbol, the
+   * dynamic linker then searches the executable file and other shared objects as usual."
+   *
+   * http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html
+   *
+   * Note that this is unlikely since static linker avoids generating
+   * relocations for -Bsymbolic linked dynamic executables.
+   */
+  if (si->has_DT_SYMBOLIC) {
+    DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si->name, name);
+    s = soinfo_elf_lookup(si, elf_hash, name);
     if (s != nullptr) {
-      *lsi = somain;
+      *lsi = si;
+    }
+  }
+
+  if (s == nullptr && somain != nullptr) {
+    // 1. Look for it in the main executable unless we already did.
+    if (si != somain || !si->has_DT_SYMBOLIC) {
+      DEBUG("%s: looking up %s in executable %s",
+            si->name, name, somain->name);
+      s = soinfo_elf_lookup(somain, elf_hash, name);
+      if (s != nullptr) {
+        *lsi = somain;
+      }
     }
 
     // 2. Look for it in the ld_preloads
@@ -505,22 +525,23 @@
         }
       }
     }
+  }
 
-    /* Look for symbols in the local scope (the object who is
-     * searching). This happens with C++ templates on x86 for some
-     * reason.
-     *
-     * Notes on weak symbols:
-     * The ELF specs are ambiguous about treatment of weak definitions in
-     * dynamic linking.  Some systems return the first definition found
-     * and some the first non-weak definition.   This is system dependent.
-     * Here we return the first definition found for simplicity.  */
+  /* Look for symbols in the local scope (the object who is
+   * searching). This happens with C++ templates on x86 for some
+   * reason.
+   *
+   * Notes on weak symbols:
+   * The ELF specs are ambiguous about treatment of weak definitions in
+   * dynamic linking.  Some systems return the first definition found
+   * and some the first non-weak definition.   This is system dependent.
+   * Here we return the first definition found for simplicity.  */
 
-    if (s == nullptr) {
-      s = soinfo_elf_lookup(si, elf_hash, name);
-      if (s != nullptr) {
-        *lsi = si;
-      }
+  if (s == nullptr && !si->has_DT_SYMBOLIC) {
+    DEBUG("%s: looking up %s in local scope", si->name, name);
+    s = soinfo_elf_lookup(si, elf_hash, name);
+    if (s != nullptr) {
+      *lsi = si;
     }
   }
 
@@ -2009,7 +2030,7 @@
         break;
 #endif
       case DT_SYMBOLIC:
-        // ignored
+        has_DT_SYMBOLIC = true;
         break;
       case DT_NEEDED:
         ++needed_count;
@@ -2023,6 +2044,9 @@
           has_text_relocations = true;
 #endif
         }
+        if (d->d_un.d_val & DF_SYMBOLIC) {
+          has_DT_SYMBOLIC = true;
+        }
         break;
 #if defined(__mips__)
       case DT_STRSZ:
diff --git a/linker/linker.h b/linker/linker.h
index 68b5594..2896933 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -197,7 +197,7 @@
 #if !defined(__LP64__)
   bool has_text_relocations;
 #endif
-  bool unused4; // DO NOT USE, maintained for compatibility
+  bool has_DT_SYMBOLIC;
 
   soinfo(const char* name, const struct stat* file_stat, int rtld_flags);