Support DT_RUNPATH in the linker.
Only $ORIGIN substitution is supported, but not linux-specific $LIB
or $PLATFORM.
Change-Id: I5814a016c7c91afba080230a547a863686e7c2b9
diff --git a/tests/Android.build.mk b/tests/Android.build.mk
index 5b2b417..6d4faa9 100644
--- a/tests/Android.build.mk
+++ b/tests/Android.build.mk
@@ -48,6 +48,10 @@
LOCAL_MULTILIB := $($(module)_multilib)
endif
+ifneq ($($(module)_relative_path),)
+ LOCAL_MODULE_RELATIVE_PATH := $($(module)_relative_path)
+endif
+
LOCAL_CFLAGS := \
$(common_cflags) \
$($(module)_cflags) \
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 3c9b8e3..1c01c62 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1062,3 +1062,17 @@
extern "C" int version_zero_function2() {
return 0;
}
+
+TEST(dlfcn, dt_runpath) {
+ void* handle = dlopen("libtest_dt_runpath_d.so", RTLD_NOW);
+ ASSERT_TRUE(handle != nullptr) << dlerror();
+
+ typedef void *(* dlopen_b_fn)();
+ dlopen_b_fn fn = (dlopen_b_fn)dlsym(handle, "dlopen_b");
+ ASSERT_TRUE(fn != nullptr) << dlerror();
+
+ void *p = fn();
+ ASSERT_TRUE(p == nullptr);
+
+ dlclose(handle);
+}
diff --git a/tests/libs/Android.build.dt_runpath.mk b/tests/libs/Android.build.dt_runpath.mk
new file mode 100644
index 0000000..e9b5265
--- /dev/null
+++ b/tests/libs/Android.build.dt_runpath.mk
@@ -0,0 +1,66 @@
+#
+# 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.
+#
+
+# -----------------------------------------------------------------------------
+# Libraries used by dt_runpath tests.
+# -----------------------------------------------------------------------------
+
+# A leaf library in a non-standard directory.
+libtest_dt_runpath_a_src_files := \
+ empty.cpp
+
+libtest_dt_runpath_a_relative_path := dt_runpath_a
+module := libtest_dt_runpath_a
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# Depends on library A with a DT_RUNPATH
+libtest_dt_runpath_b_src_files := \
+ empty.cpp
+
+libtest_dt_runpath_b_shared_libraries := libtest_dt_runpath_a
+libtest_dt_runpath_b_ldflags := -Wl,--rpath,\$${ORIGIN}/../dt_runpath_a
+libtest_dt_runpath_b_relative_path := dt_runpath_b_c_x
+module := libtest_dt_runpath_b
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# Depends on library A with an incorrect DT_RUNPATH. This does not matter
+# because B is the first in the D (below) dependency order, and library A
+# is already loaded using the correct DT_RUNPATH from library B.
+libtest_dt_runpath_c_src_files := \
+ empty.cpp
+
+libtest_dt_runpath_c_shared_libraries := libtest_dt_runpath_a
+libtest_dt_runpath_c_ldflags := -Wl,--rpath,\$${ORIGIN}/invalid_dt_runpath
+libtest_dt_runpath_c_relative_path := dt_runpath_b_c_x
+module := libtest_dt_runpath_c
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# D depends on B and C with DT_RUNPATH.
+libtest_dt_runpath_d_src_files := \
+ dlopen_b.cpp
+
+libtest_dt_runpath_d_shared_libraries := libtest_dt_runpath_b libtest_dt_runpath_c
+libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x
+module := libtest_dt_runpath_d
+include $(LOCAL_PATH)/Android.build.testlib.mk
+
+# A leaf library in a directory library D has DT_RUNPATH for.
+libtest_dt_runpath_x_src_files := \
+ empty.cpp
+
+libtest_dt_runpath_x_relative_path := dt_runpath_b_c_x
+module := libtest_dt_runpath_x
+include $(LOCAL_PATH)/Android.build.testlib.mk
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index a5ef622..662aeef 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -20,6 +20,7 @@
common_cppflags += -std=gnu++11
common_additional_dependencies := \
$(LOCAL_PATH)/Android.mk \
+ $(LOCAL_PATH)/Android.build.dt_runpath.mk \
$(LOCAL_PATH)/Android.build.dlext_testzip.mk \
$(LOCAL_PATH)/Android.build.dlopen_2_parents_reloc.mk \
$(LOCAL_PATH)/Android.build.dlopen_check_order_dlsym.mk \
@@ -180,6 +181,11 @@
include $(LOCAL_PATH)/Android.build.testlib.mk
# -----------------------------------------------------------------------------
+# Build DT_RUNPATH test helper libraries
+# -----------------------------------------------------------------------------
+include $(LOCAL_PATH)/Android.build.dt_runpath.mk
+
+# -----------------------------------------------------------------------------
# Build library with two parents
# -----------------------------------------------------------------------------
include $(LOCAL_PATH)/Android.build.dlopen_2_parents_reloc.mk
diff --git a/tests/libs/dlopen_b.cpp b/tests/libs/dlopen_b.cpp
new file mode 100644
index 0000000..34f2881
--- /dev/null
+++ b/tests/libs/dlopen_b.cpp
@@ -0,0 +1,7 @@
+#include <dlfcn.h>
+extern "C" void *dlopen_b() {
+ // This is not supposed to succeed. Even though this library has DT_RUNPATH
+ // for libtest_dt_runpath_x.so, it is not taked into account for dlopen.
+ void *handle = dlopen("libtest_dt_runpath_x.so", RTLD_NOW);
+ return handle;
+}