summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDmitriy Ivanov <dimitry@google.com>2014-05-19 15:06:58 -0700
committerDmitriy Ivanov <dimitry@google.com>2014-10-31 17:04:00 -0700
commitc87f65d2cd0690d81665f8b241c1d763f72b6f80 (patch)
tree3b2aa8f9f5db41455b221109c33d8f20f85778b5 /tests
parent210ff1b27b67bd2aa29b35a46f48430b7714a802 (diff)
downloadbionic-c87f65d2cd0690d81665f8b241c1d763f72b6f80.zip
bionic-c87f65d2cd0690d81665f8b241c1d763f72b6f80.tar.gz
bionic-c87f65d2cd0690d81665f8b241c1d763f72b6f80.tar.bz2
Add RTLD_NODELETE flag support
Bug: 18186310 Bug: https://code.google.com/p/android/issues/detail?id=64069 (cherry picked from commit 1b20dafdbe65e43b9f4c95057e8482380833ea91) Change-Id: Ic02eec22a7c322ece65eb40730a3404f611526b1
Diffstat (limited to 'tests')
-rw-r--r--tests/dlfcn_test.cpp80
-rw-r--r--tests/libs/Android.mk29
-rw-r--r--tests/libs/dlopen_nodelete_1.cpp31
-rw-r--r--tests/libs/dlopen_nodelete_2.cpp31
-rw-r--r--tests/libs/dlopen_nodelete_dt_flags_1.cpp30
5 files changed, 201 insertions, 0 deletions
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index a55b364..e7787b4 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -232,10 +232,15 @@ TEST(dlfcn, dlopen_check_rtld_global) {
ASSERT_TRUE(sym == nullptr);
void* handle = dlopen("libtest_simple.so", RTLD_NOW | RTLD_GLOBAL);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
sym = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
ASSERT_TRUE(sym != nullptr) << dlerror();
ASSERT_TRUE(reinterpret_cast<bool (*)(void)>(sym)());
dlclose(handle);
+
+ // RTLD_GLOBAL implies RTLD_NODELETE, let's check that
+ void* sym_after_dlclose = dlsym(RTLD_DEFAULT, "dlopen_testlib_simple_func");
+ ASSERT_EQ(sym, sym_after_dlclose);
}
// libtest_with_dependency_loop.so -> libtest_with_dependency_loop_a.so ->
@@ -258,6 +263,81 @@ TEST(dlfcn, dlopen_check_loop) {
ASSERT_STREQ("dlopen failed: library \"libtest_with_dependency_loop.so\" wasn't loaded and RTLD_NOLOAD prevented it", dlerror());
}
+TEST(dlfcn, dlopen_nodelete) {
+ static bool is_unloaded = false;
+
+ void* handle = dlopen("libtest_nodelete_1.so", RTLD_NOW | RTLD_NODELETE);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ void (*set_unload_flag_ptr)(bool*);
+ set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_1_set_unload_flag_ptr"));
+ ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
+ set_unload_flag_ptr(&is_unloaded);
+
+ uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
+ ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
+ ASSERT_EQ(1729U, *taxicab_number);
+ *taxicab_number = 2;
+
+ dlclose(handle);
+ ASSERT_TRUE(!is_unloaded);
+
+ uint32_t* taxicab_number_after_dlclose = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
+ ASSERT_EQ(taxicab_number_after_dlclose, taxicab_number);
+ ASSERT_EQ(2U, *taxicab_number_after_dlclose);
+
+
+ handle = dlopen("libtest_nodelete_1.so", RTLD_NOW);
+ uint32_t* taxicab_number2 = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_1_taxicab_number"));
+ ASSERT_EQ(taxicab_number2, taxicab_number);
+
+ ASSERT_EQ(2U, *taxicab_number2);
+
+ dlclose(handle);
+ ASSERT_TRUE(!is_unloaded);
+}
+
+TEST(dlfcn, dlopen_nodelete_on_second_dlopen) {
+ static bool is_unloaded = false;
+
+ void* handle = dlopen("libtest_nodelete_2.so", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ void (*set_unload_flag_ptr)(bool*);
+ set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_2_set_unload_flag_ptr"));
+ ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
+ set_unload_flag_ptr(&is_unloaded);
+
+ uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_nodelete_2_taxicab_number"));
+ ASSERT_TRUE(taxicab_number != nullptr) << dlerror();
+
+ ASSERT_EQ(1729U, *taxicab_number);
+ *taxicab_number = 2;
+
+ // This RTLD_NODELETE should be ignored
+ void* handle1 = dlopen("libtest_nodelete_2.so", RTLD_NOW | RTLD_NODELETE);
+ ASSERT_TRUE(handle1 != nullptr) << dlerror();
+ ASSERT_EQ(handle, handle1);
+
+ dlclose(handle1);
+ dlclose(handle);
+
+ ASSERT_TRUE(is_unloaded);
+}
+
+TEST(dlfcn, dlopen_nodelete_dt_flags_1) {
+ static bool is_unloaded = false;
+
+ void* handle = dlopen("libtest_nodelete_dt_flags_1.so", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+ void (*set_unload_flag_ptr)(bool*);
+ set_unload_flag_ptr = reinterpret_cast<void (*)(bool*)>(dlsym(handle, "dlopen_nodelete_dt_flags_1_set_unload_flag_ptr"));
+ ASSERT_TRUE(set_unload_flag_ptr != nullptr) << dlerror();
+ set_unload_flag_ptr(&is_unloaded);
+
+ dlclose(handle);
+ ASSERT_TRUE(!is_unloaded);
+}
+
+
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 ee97c61..b7335d5 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -113,6 +113,35 @@ build_target := SHARED_LIBRARY
include $(TEST_PATH)/Android.build.mk
# -----------------------------------------------------------------------------
+# Library used by dlfcn nodelete tests
+# -----------------------------------------------------------------------------
+libtest_nodelete_1_src_files := \
+ dlopen_nodelete_1.cpp
+
+module := libtest_nodelete_1
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
+# Library used by dlfcn nodelete tests
+# -----------------------------------------------------------------------------
+libtest_nodelete_2_src_files := \
+ dlopen_nodelete_2.cpp
+
+module := libtest_nodelete_2
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
+# Library used by dlfcn nodelete tests
+# -----------------------------------------------------------------------------
+libtest_nodelete_dt_flags_1_src_files := \
+ dlopen_nodelete_dt_flags_1.cpp
+
+libtest_nodelete_dt_flags_1_ldflags := -Wl,-z,nodelete
+
+module := libtest_nodelete_dt_flags_1
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# -----------------------------------------------------------------------------
# Libraries used by dlfcn tests to verify correct load order:
# libtest_check_order_2_right.so
# -----------------------------------------------------------------------------
diff --git a/tests/libs/dlopen_nodelete_1.cpp b/tests/libs/dlopen_nodelete_1.cpp
new file mode 100644
index 0000000..9438978
--- /dev/null
+++ b/tests/libs/dlopen_nodelete_1.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+uint32_t dlopen_nodelete_1_taxicab_number = 1729;
+static bool* unload_flag_ptr = nullptr;
+
+extern "C" void dlopen_nodelete_1_set_unload_flag_ptr(bool* ptr) {
+ unload_flag_ptr = ptr;
+}
+
+static void __attribute__((destructor)) unload_guard() {
+ if (unload_flag_ptr != nullptr) {
+ *unload_flag_ptr = true;
+ }
+}
diff --git a/tests/libs/dlopen_nodelete_2.cpp b/tests/libs/dlopen_nodelete_2.cpp
new file mode 100644
index 0000000..b5ab5c1
--- /dev/null
+++ b/tests/libs/dlopen_nodelete_2.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+uint32_t dlopen_nodelete_2_taxicab_number = 1729;
+static bool* unload_flag_ptr = nullptr;
+
+extern "C" void dlopen_nodelete_2_set_unload_flag_ptr(bool* ptr) {
+ unload_flag_ptr = ptr;
+}
+
+static void __attribute__((destructor)) unload_guard() {
+ if (unload_flag_ptr != nullptr) {
+ *unload_flag_ptr = true;
+ }
+}
diff --git a/tests/libs/dlopen_nodelete_dt_flags_1.cpp b/tests/libs/dlopen_nodelete_dt_flags_1.cpp
new file mode 100644
index 0000000..39c0a7e
--- /dev/null
+++ b/tests/libs/dlopen_nodelete_dt_flags_1.cpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+static bool* unload_flag_ptr = nullptr;
+
+extern "C" void dlopen_nodelete_dt_flags_1_set_unload_flag_ptr(bool* ptr) {
+ unload_flag_ptr = ptr;
+}
+
+static void __attribute__((destructor)) unload_guard() {
+ if (unload_flag_ptr != nullptr) {
+ *unload_flag_ptr = true;
+ }
+}