diff --git a/linker/linker.cpp b/linker/linker.cpp index 6c30e1c32..26821a58f 100644 --- a/linker/linker.cpp +++ b/linker/linker.cpp @@ -1734,6 +1734,14 @@ void soinfo::set_st_ino(ino_t ino) { } } +void soinfo::set_has_ifuncs(bool ifuncs) { + if ((this->flags & FLAG_NEW_SOINFO) == 0) { + return; + } + + has_ifuncs = ifuncs; +} + dev_t soinfo::get_st_dev() { if (has_min_version(0)) { return st_dev; @@ -2171,6 +2179,18 @@ bool soinfo::LinkImage(const android_dlextinfo* extinfo) { } #endif + // if there are ifuncs, we need to do an additional relocation pass. + // they cannot be resolved until the rest of the relocations are done + // because we need to call the resolution function which may be waiting + // on relocations. + if(si->get_has_ifuncs()) { +#if defined(__i386__) + soinfo_ifunc_relocate(si, si->plt_rel, si->plt_rel_count, needed); +#elif defined(__x86_64__) + soinfo_ifunc_relocate(si, si->plt_rela, si->plt_rela_count, needed); +#endif + } + #if defined(__mips__) if (!mips_relocate_got(this)) { return false; diff --git a/linker/linker.h b/linker/linker.h index f6e3a48ba..a48a8c6c3 100644 --- a/linker/linker.h +++ b/linker/linker.h @@ -214,8 +214,12 @@ struct soinfo { void set_st_dev(dev_t st_dev); void set_st_ino(ino_t st_ino); + void set_has_ifuncs(bool ifunc); ino_t get_st_ino(); dev_t get_st_dev(); + bool get_has_ifuncs(); + + int get_rtld_flags(); diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk index bc5f1086d..6158ddee7 100644 --- a/tests/libs/Android.mk +++ b/tests/libs/Android.mk @@ -290,6 +290,20 @@ ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),arm64 x86 x86_64)) include $(TEST_PATH)/Android.build.mk endif +# ----------------------------------------------------------------------------- +# Library used by ifunc tests +# ----------------------------------------------------------------------------- +ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86 x86_64)) + libtest_ifunc_src_files := \ + dlopen_testlib_ifunc.c + + LOCAL_SDK_VERSION := current + module := libtest_ifunc + build_type := target + build_target := SHARED_LIBRARY + include $(TEST_PATH)/Android.build.mk +endif + # ----------------------------------------------------------------------------- # Library used by atexit tests # -----------------------------------------------------------------------------