diff options
author | Dmitriy Ivanov <dimitry@google.com> | 2014-09-11 15:16:03 -0700 |
---|---|---|
committer | Dmitriy Ivanov <dimitry@google.com> | 2014-09-11 16:30:45 -0700 |
commit | 9aea164457c269c475592da36b4655d45f55c7bc (patch) | |
tree | 35f6a459b79e751d6833b2ed765b9d6c17f6672c /tests | |
parent | c71483c0b38a6b4f2675f0bffa221dcf175c34ac (diff) | |
download | bionic-9aea164457c269c475592da36b4655d45f55c7bc.zip bionic-9aea164457c269c475592da36b4655d45f55c7bc.tar.gz bionic-9aea164457c269c475592da36b4655d45f55c7bc.tar.bz2 |
Add IFUNC support for arm64 and IRELATIVE reloc
There are number of changes in the way IFUNC related relocations are done:
1. IRELATIVE relocations are now supported for x86/x86_64 and arm64.
2. IFUNC relocations are now relying on static linker to generate
them in correct order - this removes necessety of additional
relocation pass for ifuncs.
3. Related to 2: rela?.dyn relocations are preformed before .plt ones.
4. Ifunc are resolved on symbol lookup this approach allowed to avoid
mprotect(PROT_WRITE) call on r-x program segments.
Bug: 17399706
Bug: 17177284
Change-Id: I414dd3e82bd47cc03442c5dfc7c279949aec51ed
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Android.build.mk | 4 | ||||
-rw-r--r-- | tests/dlfcn_test.cpp | 14 | ||||
-rw-r--r-- | tests/libs/Android.mk | 10 | ||||
-rw-r--r-- | tests/libs/dlopen_testlib_ifunc.c | 11 |
4 files changed, 32 insertions, 7 deletions
diff --git a/tests/Android.build.mk b/tests/Android.build.mk index d4b0396..d54c851 100644 --- a/tests/Android.build.mk +++ b/tests/Android.build.mk @@ -37,6 +37,10 @@ LOCAL_CLANG := $($(module)_clang_$(build_type)) LOCAL_FORCE_STATIC_EXECUTABLE := $($(module)_force_static_executable) +ifneq ($($(module)_multilib),) + LOCAL_MULTILIB := $($(module)_multilib) +endif + LOCAL_CFLAGS := \ $(common_cflags) \ $($(module)_cflags) \ diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp index 3568f8f..4ba19c1 100644 --- a/tests/dlfcn_test.cpp +++ b/tests/dlfcn_test.cpp @@ -89,8 +89,8 @@ TEST(dlfcn, dlopen_noload) { ASSERT_EQ(0, dlclose(handle2)); } -// ifuncs are only supported on intel for now -#if defined(__i386__) || defined(__x86_64__) +// ifuncs are only supported on intel and arm64 for now +#if defined (__aarch64__) || defined(__i386__) || defined(__x86_64__) TEST(dlfcn, ifunc) { typedef const char* (*fn_ptr)(); @@ -124,9 +124,13 @@ 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_TRUE(handle != nullptr) << dlerror(); + fn_ptr is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_irelative")); + ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); + ASSERT_STREQ("false", is_ctor_called()); + + is_ctor_called = reinterpret_cast<fn_ptr>(dlsym(handle, "is_ctor_called_jump_slot")); + ASSERT_TRUE(is_ctor_called != nullptr) << dlerror(); ASSERT_STREQ("true", is_ctor_called()); dlclose(handle); } diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk index be6565b..a675a4f 100644 --- a/tests/libs/Android.mk +++ b/tests/libs/Android.mk @@ -295,7 +295,7 @@ include $(TEST_PATH)/Android.build.mk # ----------------------------------------------------------------------------- # Library used by ifunc tests # ----------------------------------------------------------------------------- -ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64)) +ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm64 x86 x86_64)) libtest_ifunc_src_files := \ dlopen_testlib_ifunc.c @@ -303,6 +303,14 @@ ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64)) module := libtest_ifunc build_type := target build_target := SHARED_LIBRARY + + ifeq ($(TARGET_ARCH),arm64) + libtest_ifunc_multilib := 64 + # TODO: This is a workaround - remove it once gcc + # removes its Android ifunc checks + libtest_ifunc_cflags := -mglibc + endif + include $(TEST_PATH)/Android.build.mk endif diff --git a/tests/libs/dlopen_testlib_ifunc.c b/tests/libs/dlopen_testlib_ifunc.c index 4874841..b68a3dd 100644 --- a/tests/libs/dlopen_testlib_ifunc.c +++ b/tests/libs/dlopen_testlib_ifunc.c @@ -23,8 +23,17 @@ static void __attribute__((constructor)) init_flag() { g_flag = 1; } +static const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun"))); + const char* foo() __attribute__ ((ifunc ("foo_ifunc"))); -const char* is_ctor_called() __attribute__ ((ifunc("is_ctor_called_ifun"))); + +// Static linker creates GLOBAL/IFUNC symbol and JUMP_SLOT relocation type for plt segment +const char* is_ctor_called_jump_slot() __attribute__ ((ifunc("is_ctor_called_ifun"))); + +const char* is_ctor_called_irelative() { + // Call internal ifunc-resolved function with IRELATIVE reloc + return is_ctor_called(); +} const char* return_true() { return "true"; |