aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDmitriy Ivanov <dimitry@google.com>2014-08-21 13:54:03 -0700
committerDmitriy Ivanov <dimitry@google.com>2014-10-01 15:51:47 -0700
commitbd321c1106ed30a71d55d5c365335dfe552b0883 (patch)
treeca05e325ffbaa32b3cca7f78de8d0938b2c0e7d3 /tests
parent31b88da8431096a6df276705046ca7a012fa3530 (diff)
downloadbionic-bd321c1106ed30a71d55d5c365335dfe552b0883.tar.gz
Run constructors before resolving ifunc functions
Bug: 17177284 (cherry picked from commit 9598b8c415e2fa9f240508185fe8c964b83f538d) Change-Id: I2c9631ee1cd77f8cf95ec0216a35b605c8786454
Diffstat (limited to 'tests')
-rw-r--r--tests/Android.mk16
-rw-r--r--tests/dlfcn_test.cpp30
-rw-r--r--tests/libs/dlopen_testlib_ifunc.c21
3 files changed, 56 insertions, 11 deletions
diff --git a/tests/Android.mk b/tests/Android.mk
index 8184bf74b..9ee33e004 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -356,6 +356,22 @@ bionic-unit-tests-run-on-host: bionic-unit-tests $(TARGET_OUT_EXECUTABLES)/$(LIN
$(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests$(NATIVE_TEST_SUFFIX) $(BIONIC_TEST_FLAGS)
endif
+ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86_64))
+# add target to run lp32 tests
+bionic-unit-tests-run-on-host32: bionic-unit-tests $(TARGET_OUT_EXECUTABLES)/$(LINKER) $(TARGET_OUT_EXECUTABLES)/sh
+ if [ ! -d /system -o ! -d /system/bin ]; then \
+ echo "Attempting to create /system/bin"; \
+ sudo mkdir -p -m 0777 /system/bin; \
+ fi
+ mkdir -p $(TARGET_OUT_DATA)/local/tmp
+ cp $(TARGET_OUT_EXECUTABLES)/linker /system/bin
+ cp $(TARGET_OUT_EXECUTABLES)/sh /system/bin
+ ANDROID_DATA=$(TARGET_OUT_DATA) \
+ ANDROID_ROOT=$(TARGET_OUT) \
+ LD_LIBRARY_PATH=$(2ND_TARGET_OUT_SHARED_LIBRARIES) \
+ $(2ND_TARGET_OUT_DATA_NATIVE_TESTS)/bionic-unit-tests/bionic-unit-tests32 $(BIONIC_TEST_FLAGS)
+endif
+
endif # linux-x86
include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 260cbd601..6de38c89e 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -90,32 +90,42 @@ TEST(dlfcn, dlopen_noload) {
// ifuncs are only supported on intel for now
#if defined(__i386__) || defined(__x86_64__)
TEST(dlfcn, ifunc) {
- const char* (*foo_ptr)();
- const char* (*foo_library_ptr)();
+ typedef const char* (*fn_ptr)();
// ifunc's choice depends on whether IFUNC_CHOICE has a value
// first check the set case
setenv("IFUNC_CHOICE", "set", 1);
void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
ASSERT_TRUE(handle != NULL);
- *(void **)(&foo_ptr) = dlsym(handle, "foo");
- *(void **)(&foo_library_ptr) = dlsym(handle, "foo_library");
+ fn_ptr foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
+ fn_ptr foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
ASSERT_TRUE(foo_ptr != NULL);
ASSERT_TRUE(foo_library_ptr != NULL);
- ASSERT_EQ(strncmp("set", (*foo_ptr)(), 3), 0);
- ASSERT_EQ(strncmp("set", (*foo_library_ptr)(), 3), 0);
+ ASSERT_EQ(strncmp("set", foo_ptr(), 3), 0);
+ ASSERT_EQ(strncmp("set", foo_library_ptr(), 3), 0);
dlclose(handle);
// then check the unset case
unsetenv("IFUNC_CHOICE");
handle = dlopen("libtest_ifunc.so", RTLD_NOW);
ASSERT_TRUE(handle != NULL);
- *(void **)(&foo_ptr) = dlsym(handle, "foo");
- *(void **)(&foo_library_ptr) = dlsym(handle, "foo_library");
+ foo_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo"));
+ foo_library_ptr = reinterpret_cast<fn_ptr>(dlsym(handle, "foo_library"));
ASSERT_TRUE(foo_ptr != NULL);
ASSERT_TRUE(foo_library_ptr != NULL);
- ASSERT_EQ(strncmp("unset", (*foo_ptr)(), 5), 0);
- ASSERT_EQ(strncmp("unset", (*foo_library_ptr)(), 3), 0);
+ ASSERT_EQ(strncmp("unset", foo_ptr(), 5), 0);
+ ASSERT_EQ(strncmp("unset", foo_library_ptr(), 3), 0);
+ dlclose(handle);
+}
+
+TEST(dlfcn, ifunc_ctor_call) {
+ typedef const char* (*fn_ptr)();
+
+ void* handle = dlopen("libtest_ifunc.so", RTLD_NOW);
+ ASSERT_TRUE(handle != NULL) << dlerror();
+ fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called"));
+ ASSERT_TRUE(is_ctor_called != NULL) << dlerror();
+ ASSERT_STREQ("true", is_ctor_called());
dlclose(handle);
}
#endif
diff --git a/tests/libs/dlopen_testlib_ifunc.c b/tests/libs/dlopen_testlib_ifunc.c
index 1c4baface..48748417d 100644
--- a/tests/libs/dlopen_testlib_ifunc.c
+++ b/tests/libs/dlopen_testlib_ifunc.c
@@ -17,7 +17,22 @@
#include <stdio.h>
#include <stdlib.h>
+static int g_flag = 0;
+
+static void __attribute__((constructor)) init_flag() {
+ g_flag = 1;
+}
+
const char* foo() __attribute__ ((ifunc ("foo_ifunc")));
+const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun")));
+
+const char* return_true() {
+ return "true";
+}
+
+const char* return_false() {
+ return "false";
+}
const char* f1() {
return "unset";
@@ -27,6 +42,10 @@ const char* f2() {
return "set";
}
+void* is_ctor_called_ifun() {
+ return g_flag == 0 ? return_false : return_true;
+}
+
void* foo_ifunc() {
char* choice = getenv("IFUNC_CHOICE");
return choice == NULL ? f1 : f2;
@@ -34,4 +53,4 @@ void* foo_ifunc() {
const char* foo_library() {
return foo();
-} \ No newline at end of file
+}