Merge "Use the kernel's sa_restorer for aarch64."
diff --git a/libc/Android.mk b/libc/Android.mk
index a81b6c2..56e9876 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -712,6 +712,7 @@
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
 $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
+$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_freebsd_src_files))
 include $(BUILD_STATIC_LIBRARY)
 
 
@@ -780,6 +781,7 @@
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
 $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
+$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_openbsd_src_files))
 include $(BUILD_STATIC_LIBRARY)
 
 
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index b1edfcc..b5ed7f0 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -1,22 +1,35 @@
-# arm specific configs
+# 32-bit arm.
 
-# These are used by the 32-bit targets, but not the 64-bit ones.
-libc_common_src_files_arm := \
+#
+# Various kinds of LP32 cruft.
+#
+
+libc_bionic_src_files_arm += \
+    bionic/mmap.cpp \
+
+libc_common_src_files_arm += \
     bionic/legacy_32_bit_support.cpp \
     bionic/ndk_cruft.cpp \
     bionic/time64.c \
+
+libc_netbsd_src_files_arm += \
+    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+
+libc_openbsd_src_files_arm += \
     upstream-openbsd/lib/libc/stdio/putw.c \
 
-# These are shared by all the 32-bit targets, but not the 64-bit ones.
-libc_bionic_src_files_arm := \
-    bionic/mmap.cpp
+#
+# Default implementations of functions that are commonly optimized.
+#
 
-libc_common_src_files_arm += \
+libc_bionic_src_files_arm += \
     bionic/memchr.c \
     bionic/memrchr.c \
     bionic/strchr.cpp \
     bionic/strnlen.c \
     bionic/strrchr.cpp \
+
+libc_freebsd_src_files_arm += \
     upstream-freebsd/lib/libc/string/wcscat.c \
     upstream-freebsd/lib/libc/string/wcschr.c \
     upstream-freebsd/lib/libc/string/wcscmp.c \
@@ -25,6 +38,8 @@
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
     upstream-freebsd/lib/libc/string/wmemmove.c \
+
+libc_openbsd_src_files_arm += \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/stpcpy.c \
     upstream-openbsd/lib/libc/string/stpncpy.c \
@@ -34,20 +49,10 @@
     upstream-openbsd/lib/libc/string/strncmp.c \
     upstream-openbsd/lib/libc/string/strncpy.c \
 
-# The C++ fortify function implementations for which there is an
-# arm assembler version.
 #
-# Fortify implementations of libc functions.
-# libc_common_src_files_arm +=
-#    bionic/__memcpy_chk.cpp \
-#    bionic/__memset_chk.cpp \
-#    bionic/__strcpy_chk.cpp \
-#    bionic/__strcat_chk.cpp \
+# Inherently architecture-specific code.
+#
 
-libc_common_cflags_arm := -DSOFTFLOAT
-
-##########################################
-### CPU specific source files
 libc_bionic_src_files_arm += \
     arch-arm/bionic/abort_arm.S \
     arch-arm/bionic/atomics_arm.c \
@@ -64,9 +69,6 @@
 libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
 libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c
 
-libc_netbsd_src_files_arm := \
-    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
-
 ## CPU variant specific source files
 ifeq ($(strip $(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)),)
   $(warning TARGET_$(my_2nd_arch_prefix)ARCH is arm, but TARGET_$(my_2nd_arch_prefix)CPU_VARIANT is not defined)
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index eb65cfd..0dd3c27 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -1,8 +1,18 @@
-# arm64 specific configs
+# 64-bit arm.
 
-libc_common_src_files_arm64 := \
+#
+# Default implementations of functions that are commonly optimized.
+#
+
+libc_bionic_src_files_arm64 += \
+    bionic/__memcpy_chk.cpp \
+    bionic/__memset_chk.cpp \
+    bionic/__strcpy_chk.cpp \
+    bionic/__strcat_chk.cpp \
     bionic/memrchr.c \
     bionic/strrchr.cpp \
+
+libc_freebsd_src_files_arm64 += \
     upstream-freebsd/lib/libc/string/wcscat.c \
     upstream-freebsd/lib/libc/string/wcschr.c \
     upstream-freebsd/lib/libc/string/wcscmp.c \
