Fix symbol lookup order during relocation

  Relocate symbol against DF_1_GLOBAL shared libraries
  loaded before this shared library. This includes
  main executable, ld_preloads and other libraries
  that have DF_1_GLOBAL flag set.

Bug: 2643900
Bug: 15432753
Change-Id: Ia788748be59b739d1c7e62b978e7e255f9e65c7b
diff --git a/tests/Android.mk b/tests/Android.mk
index c0345e4..3647cd0 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -233,6 +233,7 @@
 
 bionic-unit-tests_src_files := \
     atexit_test.cpp \
+    dl_test.cpp \
     dlext_test.cpp \
     dlfcn_test.cpp \
 
@@ -245,8 +246,7 @@
 bionic-unit-tests_cppflags := $(test_cppflags)
 
 bionic-unit-tests_ldflags := \
-    -Wl,--export-dynamic \
-    -Wl,-u,DlSymTestFunction \
+    -Wl,--export-dynamic
 
 bionic-unit-tests_c_includes := \
     bionic/libc \
@@ -255,6 +255,9 @@
 bionic-unit-tests_shared_libraries_target := \
     libdl \
     libpagemap \
+    libdl_preempt_test_1 \
+    libdl_preempt_test_2 \
+    libdl_test_df_1_global
 
 module := bionic-unit-tests
 module_tag := optional
@@ -302,6 +305,12 @@
 bionic-unit-tests-glibc_src_files := \
     atexit_test.cpp \
     dlfcn_test.cpp \
+    dl_test.cpp \
+
+bionic-unit-tests-glibc_shared_libraries := \
+    libdl_preempt_test_1 \
+    libdl_preempt_test_2 \
+    libdl_test_df_1_global
 
 bionic-unit-tests-glibc_whole_static_libraries := \
     libBionicStandardTests \
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
new file mode 100644
index 0000000..74c7b51
--- /dev/null
+++ b/tests/dl_test.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <dlfcn.h>
+#include <libgen.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include <string>
+
+extern "C" int main_global_default_serial() {
+  return 3370318;
+}
+
+extern "C" int main_global_protected_serial() {
+  return 2716057;
+}
+
+// The following functions are defined in DT_NEEDED
+// libdl_preempt_test.so library.
+
+// This one calls main_global_default_serial
+extern "C" int main_global_default_get_serial();
+
+// This one calls main_global_protected_serial
+extern "C" int main_global_protected_get_serial();
+
+// This one calls lib_global_default_serial
+extern "C" int lib_global_default_get_serial();
+
+// This one calls lib_global_protected_serial
+extern "C" int lib_global_protected_get_serial();
+
+// This test verifies that the global default function
+// main_global_default_serial() is preempted by
+// the function defined above.
+TEST(dl, main_preempts_global_default) {
+  ASSERT_EQ(3370318, main_global_default_get_serial());
+}
+
+// This one makes sure that the global protected
+// symbols do not get preempted
+TEST(dl, main_does_not_preempt_global_protected) {
+  ASSERT_EQ(3370318, main_global_protected_get_serial());
+}
+
+// check same things for lib
+TEST(dl, lib_preempts_global_default) {
+  ASSERT_EQ(3370318, lib_global_default_get_serial());
+}
+
+TEST(dl, lib_does_not_preempt_global_protected) {
+  ASSERT_EQ(3370318, lib_global_protected_get_serial());
+}
+
+// TODO: Add tests for LD_PRELOADs
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 2ab3dc1..060f7e0 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -499,6 +499,20 @@
   ASSERT_TRUE(!is_unloaded);
 }
 
