summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog43
-rw-r--r--elf/dl-conflict.c5
-rw-r--r--elf/dl-reloc.c3
-rw-r--r--elf/do-rel.h10
-rw-r--r--elf/dynamic-link.h41
-rw-r--r--elf/rtld.c12
-rw-r--r--include/dlfcn.h1
-rw-r--r--sysdeps/i386/dl-machine.h27
-rw-r--r--sysdeps/ia64/dl-machine.h6
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.h8
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h15
-rw-r--r--sysdeps/s390/s390-32/dl-machine.h5
-rw-r--r--sysdeps/s390/s390-64/dl-machine.h5
-rw-r--r--sysdeps/sh/dl-machine.h5
-rw-r--r--sysdeps/sparc/sparc32/dl-machine.h11
-rw-r--r--sysdeps/sparc/sparc64/dl-machine.h11
-rw-r--r--sysdeps/x86_64/dl-machine.h11
17 files changed, 149 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index a8ccdacc77..2fdde34850 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,46 @@
+2011-10-04 Andreas Schwab <schwab@redhat.com>
+
+ * include/dlfcn.h (__RTLD_NOIFUNC): Define.
+ * elf/do-rel.h (elf_dynamic_do_rel): Add parameter skip_ifunc and
+ pass it down.
+ * elf/dynamic-link.h: Adjust prototypes of elf_machine_rel,
+ elf_machine_rela, elf_machine_lazy_rel.
+ (_ELF_DYNAMIC_DO_RELOC): Add parameter skip_ifunc and pass it down.
+ (ELF_DYNAMIC_DO_REL): Likewise.
+ (ELF_DYNAMIC_DO_RELA): Likewise.
+ (ELF_DYNAMIC_RELOCATE): Likewise.
+ * elf/dl-reloc.c (_dl_relocate_object): Pass __RTLD_NOIFUNC down
+ to ELF_DYNAMIC_DO_REL.
+ * elf/rtld.c (_dl_start): Adjust use of ELF_DYNAMIC_RELOCATE.
+ (dl_main): In trace mode always set __RTLD_NOIFUNC.
+ * elf/dl-conflict.c (_dl_resolve_conflicts): Adjust call to
+ elf_machine_rela.
+ * sysdeps/i386/dl-machine.h (elf_machine_rel): Add parameter
+ skip_ifunc, don't call ifunc function if non-zero.
+ (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ (elf_machine_lazy_rela): Likewise.
+ * sysdeps/ia64/dl-machine.h (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/powerpc/powerpc32/dl-machine.h (elf_machine_rela):
+ Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/powerpc/powerpc64/dl-machine.h (elf_machine_rela):
+ Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/s390/s390-32/dl-machine.h (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/s390/s390-64/dl-machine.h (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/sparc/sparc32/dl-machine.h (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/sparc/sparc64/dl-machine.h (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+ * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Likewise.
+ (elf_machine_lazy_rel): Likewise.
+
2011-09-28 Ulrich Drepper <drepper@gmail.com>
* nss/nss_files/files-init.c (_nss_files_init): Use static
diff --git a/elf/dl-conflict.c b/elf/dl-conflict.c
index b730105628..653e446170 100644
--- a/elf/dl-conflict.c
+++ b/elf/dl-conflict.c
@@ -1,5 +1,5 @@
/* Resolve conflicts against already prelinked libraries.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001.
@@ -69,7 +69,8 @@ _dl_resolve_conflicts (struct link_map *l, ElfW(Rela) *conflict,
GL(dl_num_cache_relocations) += conflictend - conflict;
for (; conflict < conflictend; ++conflict)
- elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset);
+ elf_machine_rela (l, conflict, NULL, NULL, (void *) conflict->r_offset,
+ 0);
}
#endif
}
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 7294112346..c57b0f0a0d 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -162,6 +162,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
/* Initialize it to make the compiler happy. */
const char *errstring = NULL;
int lazy = reloc_mode & RTLD_LAZY;
+ int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
#ifdef SHARED
/* If we are auditing, install the same handlers we need for profiling. */
@@ -261,7 +262,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
#include "dynamic-link.h"
- ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling);
+ ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
#ifndef PROF
if (__builtin_expect (consider_profiling, 0))
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 990b9615e0..6187b9ed7a 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -1,5 +1,5 @@
/* Do relocations for ELF dynamic linking.
- Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2003, 2004, 2011 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -52,7 +52,7 @@
auto inline void __attribute__ ((always_inline))
elf_dynamic_do_rel (struct link_map *map,
ElfW(Addr) reladdr, ElfW(Addr) relsize,
- int lazy)
+ int lazy, int skip_ifunc)
{
const ElfW(Rel) *r = (const void *) reladdr;
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
@@ -66,7 +66,7 @@ elf_dynamic_do_rel (struct link_map *map,
{
/* Doing lazy PLT relocations; they need very little info. */
for (; r < end; ++r)
- elf_machine_lazy_rel (map, l_addr, r);
+ elf_machine_lazy_rel (map, l_addr, r, skip_ifunc);
}
else
#endif
@@ -119,14 +119,14 @@ elf_dynamic_do_rel (struct link_map *map,
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx],
- (void *) (l_addr + r->r_offset));
+ (void *) (l_addr + r->r_offset), skip_ifunc);
}
}
#ifndef RTLD_BOOTSTRAP
else
for (; r < end; ++r)
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
- (void *) (l_addr + r->r_offset));
+ (void *) (l_addr + r->r_offset), skip_ifunc);
#endif
}
}
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index 9c16da4ebe..2bdab45464 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -60,7 +60,7 @@ int internal_function _dl_try_allocate_static_tls (struct link_map *map);
auto inline void __attribute__((always_inline))
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version,
- void *const reloc_addr);
+ void *const reloc_addr, int skip_ifunc);
auto inline void __attribute__((always_inline))
elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
void *const reloc_addr);
@@ -69,7 +69,7 @@ elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
auto inline void __attribute__((always_inline))
elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version,
- void *const reloc_addr);
+ void *const reloc_addr, int skip_ifunc);
auto inline void __attribute__((always_inline))
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr);
@@ -77,11 +77,13 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
# if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
auto inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- ElfW(Addr) l_addr, const ElfW(Rel) *reloc);
+ ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
+ int skip_ifunc);
# else
auto inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- ElfW(Addr) l_addr, const ElfW(Rela) *reloc);
+ ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+ int skip_ifunc);
# endif
#endif
@@ -254,7 +256,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
not happen we do something more optimal. */
# ifdef ELF_MACHINE_PLTREL_OVERLAP
-# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
+# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
do { \
struct { ElfW(Addr) start, size; int lazy; } ranges[3]; \
int ranges_index; \
@@ -284,10 +286,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
elf_dynamic_do_##reloc ((map), \
ranges[ranges_index].start, \
ranges[ranges_index].size, \
- ranges[ranges_index].lazy); \
+ ranges[ranges_index].lazy, \
+ skip_ifunc); \
} while (0)
# else
-# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, test_rel) \
+# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
do { \
struct { ElfW(Addr) start, size; int lazy; } ranges[2]; \
ranges[0].lazy = 0; \
@@ -324,7 +327,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
} \
\
if (ELF_DURING_STARTUP) \
- elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, 0); \
+ elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size, 0, \
+ skip_ifunc); \
else \
{ \
int ranges_index; \
@@ -332,7 +336,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
elf_dynamic_do_##reloc ((map), \
ranges[ranges_index].start, \
ranges[ranges_index].size, \
- ranges[ranges_index].lazy); \
+ ranges[ranges_index].lazy, \
+ skip_ifunc); \
} \
} while (0)
# endif
@@ -345,29 +350,29 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
# if ! ELF_MACHINE_NO_REL
# include "do-rel.h"
-# define ELF_DYNAMIC_DO_REL(map, lazy) \
- _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, _ELF_CHECK_REL)
+# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \
+ _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, skip_ifunc, _ELF_CHECK_REL)
# else
-# define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do. */
+# define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do. */
# endif
# if ! ELF_MACHINE_NO_RELA
# define DO_RELA
# include "do-rel.h"
-# define ELF_DYNAMIC_DO_RELA(map, lazy) \
- _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL)
+# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \
+ _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, skip_ifunc, _ELF_CHECK_REL)
# else
-# define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do. */
+# define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do. */
# endif
/* This can't just be an inline function because GCC is too dumb
to inline functions containing inlines themselves. */
-# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile) \
+# define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc) \
do { \
int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \
(consider_profile)); \
- ELF_DYNAMIC_DO_REL ((map), edr_lazy); \
- ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \
+ ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc); \
+ ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc); \
} while (0)
#endif
diff --git a/elf/rtld.c b/elf/rtld.c
index 324d979107..e4e413f601 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -544,7 +544,7 @@ _dl_start (void *arg)
/* Relocate ourselves so we can do normal function calls and
data access using the global offset table. */
- ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
+ ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0);
}
bootstrap_map.l_relocated = 1;
@@ -1951,8 +1951,9 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
/* Relocate the main executable. */
struct relocate_args args = { .l = l,
- .reloc_mode = (GLRO(dl_lazy)
- ? RTLD_LAZY : 0) };
+ .reloc_mode = ((GLRO(dl_lazy)
+ ? RTLD_LAZY : 0)
+ | __RTLD_NOIFUNC) };
_dl_receive_error (print_unresolved, relocate_doit, &args);
/* This loop depends on the dependencies of the executable to
@@ -2029,7 +2030,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
struct relocate_args args;
unsigned int i;
- args.reloc_mode = GLRO(dl_lazy) ? RTLD_LAZY : 0;
+ args.reloc_mode = ((GLRO(dl_lazy) ? RTLD_LAZY : 0)
+ | __RTLD_NOIFUNC);
i = main_map->l_searchlist.r_nlist;
while (i-- > 0)
@@ -2049,7 +2051,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
/* Mark the link map as not yet relocated again. */
GL(dl_rtld_map).l_relocated = 0;
_dl_relocate_object (&GL(dl_rtld_map),
- main_map->l_scope, 0, 0);
+ main_map->l_scope, __RTLD_NOIFUNC, 0);
}
}
#define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))
diff --git a/include/dlfcn.h b/include/dlfcn.h
index af92483f59..9e76d35600 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -10,6 +10,7 @@
#define __RTLD_CALLMAP 0x10000000
#define __RTLD_AUDIT 0x08000000
#define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */
+#define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */
#define __LM_ID_CALLER -2
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index d1a83ee0f2..9469a2b5d3 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -305,7 +305,7 @@ auto inline void
__attribute ((always_inline))
elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
@@ -341,7 +341,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0)
- && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+ && __builtin_expect (!skip_ifunc, 1))
value = ((Elf32_Addr (*) (void)) value) ();
switch (r_type)
@@ -482,7 +483,7 @@ auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
@@ -499,8 +500,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
if (sym != NULL
&& __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
- && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
- 0))
+ && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
+ && __builtin_expect (!skip_ifunc, 1))
value = ((Elf32_Addr (*) (void)) value) ();
switch (ELF32_R_TYPE (reloc->r_info))
@@ -647,7 +648,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf32_Addr l_addr, const Elf32_Rel *reloc)
+ Elf32_Addr l_addr, const Elf32_Rel *reloc,
+ int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
@@ -698,19 +700,20 @@ elf_machine_lazy_rel (struct link_map *map,
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx],
- (void *) (l_addr + r->r_offset));
+ (void *) (l_addr + r->r_offset), skip_ifunc);
}
# ifndef RTLD_BOOTSTRAP
else
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
- (void *) (l_addr + r->r_offset));
+ (void *) (l_addr + r->r_offset), skip_ifunc);
# endif
}
}
else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
{
Elf32_Addr value = map->l_addr + *reloc_addr;
- value = ((Elf32_Addr (*) (void)) value) ();
+ if (__builtin_expect (!skip_ifunc, 1))
+ value = ((Elf32_Addr (*) (void)) value) ();
*reloc_addr = value;
}
else
@@ -722,7 +725,8 @@ elf_machine_lazy_rel (struct link_map *map,
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rela (struct link_map *map,
- Elf32_Addr l_addr, const Elf32_Rela *reloc)
+ Elf32_Addr l_addr, const Elf32_Rela *reloc,
+ int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
@@ -739,7 +743,8 @@ elf_machine_lazy_rela (struct link_map *map,
else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
{
Elf32_Addr value = map->l_addr + reloc->r_addend;
- value = ((Elf32_Addr (*) (void)) value) ();
+ if (__builtin_expect (!skip_ifunc, 1))
+ value = ((Elf32_Addr (*) (void)) value) ();
*reloc_addr = value;
}
else
diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h
index 6f88005482..6053b3b786 100644
--- a/sysdeps/ia64/dl-machine.h
+++ b/sysdeps/ia64/dl-machine.h
@@ -372,7 +372,8 @@ elf_machine_rela (struct link_map *map,
const Elf64_Rela *reloc,
const Elf64_Sym *sym,
const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg,
+ int skip_ifunc)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
@@ -486,7 +487,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
auto inline void
__attribute ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf64_Addr l_addr, const Elf64_Rela *reloc)
+ Elf64_Addr l_addr, const Elf64_Rela *reloc,
+ int skip_ifunc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index e7052b69d5..b24fee0962 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -272,7 +272,7 @@ extern void _dl_reloc_overflow (struct link_map *map,
auto inline void __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const Elf32_Sym *const refsym = sym;
@@ -307,7 +307,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
- && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+ && __builtin_expect (!skip_ifunc, 1))
value = ((Elf32_Addr (*) (void)) value) ();
/* A small amount of code is duplicated here for speed. In libc,
@@ -382,7 +383,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
auto inline void __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf32_Addr l_addr, const Elf32_Rela *reloc)
+ Elf32_Addr l_addr, const Elf32_Rela *reloc,
+ int skip_ifunc)
{
/* elf_machine_runtime_setup handles this. */
}
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index ab90d1e899..f4265bb157 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -556,7 +556,8 @@ elf_machine_rela (struct link_map *map,
const Elf64_Rela *reloc,
const Elf64_Sym *sym,
const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg,
+ int skip_ifunc)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
const int r_type = ELF64_R_TYPE (reloc->r_info);
@@ -579,7 +580,8 @@ elf_machine_rela (struct link_map *map,
if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
- && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+ && __builtin_expect (!skip_ifunc, 1))
value = resolve_ifunc (value, map, sym_map);
/* For relocs that don't edit code, return.
@@ -592,12 +594,14 @@ elf_machine_rela (struct link_map *map,
return;
case R_PPC64_IRELATIVE:
- value = resolve_ifunc (value, map, sym_map);
+ if (__builtin_expect (!skip_ifunc, 1))
+ value = resolve_ifunc (value, map, sym_map);
*reloc_addr = value;
return;
case R_PPC64_JMP_IREL:
- value = resolve_ifunc (value, map, sym_map);
+ if (__builtin_expect (!skip_ifunc, 1))
+ value = resolve_ifunc (value, map, sym_map);
/* Fall thru */
case R_PPC64_JMP_SLOT:
#ifdef RESOLVE_CONFLICT_FIND_MAP
@@ -846,7 +850,8 @@ elf_machine_rela (struct link_map *map,
auto inline void __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf64_Addr l_addr, const Elf64_Rela *reloc)
+ Elf64_Addr l_addr, const Elf64_Rela *reloc,
+ int skip_ifunc)
{
/* elf_machine_runtime_setup handles this. */
}
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
index b1f6f41640..ea7c6a68b9 100644
--- a/sysdeps/s390/s390-32/dl-machine.h
+++ b/sysdeps/s390/s390-32/dl-machine.h
@@ -275,7 +275,7 @@ auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
@@ -433,7 +433,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf32_Addr l_addr, const Elf32_Rela *reloc)
+ Elf32_Addr l_addr, const Elf32_Rela *reloc,
+ int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
index 913ea0870b..68015a7a00 100644
--- a/sysdeps/s390/s390-64/dl-machine.h
+++ b/sysdeps/s390/s390-64/dl-machine.h
@@ -247,7 +247,7 @@ auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
@@ -412,7 +412,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf64_Addr l_addr, const Elf64_Rela *reloc)
+ Elf64_Addr l_addr, const Elf64_Rela *reloc,
+ int skip_ifunc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index 4e09ea4eb5..e02f47cb00 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -262,7 +262,7 @@ auto inline void
__attribute ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
@@ -446,7 +446,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf32_Addr l_addr, const Elf32_Rela *reloc)
+ Elf32_Addr l_addr, const Elf32_Rela *reloc,
+ int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
/* Check for unexpected PLT reloc type. */
diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h
index 8f54f7e3ef..0ef5d2850b 100644
--- a/sysdeps/sparc/sparc32/dl-machine.h
+++ b/sysdeps/sparc/sparc32/dl-machine.h
@@ -342,7 +342,7 @@ auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = reloc_addr_arg;
const Elf32_Sym *const refsym = sym;
@@ -392,7 +392,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
- && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+ && __builtin_expect (!skip_ifunc, 1))
{
value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap));
}
@@ -546,7 +547,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf32_Addr l_addr, const Elf32_Rela *reloc)
+ Elf32_Addr l_addr, const Elf32_Rela *reloc,
+ int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
@@ -556,7 +558,8 @@ elf_machine_lazy_rel (struct link_map *map,
else if (r_type == R_SPARC_JMP_IREL)
{
Elf32_Addr value = map->l_addr + reloc->r_addend;
- value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap));
+ if (__builtin_expect (!skip_ifunc, 1))
+ value = ((Elf32_Addr (*) (int)) value) (GLRO(dl_hwcap));
sparc_fixup_plt (reloc, reloc_addr, value, 1, 1);
}
else if (r_type == R_SPARC_NONE)
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index 47579cd05f..501092e0ca 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -368,7 +368,7 @@ auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
@@ -422,7 +422,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
- && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+ && __builtin_expect (!skip_ifunc, 1))
value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
switch (r_type)
@@ -639,7 +640,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
auto inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf64_Addr l_addr, const Elf64_Rela *reloc)
+ Elf64_Addr l_addr, const Elf64_Rela *reloc,
+ int skip_ifunc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
@@ -650,7 +652,8 @@ elf_machine_lazy_rel (struct link_map *map,
|| r_type == R_SPARC_IRELATIVE)
{
Elf64_Addr value = map->l_addr + reloc->r_addend;
- value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
+ if (__builtin_expect (!skip_ifunc, 1))
+ value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
if (r_type == R_SPARC_JMP_IREL)
{
/* 'high' is always zero, for large PLT entries the linker
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index 4c31ac5da8..6d66ff69c7 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -255,7 +255,7 @@ auto inline void
__attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version,
- void *const reloc_addr_arg)
+ void *const reloc_addr_arg, int skip_ifunc)
{
Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
@@ -293,7 +293,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0)
- && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1))
+ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
+ && __builtin_expect (!skip_ifunc, 1))
value = ((Elf64_Addr (*) (void)) value) ();
switch (r_type)
@@ -459,7 +460,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
auto inline void
__attribute ((always_inline))
elf_machine_lazy_rel (struct link_map *map,
- Elf64_Addr l_addr, const Elf64_Rela *reloc)
+ Elf64_Addr l_addr, const Elf64_Rela *reloc,
+ int skip_ifunc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
@@ -486,7 +488,8 @@ elf_machine_lazy_rel (struct link_map *map,
else if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 0))
{
Elf64_Addr value = map->l_addr + reloc->r_addend;
- value = ((Elf64_Addr (*) (void)) value) ();
+ if (__builtin_expect (!skip_ifunc, 1))
+ value = ((Elf64_Addr (*) (void)) value) ();
*reloc_addr = value;
}
else