@@ -10,6 +20,8 @@
     upstream-freebsd/lib/libc/string/wcslen.c \
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
+
+libc_openbsd_src_files_arm64 += \
     upstream-openbsd/lib/libc/string/stpncpy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
     upstream-openbsd/lib/libc/string/strlcat.c \
@@ -17,16 +29,11 @@
     upstream-openbsd/lib/libc/string/strncat.c \
     upstream-openbsd/lib/libc/string/strncpy.c \
 
-# Fortify implementations of libc functions.
-libc_common_src_files_arm64 += \
-    bionic/__memcpy_chk.cpp \
-    bionic/__memset_chk.cpp \
-    bionic/__strcpy_chk.cpp \
-    bionic/__strcat_chk.cpp \
+#
+# Inherently architecture-specific code.
+#
 
-##########################################
-### CPU specific source files
-libc_bionic_src_files_arm64 := \
+libc_bionic_src_files_arm64 += \
     arch-arm64/bionic/__bionic_clone.S \
     arch-arm64/bionic/_exit_with_stack_teardown.S \
     arch-arm64/bionic/_setjmp.S \
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index 31a1f32..ac75a4b 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -1,17 +1,32 @@
-# mips specific configs
+# 32-bit mips.
 
-# These are shared by all the 32-bit targets, but not the 64-bit ones.
-libc_common_src_files_mips := \
+#
+# Various kinds of LP32 cruft.
+#
+
+libc_bionic_src_files_mips += \
+    bionic/mmap.cpp \
+
+libc_common_src_files_mips += \
     bionic/legacy_32_bit_support.cpp \
     bionic/ndk_cruft.cpp \
     bionic/time64.c \
+
+libc_netbsd_src_files_mips += \
+    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+
+libc_openbsd_src_files_mips += \
     upstream-openbsd/lib/libc/stdio/putw.c \
 
-# These are shared by all the 32-bit targets, but not the 64-bit ones.
-libc_bionic_src_files_mips += \
-     bionic/mmap.cpp
+#
+# Default implementations of functions that are commonly optimized.
+#
 
-libc_common_src_files_mips += \
+libc_bionic_src_files_mips += \
+    bionic/__memcpy_chk.cpp \
+    bionic/__memset_chk.cpp \
+    bionic/__strcpy_chk.cpp \
+    bionic/__strcat_chk.cpp \
     bionic/memchr.c \
     bionic/memcmp.c \
     bionic/memmove.c \
@@ -19,6 +34,8 @@
     bionic/strchr.cpp \
     bionic/strnlen.c \
     bionic/strrchr.cpp \
+
+libc_freebsd_src_files_mips += \
     upstream-freebsd/lib/libc/string/wcscat.c \
     upstream-freebsd/lib/libc/string/wcschr.c \
     upstream-freebsd/lib/libc/string/wcscmp.c \
@@ -27,6 +44,8 @@
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
     upstream-freebsd/lib/libc/string/wmemmove.c \
+
+libc_openbsd_src_files_mips += \
     upstream-openbsd/lib/libc/string/bcopy.c \
     upstream-openbsd/lib/libc/string/stpcpy.c \
     upstream-openbsd/lib/libc/string/stpncpy.c \
@@ -39,16 +58,10 @@
     upstream-openbsd/lib/libc/string/strncmp.c \
     upstream-openbsd/lib/libc/string/strncpy.c \
 
-# Fortify implementations of libc functions.
-libc_common_src_files_mips += \
-    bionic/__memcpy_chk.cpp \
-    bionic/__memset_chk.cpp \
-    bionic/__strcpy_chk.cpp \
-    bionic/__strcat_chk.cpp \
+#
+# Inherently architecture-specific code.
+#
 
-
-##########################################
-### CPU specific source files
 libc_bionic_src_files_mips += \
     arch-mips/bionic/__bionic_clone.S \
     arch-mips/bionic/bzero.S \
@@ -69,13 +82,12 @@
 else
 libc_bionic_src_files_mips += \
     bionic/memcpy.cpp \
-    bionic/memset.c
-libc_common_src_files_mips += \
-    upstream-openbsd/lib/libc/string/strlen.c
-endif
+    bionic/memset.c \
 
