Index: headers.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/headers.c,v retrieving revision 1.54 diff -u -p -r1.54 headers.c --- headers.c 7 Mar 2014 01:27:14 -0000 1.54 +++ headers.c 2 Mar 2016 22:19:54 -0000 @@ -74,7 +74,9 @@ _rtld_digest_dynamic(const char *execnam bool use_pltrela = false; Elf_Addr relsz = 0, relasz = 0; Elf_Addr pltrel = 0, pltrelsz = 0; +#ifdef RTLD_LOADER Elf_Addr init = 0, fini = 0; +#endif dbg(("headers: digesting PT_DYNAMIC at %p", obj->dynamic)); for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) { @@ -227,13 +229,15 @@ _rtld_digest_dynamic(const char *execnam break; case DT_INIT: +#ifdef RTLD_LOADER init = dynp->d_un.d_ptr; +#endif break; #ifdef HAVE_INITFINI_ARRAY case DT_INIT_ARRAY: obj->init_array = - (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr); + (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); dbg(("headers: DT_INIT_ARRAY at %p", obj->init_array)); break; @@ -246,13 +250,15 @@ _rtld_digest_dynamic(const char *execnam #endif case DT_FINI: +#ifdef RTLD_LOADER fini = dynp->d_un.d_ptr; +#endif break; #ifdef HAVE_INITFINI_ARRAY case DT_FINI_ARRAY: obj->fini_array = - (fptr_t *)(obj->relocbase + dynp->d_un.d_ptr); + (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); dbg(("headers: DT_FINI_ARRAY at %p", obj->fini_array)); break; @@ -345,20 +351,11 @@ _rtld_digest_dynamic(const char *execnam obj->relalim = obj->pltrela; } -#if defined(RTLD_LOADER) && defined(__HAVE_FUNCTION_DESCRIPTORS) - if (init != 0) - obj->init = (void (*)(void)) - _rtld_function_descriptor_alloc(obj, NULL, init); - if (fini != 0) - obj->fini = (void (*)(void)) - _rtld_function_descriptor_alloc(obj, NULL, fini); -#else +#ifdef RTLD_LOADER if (init != 0) - obj->init = (void (*)(void)) - (obj->relocbase + init); + obj->init = (Elf_Addr) obj->relocbase + init; if (fini != 0) - obj->fini = (void (*)(void)) - (obj->relocbase + fini); + obj->fini = (Elf_Addr) obj->relocbase + fini; #endif if (dyn_rpath != NULL) { Index: map_object.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/map_object.c,v retrieving revision 1.52 diff -u -p -r1.52 map_object.c --- map_object.c 3 Aug 2013 13:17:05 -0000 1.52 +++ map_object.c 2 Mar 2016 22:19:54 -0000 @@ -442,10 +442,10 @@ _rtld_obj_free(Obj_Entry *obj) } if (!obj->phdr_loaded) xfree((void *)(uintptr_t)obj->phdr); - xfree(obj); #ifdef COMBRELOC _rtld_combreloc_reset(obj); #endif + xfree(obj); } Obj_Entry * Index: paths.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/paths.c,v retrieving revision 1.41 diff -u -p -r1.41 paths.c --- paths.c 6 May 2013 08:02:20 -0000 1.41 +++ paths.c 2 Mar 2016 22:19:54 -0000 @@ -49,7 +49,6 @@ __RCSID("$NetBSD: paths.c,v 1.41 2013/05 #include #include #include -#include #include #include Index: reloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/reloc.c,v retrieving revision 1.106 diff -u -p -r1.106 reloc.c --- reloc.c 6 Jan 2012 10:38:56 -0000 1.106 +++ reloc.c 2 Mar 2016 22:19:54 -0000 @@ -226,3 +226,16 @@ _rtld_relocate_objects(Obj_Entry *first, return 0; } + +Elf_Addr +_rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def) +{ + Elf_Addr target; + + _rtld_shared_exit(); + target = _rtld_call_function_addr(obj, + (Elf_Addr)obj->relocbase + def->st_value); + _rtld_shared_enter(); + + return target; +} Index: rtld.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.c,v retrieving revision 1.173.4.2 diff -u -p -r1.173.4.2 rtld.c --- rtld.c 6 Apr 2015 02:01:39 -0000 1.173.4.2 +++ rtld.c 2 Mar 2016 22:19:55 -0000 @@ -136,25 +136,25 @@ static void _rtld_unref_dag(Obj_Entry *) static Obj_Entry *_rtld_obj_from_addr(const void *); static inline void -_rtld_call_initfini_function(fptr_t func, sigset_t *mask) +_rtld_call_initfini_function(const Obj_Entry *obj, Elf_Addr func, sigset_t *mask) { _rtld_exclusive_exit(mask); - (*func)(); + _rtld_call_function_void(obj, func); _rtld_exclusive_enter(mask); } static void _rtld_call_fini_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen) { - if (obj->fini_arraysz == 0 && (obj->fini == NULL || obj->fini_called)) { - return; - } - if (obj->fini != NULL && !obj->fini_called) { + if (obj->fini_arraysz == 0 && (obj->fini == 0 || obj->fini_called)) + return; + + if (obj->fini != 0 && !obj->fini_called) { dbg (("calling fini function %s at %p%s", obj->path, (void *)obj->fini, obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); obj->fini_called = 1; - _rtld_call_initfini_function(obj->fini, mask); + _rtld_call_initfini_function(obj, obj->fini, mask); } #ifdef HAVE_INITFINI_ARRAY /* @@ -164,12 +164,12 @@ _rtld_call_fini_function(Obj_Entry *obj, * the loop. */ while (obj->fini_arraysz > 0 && _rtld_objgen == cur_objgen) { - fptr_t fini = *obj->fini_array++; + Elf_Addr fini = *obj->fini_array++; obj->fini_arraysz--; dbg (("calling fini array function %s at %p%s", obj->path, (void *)fini, obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); - _rtld_call_initfini_function(fini, mask); + _rtld_call_initfini_function(obj, fini, mask); } #endif /* HAVE_INITFINI_ARRAY */ } @@ -230,15 +230,15 @@ restart: static void _rtld_call_init_function(Obj_Entry *obj, sigset_t *mask, u_int cur_objgen) { - if (obj->init_arraysz == 0 && (obj->init_called || obj->init == NULL)) { + if (obj->init_arraysz == 0 && (obj->init_called || obj->init == 0)) return; - } - if (!obj->init_called && obj->init != NULL) { + + if (!obj->init_called && obj->init != 0) { dbg (("calling init function %s at %p%s", obj->path, (void *)obj->init, obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); obj->init_called = 1; - _rtld_call_initfini_function(obj->init, mask); + _rtld_call_initfini_function(obj, obj->init, mask); } #ifdef HAVE_INITFINI_ARRAY @@ -249,12 +249,12 @@ _rtld_call_init_function(Obj_Entry *obj, * the loop. */ while (obj->init_arraysz > 0 && _rtld_objgen == cur_objgen) { - fptr_t init = *obj->init_array++; + Elf_Addr init = *obj->init_array++; obj->init_arraysz--; dbg (("calling init_array function %s at %p%s", obj->path, (void *)init, obj->z_initfirst ? " (DF_1_INITFIRST)" : "")); - _rtld_call_initfini_function(init, mask); + _rtld_call_initfini_function(obj, init, mask); } #endif /* HAVE_INITFINI_ARRAY */ } @@ -1176,6 +1176,17 @@ do_dlsym(void *handle, const char *name, if (def != NULL) { void *p; + + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { +#ifdef __HAVE_FUNCTION_DESCRIPTORS + lookup_mutex_exit(); + _rtld_shared_enter(); +#endif + p = (void *)_rtld_resolve_ifunc(defobj, def); + _rtld_shared_exit(); + return p; + } + #ifdef __HAVE_FUNCTION_DESCRIPTORS if (ELF_ST_TYPE(def->st_info) == STT_FUNC) { p = (void *)_rtld_function_descriptor_alloc(defobj, @@ -1533,6 +1544,7 @@ _rtld_shared_enter(void) /* Yes, so increment use counter */ if (atomic_cas_uint(&_rtld_mutex, cur, cur + 1) != cur) continue; + membar_enter(); return; } /* @@ -1550,6 +1562,7 @@ _rtld_shared_enter(void) /* * Check for race against _rtld_exclusive_exit before sleeping. */ + membar_sync(); if ((_rtld_mutex & RTLD_EXCLUSIVE_MASK) || _rtld_waiter_exclusive) _lwp_park(CLOCK_REALTIME, 0, NULL, 0, @@ -1577,12 +1590,12 @@ _rtld_shared_exit(void) * Wakeup LWPs waiting for an exclusive lock if this is the last * LWP on the shared lock. */ + membar_exit(); if (atomic_dec_uint_nv(&_rtld_mutex)) return; + membar_sync(); if ((waiter = _rtld_waiter_exclusive) != 0) _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); - - membar_exit(); } void @@ -1597,12 +1610,13 @@ _rtld_exclusive_enter(sigset_t *mask) sigdelset(&blockmask, SIGTRAP); /* Allow the debugger */ sigprocmask(SIG_BLOCK, &blockmask, mask); - membar_enter(); - for (;;) { - if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0) + if (atomic_cas_uint(&_rtld_mutex, 0, locked_value) == 0) { + membar_enter(); break; + } waiter = atomic_swap_uint(&_rtld_waiter_exclusive, self); + membar_sync(); cur = _rtld_mutex; if (cur == locked_value) { _rtld_error("dead lock detected"); @@ -1622,13 +1636,14 @@ _rtld_exclusive_exit(sigset_t *mask) { lwpid_t waiter; + membar_exit(); _rtld_mutex = 0; + membar_sync(); if ((waiter = _rtld_waiter_exclusive) != 0) _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); if ((waiter = _rtld_waiter_shared) != 0) _lwp_unpark(waiter, __UNVOLATILE(&_rtld_mutex)); - membar_exit(); sigprocmask(SIG_SETMASK, mask, NULL); } Index: rtld.h =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/rtld.h,v retrieving revision 1.118 diff -u -p -r1.118 rtld.h --- rtld.h 10 Aug 2014 23:35:26 -0000 1.118 +++ rtld.h 2 Mar 2016 22:19:56 -0000 @@ -179,7 +179,7 @@ typedef struct Struct_Obj_Entry { const Elf_Sym *symtab; /* Symbol table */ const char *strtab; /* String table */ unsigned long strsize; /* Size in bytes of string table */ -#ifdef __mips__ +#if defined(__mips__) || defined(__riscv__) Elf_Word local_gotno; /* Number of local GOT entries */ Elf_Word symtabno; /* Number of dynamic symbols */ Elf_Word gotsym; /* First dynamic symbol in GOT */ @@ -193,8 +193,8 @@ typedef struct Struct_Obj_Entry { Search_Path *rpaths; /* Search path specified in object */ Needed_Entry *needed; /* Shared objects needed by this (%) */ - fptr_t init; /* Initialization function to call */ - fptr_t fini; /* Termination function to call */ + Elf_Addr init; /* Initialization function to call */ + Elf_Addr fini; /* Termination function to call */ /* * BACKWARDS COMPAT Entry points for dlopen() and friends. @@ -288,9 +288,9 @@ typedef struct Struct_Obj_Entry { int vertabnum; /* Number of entries in vertab */ /* init_array/fini_array */ - fptr_t *init_array; /* start of init array */ + Elf_Addr *init_array; /* start of init array */ size_t init_arraysz; /* # of entries in it */ - fptr_t *fini_array; /* start of fini array */ + Elf_Addr *fini_array; /* start of fini array */ size_t fini_arraysz; /* # of entries in it */ #ifdef __ARM_EABI__ void *exidx_start; @@ -326,7 +326,7 @@ extern Elf_Sym _rtld_sym_zero; /* Flags to be passed into _rtld_symlook_ family of functions. */ #define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ -#define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol. +#define SYMLOOK_DLSYM 0x02 /* Return newest versioned symbol. Used by dlsym. */ /* Flags for _rtld_load_object() and friends. */ @@ -404,6 +404,7 @@ int _rtld_relocate_nonplt_objects(Obj_En int _rtld_relocate_plt_lazy(const Obj_Entry *); int _rtld_relocate_plt_objects(const Obj_Entry *); void _rtld_setup_pltgot(const Obj_Entry *); +Elf_Addr _rtld_resolve_ifunc(const Obj_Entry *, const Elf_Sym *); /* search.c */ Obj_Entry *_rtld_load_library(const char *, const Obj_Entry *, int); @@ -474,12 +475,28 @@ Obj_Entry *_rtld_map_object(const char * void _rtld_obj_free(Obj_Entry *); Obj_Entry *_rtld_obj_new(void); +#ifdef RTLD_LOADER /* function descriptors */ #ifdef __HAVE_FUNCTION_DESCRIPTORS Elf_Addr _rtld_function_descriptor_alloc(const Obj_Entry *, const Elf_Sym *, Elf_Addr); const void *_rtld_function_descriptor_function(const void *); + +void _rtld_call_function_void(const Obj_Entry *, Elf_Addr); +Elf_Addr _rtld_call_function_addr(const Obj_Entry *, Elf_Addr); +#else +static inline void +_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr addr) +{ + ((void (*)(void))addr)(); +} +static inline Elf_Addr +_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr addr) +{ + return ((Elf_Addr(*)(void))addr)(); +} #endif /* __HAVE_FUNCTION_DESCRIPTORS */ +#endif /* RTLD_LOADER */ #endif /* _RTLD_SOURCE */ Index: arch/aarch64/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/aarch64/mdreloc.c,v retrieving revision 1.1 diff -u -p -r1.1 mdreloc.c --- arch/aarch64/mdreloc.c 10 Aug 2014 05:47:37 -0000 1.1 +++ arch/aarch64/mdreloc.c 2 Mar 2016 22:20:03 -0000 @@ -222,7 +222,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + } rdbg(("bind now/fixup in %s --> old=%p new=%p", defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); if (*where != new_value) Index: arch/alpha/alpha_reloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/alpha/alpha_reloc.c,v retrieving revision 1.40 diff -u -p -r1.40 alpha_reloc.c --- arch/alpha/alpha_reloc.c 31 Mar 2011 15:30:31 -0000 1.40 +++ arch/alpha/alpha_reloc.c 2 Mar 2016 22:20:03 -0000 @@ -376,7 +376,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + } rdbg(("bind now/fixup in %s --> old=%p new=%p", defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); Index: arch/arm/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/arm/mdreloc.c,v retrieving revision 1.37 diff -u -p -r1.37 mdreloc.c --- arch/arm/mdreloc.c 18 Nov 2011 16:10:03 -0000 1.37 +++ arch/arm/mdreloc.c 2 Mar 2016 22:20:04 -0000 @@ -286,7 +286,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + } /* Set the Thumb bit, if needed. */ if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) new_value |= 1; Index: arch/hppa/hppa_reloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/hppa/hppa_reloc.c,v retrieving revision 1.42 diff -u -p -r1.42 hppa_reloc.c --- arch/hppa/hppa_reloc.c 6 Jan 2012 10:38:57 -0000 1.42 +++ arch/hppa/hppa_reloc.c 2 Mar 2016 22:20:04 -0000 @@ -656,9 +656,19 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - func_pc = (Elf_Addr)(defobj->relocbase + def->st_value + - rela->r_addend); - func_sl = (Elf_Addr)(defobj->pltgot); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + Elf_Addr ptr = _rtld_resolve_ifunc(defobj, def); + assert(RTLD_IS_PLABEL(ptr)); + hppa_plabel *label = RTLD_GET_PLABEL(ptr); + func_pc = label->hppa_plabel_pc; + func_sl = label->hppa_plabel_sl; + } else { + func_pc = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + func_sl = (Elf_Addr)(defobj->pltgot); + } rdbg(("bind now/fixup in %s --> old=(%p,%p) new=(%p,%p)", defobj->strtab + def->st_name, @@ -710,3 +720,29 @@ _rtld_relocate_plt_objects(const Obj_Ent } return 0; } + +void +_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr ptr) +{ + volatile hppa_plabel plabel; + void (*f)(void); + + plabel.hppa_plabel_pc = (Elf_Addr)ptr; + plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot); + f = (void (*)(void))RTLD_MAKE_PLABEL(&plabel); + + f(); +} + +Elf_Addr +_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr ptr) +{ + volatile hppa_plabel plabel; + Elf_Addr (*f)(void); + + plabel.hppa_plabel_pc = (Elf_Addr)ptr; + plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot); + f = (Elf_Addr (*)(void))RTLD_MAKE_PLABEL(&plabel); + + return f(); +} Index: arch/i386/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/i386/mdreloc.c,v retrieving revision 1.35 diff -u -p -r1.35 mdreloc.c --- arch/i386/mdreloc.c 7 Nov 2012 07:24:46 -0000 1.35 +++ arch/i386/mdreloc.c 2 Mar 2016 22:20:05 -0000 @@ -230,7 +230,14 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - target = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + target = _rtld_resolve_ifunc(defobj, def); + } else { + target = (Elf_Addr)(defobj->relocbase + def->st_value); + } + rdbg(("bind now/fixup in %s --> old=%p new=%p", defobj->strtab + def->st_name, (void *)*where, (void *)target)); Index: arch/m68k/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/m68k/mdreloc.c,v retrieving revision 1.29 diff -u -p -r1.29 mdreloc.c --- arch/m68k/mdreloc.c 22 Nov 2011 15:25:28 -0000 1.29 +++ arch/m68k/mdreloc.c 2 Mar 2016 22:20:05 -0000 @@ -223,8 +223,14 @@ _rtld_relocate_plt_object(const Obj_Entr return 0; assert(rela->r_addend == 0); - new_value = (Elf_Addr)(defobj->relocbase + def->st_value + - rela->r_addend); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + } rdbg(("bind now/fixup in %s --> old=%p new=%p", defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); if (*where != new_value) Index: arch/mips/mips_reloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/mips/mips_reloc.c,v retrieving revision 1.62 diff -u -p -r1.62 mips_reloc.c --- arch/mips/mips_reloc.c 25 Mar 2011 18:07:05 -0000 1.62 +++ arch/mips/mips_reloc.c 2 Mar 2016 22:20:05 -0000 @@ -445,7 +445,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry rdbg(("TPREL %s in %s --> %p in %s", obj->strtab + obj->symtab[r_symndx].st_name, - obj->path, (void *)*where, defobj->path)); + obj->path, where, defobj->path)); break; } @@ -487,7 +487,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + } rdbg(("bind now/fixup in %s --> new=%p", defobj->strtab + def->st_name, (void *)new_value)); got[obj->local_gotno + sym - obj->gotsym] = new_value; Index: arch/powerpc/ppc_reloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c,v retrieving revision 1.52 diff -u -p -r1.52 ppc_reloc.c --- arch/powerpc/ppc_reloc.c 28 Jul 2014 17:28:13 -0000 1.52 +++ arch/powerpc/ppc_reloc.c 2 Mar 2016 22:20:05 -0000 @@ -366,7 +366,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + value = _rtld_resolve_ifunc(defobj, def); + } else { + value = (Elf_Addr)(defobj->relocbase + def->st_value); + } rdbg(("bind now/fixup in %s --> new=%p", defobj->strtab + def->st_name, (void *)value)); Index: arch/sh3/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/sh3/mdreloc.c,v retrieving revision 1.30 diff -u -p -r1.30 mdreloc.c --- arch/sh3/mdreloc.c 25 Mar 2011 18:07:06 -0000 1.30 +++ arch/sh3/mdreloc.c 2 Mar 2016 22:20:05 -0000 @@ -282,7 +282,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + } rdbg(("bind now/fixup in %s --> old=%p new=%p", defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); if (*where != new_value) Index: arch/sparc/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/sparc/mdreloc.c,v retrieving revision 1.47 diff -u -p -r1.47 mdreloc.c --- arch/sparc/mdreloc.c 31 Mar 2011 12:47:01 -0000 1.47 +++ arch/sparc/mdreloc.c 2 Mar 2016 22:20:05 -0000 @@ -448,7 +448,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + value = _rtld_resolve_ifunc(defobj, def); + } else { + value = (Elf_Addr)(defobj->relocbase + def->st_value); + } rdbg(("bind now/fixup in %s --> new=%p", defobj->strtab + def->st_name, (void *)value)); Index: arch/sparc64/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/sparc64/mdreloc.c,v retrieving revision 1.56 diff -u -p -r1.56 mdreloc.c --- arch/sparc64/mdreloc.c 2 Apr 2014 14:11:25 -0000 1.56 +++ arch/sparc64/mdreloc.c 2 Mar 2016 22:20:06 -0000 @@ -602,7 +602,13 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - value = (Elf_Addr)(defobj->relocbase + def->st_value); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + value = _rtld_resolve_ifunc(defobj, def); + } else { + value = (Elf_Addr)(defobj->relocbase + def->st_value); + } rdbg(("bind now/fixup in %s at %p --> new=%p", defobj->strtab + def->st_name, (void*)where, (void *)value)); Index: arch/vax/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/vax/mdreloc.c,v retrieving revision 1.29 diff -u -p -r1.29 mdreloc.c --- arch/vax/mdreloc.c 21 Mar 2014 01:43:33 -0000 1.29 +++ arch/vax/mdreloc.c 2 Mar 2016 22:20:08 -0000 @@ -166,8 +166,14 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - new_value = (Elf_Addr)(defobj->relocbase + def->st_value + - rela->r_addend); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + } rdbg(("bind now/fixup pltgot %p in %s --> old=%p new=%p", where, defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); if (*where != new_value) Index: arch/x86_64/mdreloc.c =================================================================== RCS file: /cvsroot/src/libexec/ld.elf_so/arch/x86_64/mdreloc.c,v retrieving revision 1.40 diff -u -p -r1.40 mdreloc.c --- arch/x86_64/mdreloc.c 25 Mar 2011 18:07:07 -0000 1.40 +++ arch/x86_64/mdreloc.c 2 Mar 2016 22:20:08 -0000 @@ -313,8 +313,15 @@ _rtld_relocate_plt_object(const Obj_Entr if (__predict_false(def == &_rtld_sym_zero)) return 0; - new_value = (Elf_Addr)(defobj->relocbase + def->st_value + - rela->r_addend); + if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) { + if (tp == NULL) + return 0; + new_value = _rtld_resolve_ifunc(defobj, def); + } else { + new_value = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + } + rdbg(("bind now/fixup in %s --> old=%p new=%p", defobj->strtab + def->st_name, (void *)*where, (void *)new_value)); if (*where != new_value)