Merge "Adjust symbol lookup for DT_SYMBOLIC case"
diff --git a/linker/linker.cpp b/linker/linker.cpp
old mode 100644
new mode 100755
index 40f29a2..e064ccf
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -458,38 +458,68 @@
     Elf32_Sym *s = NULL;
     int i;
 
-    if (si != NULL) {
+    if (si != NULL && somain != NULL) {
 
         /*
-         * If this object was built with symbolic relocations disabled, the
-         * first place to look to resolve external references is the main
-         * executable.
+         * Local scope is executable scope. Just start looking into it right away
+         * for the shortcut.
          */
 
-        if (!si->has_DT_SYMBOLIC) {
-            DEBUG("%5d %s: looking up %s in executable %s\n",
-                  pid, si->name, name, somain->name);
-            s = soinfo_elf_lookup(somain, elf_hash, name);
+        if (si == somain) {
+            s = soinfo_elf_lookup(si, elf_hash, name);
             if (s != NULL) {
-                *lsi = somain;
+                *lsi = si;
                 goto done;
             }
-        }
+        } else {
+            /* Order of symbol lookup is controlled by DT_SYMBOLIC flag */
 
-        /* Look for symbols in the local scope (the object who is
-         * searching). This happens with C++ templates on i386 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 this object was built with symbolic relocations disabled, the
+             * first place to look to resolve external references is the main
+             * executable.
+             */
 
-        s = soinfo_elf_lookup(si, elf_hash, name);
-        if (s != NULL) {
-            *lsi = si;
-            goto done;
+            if (!si->has_DT_SYMBOLIC) {
+                DEBUG("%5d %s: looking up %s in executable %s\n",
+                      pid, si->name, name, somain->name);
+                s = soinfo_elf_lookup(somain, elf_hash, name);
+                if (s != NULL) {
+                    *lsi = somain;
+                    goto done;
+                }
+            }
+
+            /* Look for symbols in the local scope (the object who is
+             * searching). This happens with C++ templates on i386 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.  */
+
+            s = soinfo_elf_lookup(si, elf_hash, name);
+            if (s != NULL) {
+                *lsi = si;
+                goto done;
+            }
+
+            /*
+             * If this object was built with -Bsymbolic and symbol is not found
+             * in the local scope, try to find the symbol in the main executable.
+             */
+
+            if (si->has_DT_SYMBOLIC) {
+                DEBUG("%5d %s: looking up %s in executable %s after local scope\n",
+                      pid, si->name, name, somain->name);
+                s = soinfo_elf_lookup(somain, elf_hash, name);
+                if (s != NULL) {
+                    *lsi = somain;
+                    goto done;
+                }
+            }
         }
     }