-libc_netbsd_src_files_mips := \
-    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+libc_openbsd_src_files_mips += \
+    upstream-openbsd/lib/libc/string/strlen.c \
+
+endif
 
 libc_crt_target_cflags_mips := \
     $($(my_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk
index 230cb26..0d4b727 100644
--- a/libc/arch-mips64/mips64.mk
+++ b/libc/arch-mips64/mips64.mk
@@ -1,13 +1,25 @@
-# mips64 specific configs
+# 64-bit mips.
 
-libc_common_src_files_mips64 := \
+#
+# Default implementations of functions that are commonly optimized.
+#
+
+libc_bionic_src_files_mips64 += \
+    bionic/__memcpy_chk.cpp \
+    bionic/__memset_chk.cpp \
+    bionic/__strcpy_chk.cpp \
+    bionic/__strcat_chk.cpp \
     bionic/memchr.c \
     bionic/memcmp.c \
+    bionic/memcpy.cpp \
     bionic/memmove.c \
     bionic/memrchr.c \
+    bionic/memset.c \
     bionic/strchr.cpp \
     bionic/strnlen.c \
     bionic/strrchr.cpp \
+
+libc_freebsd_src_files_mips64 += \
     upstream-freebsd/lib/libc/string/wcscat.c \
     upstream-freebsd/lib/libc/string/wcschr.c \
     upstream-freebsd/lib/libc/string/wcscmp.c \
@@ -16,6 +28,8 @@
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
     upstream-freebsd/lib/libc/string/wmemmove.c \
+
+libc_openbsd_src_files_mips64 += \
     upstream-openbsd/lib/libc/string/stpcpy.c \
     upstream-openbsd/lib/libc/string/stpncpy.c \
     upstream-openbsd/lib/libc/string/strcat.c \
@@ -28,17 +42,11 @@
     upstream-openbsd/lib/libc/string/strncmp.c \
     upstream-openbsd/lib/libc/string/strncpy.c \
 
-# Fortify implementations of libc functions.
-libc_common_src_files_mips64 += \
-    bionic/__memcpy_chk.cpp \
-    bionic/__memset_chk.cpp \
-    bionic/__strcpy_chk.cpp \
-    bionic/__strcat_chk.cpp \
+#
+# Inherently architecture-specific code.
+#
 
-
-##########################################
-### CPU specific source files
-libc_bionic_src_files_mips64 := \
+libc_bionic_src_files_mips64 += \
     arch-mips64/bionic/__bionic_clone.S \
     arch-mips64/bionic/_exit_with_stack_teardown.S \
     arch-mips64/bionic/__get_sp.S \
@@ -48,25 +56,18 @@
     arch-mips64/bionic/syscall.S \
     arch-mips64/bionic/vfork.S \
 
-# FIXME TODO
-## libc_bionic_src_files_mips64 += arch-mips64/string/memcpy.S
-## libc_bionic_src_files_mips64 += arch-mips64/string/memset.S
-libc_bionic_src_files_mips64 += bionic/memcpy.cpp
-libc_bionic_src_files_mips64 += bionic/memset.c
-
-
 libc_crt_target_cflags_mips64 := \
     $($(my_2nd_arch_prefix)TARGET_GLOBAL_CFLAGS) \
-    -I$(LOCAL_PATH)/arch-mips64/include
+    -I$(LOCAL_PATH)/arch-mips64/include \
 
 libc_crt_target_crtbegin_file_mips64 := \
-    $(LOCAL_PATH)/arch-mips64/bionic/crtbegin.c
+    $(LOCAL_PATH)/arch-mips64/bionic/crtbegin.c \
 
 libc_crt_target_crtbegin_so_file_mips64 := \
-    $(LOCAL_PATH)/arch-common/bionic/crtbegin_so.c
+    $(LOCAL_PATH)/arch-common/bionic/crtbegin_so.c \
 
 libc_crt_target_so_cflags_mips64 := \
-    -fPIC
+    -fPIC \
 
 libc_crt_target_ldflags_mips64 := \
-    -melf64ltsmip
+    -melf64ltsmip \
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index f45eb65..9f2188c 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -1,27 +1,40 @@
-# x86 specific configs
+# 32-bit x86.
 
-# These are shared by all the 32-bit targets, but not the 64-bit ones.
-libc_common_src_files_x86 := \
+#
+# Various kinds of LP32 cruft.
+#
+
+libc_bionic_src_files_x86 += \
+    bionic/mmap.cpp \
+
+libc_common_src_files_x86 += \
     bionic/legacy_32_bit_support.cpp \
     bionic/ndk_cruft.cpp \
     bionic/time64.c \
+
+libc_netbsd_src_files_x86 += \
+    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
+
+libc_openbsd_src_files_x86 += \
     upstream-openbsd/lib/libc/stdio/putw.c \
 
-# Fortify implementations of libc functions.
+#
+# Default implementations of functions that are commonly optimized.
+#
+
 libc_common_src_files_x86 += \
     bionic/__memcpy_chk.cpp \
     bionic/__memset_chk.cpp \
     bionic/__strcpy_chk.cpp \
     bionic/__strcat_chk.cpp \
+
+libc_freebsd_src_files_x86 += \
     upstream-freebsd/lib/libc/string/wmemmove.c \
 
+#
+# Inherently architecture-specific functions.
+#
 
-# These are shared by all the 32-bit targets, but not the 64-bit ones.
-libc_bionic_src_files_x86 := \
-    bionic/mmap.cpp
-
-##########################################
-### CPU specific source files
 libc_bionic_src_files_x86 += \
     arch-x86/bionic/__bionic_clone.S \
     arch-x86/bionic/_exit_with_stack_teardown.S \
@@ -42,9 +55,6 @@
 include $(arch_variant_mk)
 libc_common_additional_dependencies += $(arch_variant_mk)
 
-libc_netbsd_src_files_x86 := \
-    upstream-netbsd/common/lib/libc/hash/sha1/sha1.c \
-
 arch_variant_mk :=
 
 libc_crt_target_cflags_x86 := \
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 5f12a49..8675ef4 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -1,11 +1,21 @@
-# x86_64 specific configs
+# 64-bit x86.
 
-libc_common_src_files_x86_64 := \
+#
+# Default implementations of functions that are commonly optimized.
+#
+
+libc_bionic_src_files_x86_64 += \
+    bionic/__memcpy_chk.cpp \
+    bionic/__memset_chk.cpp \
+    bionic/__strcpy_chk.cpp \
+    bionic/__strcat_chk.cpp \
     bionic/memchr.c \
     bionic/memrchr.c \
     bionic/strchr.cpp \
     bionic/strnlen.c \
     bionic/strrchr.cpp \
+
+libc_freebsd_src_files_x86_64 += \
     upstream-freebsd/lib/libc/string/wcscat.c \
     upstream-freebsd/lib/libc/string/wcschr.c \
     upstream-freebsd/lib/libc/string/wcscmp.c \
@@ -14,20 +24,16 @@
     upstream-freebsd/lib/libc/string/wcsrchr.c \
     upstream-freebsd/lib/libc/string/wmemcmp.c \
     upstream-freebsd/lib/libc/string/wmemmove.c \
+
+libc_openbsd_src_files_x86_64 += \
     upstream-openbsd/lib/libc/string/strlcat.c \
     upstream-openbsd/lib/libc/string/strlcpy.c \
 
-# Fortify implementations of libc functions.
-libc_common_src_files_x86_64 += \
-    bionic/__memcpy_chk.cpp \
-    bionic/__memset_chk.cpp \
-    bionic/__strcpy_chk.cpp \
-    bionic/__strcat_chk.cpp \
+#
+# Inherently architecture-specific code.
+#
 
-
-##########################################
-### CPU specific source files
-libc_bionic_src_files_x86_64 := \
+libc_bionic_src_files_x86_64 += \
     arch-x86_64/bionic/__bionic_clone.S \
     arch-x86_64/bionic/_exit_with_stack_teardown.S \
     arch-x86_64/bionic/__restore_rt.S \
@@ -38,6 +44,10 @@
     arch-x86_64/bionic/syscall.S \
     arch-x86_64/bionic/vfork.S \
 
+#
+# Optimized memory/string functions.
+#
+
 libc_bionic_src_files_x86_64 += \
     arch-x86_64/string/sse2-memcpy-slm.S \
     arch-x86_64/string/sse2-memmove-slm.S \
@@ -55,15 +65,15 @@
 
 libc_crt_target_cflags_x86_64 += \
     -m64 \
-    -I$(LOCAL_PATH)/arch-x86_64/include
+    -I$(LOCAL_PATH)/arch-x86_64/include \
 
-libc_crt_target_ldflags_x86_64 := -melf_x86_64
+libc_crt_target_ldflags_x86_64 := -melf_x86_64 \
 
 libc_crt_target_crtbegin_file_x86_64 := \
-    $(LOCAL_PATH)/arch-common/bionic/crtbegin.c
+    $(LOCAL_PATH)/arch-common/bionic/crtbegin.c \
 
 libc_crt_target_crtbegin_so_file_x86_64 := \
-    $(LOCAL_PATH)/arch-common/bionic/crtbegin_so.c
+    $(LOCAL_PATH)/arch-common/bionic/crtbegin_so.c \
 
 libc_crt_target_so_cflags_x86_64 := \
-    -fPIC
+    -fPIC \
diff --git a/linker/dlfcn.cpp b/linker/dlfcn.cpp
index 712e80e..c930ce9 100644
--- a/linker/dlfcn.cpp
+++ b/linker/dlfcn.cpp
@@ -244,7 +244,6 @@
     __libdl_info.nchain = sizeof(g_libdl_chains)/sizeof(unsigned);
     __libdl_info.bucket = g_libdl_buckets;
     __libdl_info.chain = g_libdl_chains;
-    __libdl_info.has_DT_SYMBOLIC = true;
     __libdl_info.ref_count = 1;
   }
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 3b18900..6dfa768 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -486,117 +486,65 @@
   ElfW(Sym)* s = nullptr;
 
   if (somain != nullptr) {
-    /*
-     * Local scope is executable scope. Just start looking into it right away
-     * for the shortcut.
-     */
+    DEBUG("%s: looking up %s in executable %s",
+          si->name, name, somain->name);
 
-    if (si == somain) {
-      s = soinfo_elf_lookup(si, elf_hash, name);
-      if (s != nullptr) {
-        *lsi = si;
-        goto done;
-      }
+    // 1. Look for it in the main executable
+    s = soinfo_elf_lookup(somain, elf_hash, name);
+    if (s != nullptr) {
+      *lsi = somain;
+    }
 
-      /* Next, look for it in the preloads list */
+    // 2. Look for it in the ld_preloads
+    if (s == nullptr) {
       for (int i = 0; g_ld_preloads[i] != NULL; i++) {
         s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
-        if (s != NULL) {
-          *lsi = g_ld_preloads[i];
-          goto done;
-        }
-      }
-    } else {
-      /* Order of symbol lookup is controlled by DT_SYMBOLIC flag */
-
-      /*
-       * If this object was built with symbolic relocations disabled, the
-       * first place to look to resolve external references is the main
-       * executable.
-       */
-
-      if (!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;
-          goto done;
-        }
-
-        /* Next, look for it in the preloads list */
-        for (int i = 0; g_ld_preloads[i] != NULL; i++) {
-          s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
-          if (s != NULL) {
-            *lsi = g_ld_preloads[i];
-            goto done;
-          }
+          *lsi = g_ld_preloads[i];
+          break;
         }
       }
+    }
 
-      /* 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;
-        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("%s: looking up %s in executable %s after local scope",
-              si->name, name, somain->name);
-        s = soinfo_elf_lookup(somain, elf_hash, name);
-        if (s != nullptr) {
-          *lsi = somain;
-          goto done;
-        }
-
-        /* Next, look for it in the preloads list */
-        for (int i = 0; g_ld_preloads[i] != NULL; i++) {
-          s = soinfo_elf_lookup(g_ld_preloads[i], elf_hash, name);
-          if (s != NULL) {
-            *lsi = g_ld_preloads[i];
-            goto done;
-          }
-        }
       }
     }
   }
 