+TEST(dlfcn, dlsym_df_1_global) {
+#if !defined(__arm__)
+  void* handle = dlopen("libtest_dlsym_df_1_global.so", RTLD_NOW);
+  ASSERT_TRUE(handle != nullptr) << dlerror();
+  int (*get_answer)();
+  get_answer = reinterpret_cast<int (*)()>(dlsym(handle, "dl_df_1_global_get_answer"));
+  ASSERT_TRUE(get_answer != nullptr) << dlerror();
+  ASSERT_EQ(42, get_answer());
+  ASSERT_EQ(0, dlclose(handle));
+#else
+  GTEST_LOG_(INFO) << "This test does nothing on arm (to be reenabled once b/18137520 or b/18130452 are fixed).\n";
+#endif
+}
+
 TEST(dlfcn, dlopen_failure) {
   void* self = dlopen("/does/not/exist", RTLD_NOW);
   ASSERT_TRUE(self == NULL);
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index e4fee6a..a454420 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -291,6 +291,42 @@
 include $(LOCAL_PATH)/Android.build.testlib.mk
 
 # -----------------------------------------------------------------------------
+# This library is used by dl_load test to check symbol preempting
+# by main executable
+# -----------------------------------------------------------------------------
+libdl_preempt_test_1_src_files := dl_preempt_library_1.cpp
+
+module := libdl_preempt_test_1
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
+# This library is used by dl_load test to check symbol preempting
+# by libdl_preempt_test_1.so
+# -----------------------------------------------------------------------------
+libdl_preempt_test_2_src_files := dl_preempt_library_2.cpp
+
+module := libdl_preempt_test_2
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
+# Library with DF_1_GLOBAL
+# -----------------------------------------------------------------------------
+# TODO: re-enable arm once b/18137520 or b/18130452 are fixed
+ifeq ($(filter $(TARGET_ARCH),arm),)
+libdl_test_df_1_global_src_files := dl_df_1_global.cpp
+libdl_test_df_1_global_ldflags := -fuse-ld=bfd -Wl,-z,global
+module := libdl_test_df_1_global
+include $(LOCAL_PATH)/Android.build.testlib.mk
+endif
+
+# -----------------------------------------------------------------------------
+# Library using symbol from libdl_test_df_1_global
+# -----------------------------------------------------------------------------
+libtest_dlsym_df_1_global_src_files := dl_df_1_use_global.cpp
+module := libtest_dlsym_df_1_global
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
 # Library with weak function
 # -----------------------------------------------------------------------------
 libtest_dlsym_weak_func_src_files := \
diff --git a/tests/libs/dl_df_1_global.cpp b/tests/libs/dl_df_1_global.cpp
new file mode 100644
index 0000000..39856fd
--- /dev/null
+++ b/tests/libs/dl_df_1_global.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern "C" int dl_df_1_global_get_answer_impl() {
+  return 42;
+}
diff --git a/tests/libs/dl_df_1_use_global.cpp b/tests/libs/dl_df_1_use_global.cpp
new file mode 100644
index 0000000..e14910d
--- /dev/null
+++ b/tests/libs/dl_df_1_use_global.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+extern "C" int __attribute__((weak)) dl_df_1_global_get_answer_impl() {
+  return 0;
+}
+
+extern "C" int dl_df_1_global_get_answer() {
+  return dl_df_1_global_get_answer_impl();
+}
diff --git a/tests/libs/dl_preempt_library_1.cpp b/tests/libs/dl_preempt_library_1.cpp
new file mode 100644
index 0000000..b4d81d5
--- /dev/null
+++ b/tests/libs/dl_preempt_library_1.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This one should be preempted by the function
+// defined in the main executable.
+extern "C" int __attribute__((weak)) main_global_default_serial() {
+  return 2716057;
+}
+
+// Even though this one is defined by the main
+// executable it should not be preempted
+// because of protected visibility
+extern "C" int __attribute__((weak, visibility("protected"))) main_global_protected_serial() {
+  return 3370318;
+}
+
+extern "C" int main_global_default_get_serial() {
+  return main_global_default_serial();
+}
+
+extern "C" int main_global_protected_get_serial() {
+  return main_global_protected_serial();
+}
+
+// Trying to preempt functions from a DT_NEEDED .so
+extern "C" int lib_global_default_serial() {
+  return 3370318;
+}
+
+extern "C" int lib_global_protected_serial() {
+  return 2716057;
+}
diff --git a/tests/libs/dl_preempt_library_2.cpp b/tests/libs/dl_preempt_library_2.cpp
new file mode 100644
index 0000000..8df9a16
--- /dev/null
+++ b/tests/libs/dl_preempt_library_2.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This one should be preempted by the function
+// defined in libdl_preempt_test_1.so
+extern "C" int __attribute__((weak)) lib_global_default_serial() {
+  return 2716057;
+}
+
+// Even though this one is defined by
+// libdl_preempt_test_1.so it should not be
+// preempted because of protected visibility
+extern "C" int __attribute__((weak,visibility("protected"))) lib_global_protected_serial() {
+  return 3370318;
+}
+
+extern "C" int lib_global_default_get_serial() {
+  return lib_global_default_serial();
+}
+
+extern "C" int lib_global_protected_get_serial() {
+  return lib_global_protected_serial();
+}
+