-  si->get_children().visit([&](soinfo* child) {
-    DEBUG("%s: looking up %s in %s", si->name, name, child->name);
-    s = soinfo_elf_lookup(child, elf_hash, name);
-    if (s != nullptr) {
-      *lsi = child;
-      return false;
-    }
-    return true;
-  });
+  if (s == nullptr) {
+    si->get_children().visit([&](soinfo* child) {
+      DEBUG("%s: looking up %s in %s", si->name, name, child->name);
+      s = soinfo_elf_lookup(child, elf_hash, name);
+      if (s != nullptr) {
+        *lsi = child;
+        return false;
+      }
+      return true;
+    });
+  }
 
-done:
   if (s != nullptr) {
     TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
                "found in %s, base = %p, load bias = %p",
                si->name, name, reinterpret_cast<void*>(s->st_value),
                (*lsi)->name, reinterpret_cast<void*>((*lsi)->base),
                reinterpret_cast<void*>((*lsi)->load_bias));
-    return s;
   }
 
-  return nullptr;
+  return s;
 }
 
 // Each size has it's own allocator.
@@ -1911,6 +1859,10 @@
     DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",
           d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
     switch (d->d_tag) {
+      case DT_SONAME:
+        // TODO: glibc dynamic linker uses this name for
+        // initial library lookup; consider doing the same here.
+        break;
       case DT_HASH:
         nbucket = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[0];
         nchain = reinterpret_cast<uint32_t*>(load_bias + d->d_un.d_ptr)[1];
@@ -1923,6 +1875,12 @@
       case DT_SYMTAB:
         symtab = reinterpret_cast<ElfW(Sym)*>(load_bias + d->d_un.d_ptr);
         break;
+      case DT_SYMENT:
+        if (d->d_un.d_val != sizeof(ElfW(Sym))) {
+          DL_ERR("invalid DT_SYMENT: %zd", static_cast<size_t>(d->d_un.d_val));
+          return false;
+        }
+        break;
 #if !defined(__LP64__)
       case DT_PLTREL:
         if (d->d_un.d_val != DT_REL) {
@@ -1945,12 +1903,13 @@
         plt_rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
 #endif
         break;
-#if defined(__mips__)
       case DT_PLTGOT:
+#if defined(__mips__)
         // Used by mips and mips64.
         plt_got = reinterpret_cast<ElfW(Addr)**>(load_bias + d->d_un.d_ptr);
-        break;
 #endif
+        // Ignore for other platforms... (because RTLD_LAZY is not supported)
+        break;
       case DT_DEBUG:
         // Set the DT_DEBUG entry to the address of _r_debug for GDB
         // if the dynamic table is writable
@@ -1971,6 +1930,15 @@
       case DT_RELASZ:
         rela_count = d->d_un.d_val / sizeof(ElfW(Rela));
         break;
+      case DT_RELAENT:
+        if (d->d_un.d_val != sizeof(ElfW(Rela))) {
+          DL_ERR("invalid DT_RELAENT: %zd", static_cast<size_t>(d->d_un.d_val));
+          return false;
+        }
+        break;
+      case DT_RELACOUNT:
+        // ignored (see DT_RELCOUNT comments for details)
+        break;
       case DT_REL:
         DL_ERR("unsupported DT_REL in \"%s\"", name);
         return false;
@@ -1984,6 +1952,19 @@
       case DT_RELSZ:
         rel_count = d->d_un.d_val / sizeof(ElfW(Rel));
         break;
+      case DT_RELENT:
+        if (d->d_un.d_val != sizeof(ElfW(Rel))) {
+          DL_ERR("invalid DT_RELENT: %zd", static_cast<size_t>(d->d_un.d_val));
+          return false;
+        }
+        break;
+      case DT_RELCOUNT:
+        // "Indicates that all RELATIVE relocations have been concatenated together,
+        // and specifies the RELATIVE relocation count."
+        //
+        // TODO: Spec also mentions that this can be used to optimize relocation process;
+        // Not currently used by bionic linker - ignored.
+        break;
       case DT_RELA:
         DL_ERR("unsupported DT_RELA in \"%s\"", name);
         return false;
@@ -2026,7 +2007,7 @@
         break;
 #endif
       case DT_SYMBOLIC:
-        has_DT_SYMBOLIC = true;
+        // ignored
         break;
       case DT_NEEDED:
         ++needed_count;
@@ -2040,14 +2021,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:
-      case DT_SYMENT:
-      case DT_RELENT:
         break;
       case DT_MIPS_RLD_MAP:
         // Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB.
@@ -2076,8 +2052,10 @@
 #endif
 
       default:
-        DEBUG("Unused DT entry: type %p arg %p",
-        reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+        if (!relocating_linker) {
+          DL_WARN("%s: unused DT entry: type %p arg %p", name,
+              reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+        }
         break;
     }
   }
diff --git a/linker/linker.h b/linker/linker.h
index ca96e2f..68b5594 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -197,9 +197,7 @@
 #if !defined(__LP64__)
   bool has_text_relocations;
 #endif
-  // TODO: remove this flag, dynamic linker
-  // should not use it in any way.
-  bool has_DT_SYMBOLIC;
+  bool unused4; // DO NOT USE, maintained for compatibility
 
   soinfo(const char* name, const struct stat* file_stat, int rtld_flags);