Don't call ifunc functions in trace mode

This commit is contained in:
Andreas Schwab 2011-10-04 16:10:16 +02:00
parent 6857791843
commit 3a62d00d40
17 changed files with 149 additions and 70 deletions

View File

@ -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> 2011-09-28 Ulrich Drepper <drepper@gmail.com>
* nss/nss_files/files-init.c (_nss_files_init): Use static * nss/nss_files/files-init.c (_nss_files_init): Use static

View File

@ -1,5 +1,5 @@
/* Resolve conflicts against already prelinked libraries. /* 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. This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2001. 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; GL(dl_num_cache_relocations) += conflictend - conflict;
for (; conflict < 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 #endif
} }

View File

@ -162,6 +162,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
/* Initialize it to make the compiler happy. */ /* Initialize it to make the compiler happy. */
const char *errstring = NULL; const char *errstring = NULL;
int lazy = reloc_mode & RTLD_LAZY; int lazy = reloc_mode & RTLD_LAZY;
int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
#ifdef SHARED #ifdef SHARED
/* If we are auditing, install the same handlers we need for profiling. */ /* 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" #include "dynamic-link.h"
ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling); ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
#ifndef PROF #ifndef PROF
if (__builtin_expect (consider_profiling, 0)) if (__builtin_expect (consider_profiling, 0))

View File

@ -1,5 +1,5 @@
/* Do relocations for ELF dynamic linking. /* 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. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -52,7 +52,7 @@
auto inline void __attribute__ ((always_inline)) auto inline void __attribute__ ((always_inline))
elf_dynamic_do_rel (struct link_map *map, elf_dynamic_do_rel (struct link_map *map,
ElfW(Addr) reladdr, ElfW(Addr) relsize, ElfW(Addr) reladdr, ElfW(Addr) relsize,
int lazy) int lazy, int skip_ifunc)
{ {
const ElfW(Rel) *r = (const void *) reladdr; const ElfW(Rel) *r = (const void *) reladdr;
const ElfW(Rel) *end = (const void *) (reladdr + relsize); 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. */ /* Doing lazy PLT relocations; they need very little info. */
for (; r < end; ++r) for (; r < end; ++r)
elf_machine_lazy_rel (map, l_addr, r); elf_machine_lazy_rel (map, l_addr, r, skip_ifunc);
} }
else else
#endif #endif
@ -119,14 +119,14 @@ elf_dynamic_do_rel (struct link_map *map,
ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff; ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx], &map->l_versions[ndx],
(void *) (l_addr + r->r_offset)); (void *) (l_addr + r->r_offset), skip_ifunc);
} }
} }
#ifndef RTLD_BOOTSTRAP #ifndef RTLD_BOOTSTRAP
else else
for (; r < end; ++r) for (; r < end; ++r)
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, 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 #endif
} }
} }

View File

@ -60,7 +60,7 @@ int internal_function _dl_try_allocate_static_tls (struct link_map *map);
auto inline void __attribute__((always_inline)) auto inline void __attribute__((always_inline))
elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc, elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version, 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)) auto inline void __attribute__((always_inline))
elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc, elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
void *const reloc_addr); 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)) auto inline void __attribute__((always_inline))
elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
const ElfW(Sym) *sym, const struct r_found_version *version, 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)) auto inline void __attribute__((always_inline))
elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc, elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
void *const reloc_addr); 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 # if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
auto inline void __attribute__((always_inline)) auto inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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 # else
auto inline void __attribute__((always_inline)) auto inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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
#endif #endif
@ -254,7 +256,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
not happen we do something more optimal. */ not happen we do something more optimal. */
# ifdef ELF_MACHINE_PLTREL_OVERLAP # 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 { \ do { \
struct { ElfW(Addr) start, size; int lazy; } ranges[3]; \ struct { ElfW(Addr) start, size; int lazy; } ranges[3]; \
int ranges_index; \ int ranges_index; \
@ -284,10 +286,11 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
elf_dynamic_do_##reloc ((map), \ elf_dynamic_do_##reloc ((map), \
ranges[ranges_index].start, \ ranges[ranges_index].start, \
ranges[ranges_index].size, \ ranges[ranges_index].size, \
ranges[ranges_index].lazy); \ ranges[ranges_index].lazy, \
skip_ifunc); \
} while (0) } while (0)
# else # 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 { \ do { \
struct { ElfW(Addr) start, size; int lazy; } ranges[2]; \ struct { ElfW(Addr) start, size; int lazy; } ranges[2]; \
ranges[0].lazy = 0; \ ranges[0].lazy = 0; \
@ -324,7 +327,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
} \ } \
\ \
if (ELF_DURING_STARTUP) \ 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 \ else \
{ \ { \
int ranges_index; \ int ranges_index; \
@ -332,7 +336,8 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
elf_dynamic_do_##reloc ((map), \ elf_dynamic_do_##reloc ((map), \
ranges[ranges_index].start, \ ranges[ranges_index].start, \
ranges[ranges_index].size, \ ranges[ranges_index].size, \
ranges[ranges_index].lazy); \ ranges[ranges_index].lazy, \
skip_ifunc); \
} \ } \
} while (0) } while (0)
# endif # endif
@ -345,29 +350,29 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
# if ! ELF_MACHINE_NO_REL # if ! ELF_MACHINE_NO_REL
# include "do-rel.h" # include "do-rel.h"
# define ELF_DYNAMIC_DO_REL(map, lazy) \ # define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \
_ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, _ELF_CHECK_REL) _ELF_DYNAMIC_DO_RELOC (REL, rel, map, lazy, skip_ifunc, _ELF_CHECK_REL)
# else # else
# define ELF_DYNAMIC_DO_REL(map, lazy) /* Nothing to do. */ # define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do. */
# endif # endif
# if ! ELF_MACHINE_NO_RELA # if ! ELF_MACHINE_NO_RELA
# define DO_RELA # define DO_RELA
# include "do-rel.h" # include "do-rel.h"
# define ELF_DYNAMIC_DO_RELA(map, lazy) \ # define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \
_ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, _ELF_CHECK_REL) _ELF_DYNAMIC_DO_RELOC (RELA, rela, map, lazy, skip_ifunc, _ELF_CHECK_REL)
# else # else
# define ELF_DYNAMIC_DO_RELA(map, lazy) /* Nothing to do. */ # define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do. */
# endif # endif
/* This can't just be an inline function because GCC is too dumb /* This can't just be an inline function because GCC is too dumb
to inline functions containing inlines themselves. */ 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 { \ do { \
int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \ int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \
(consider_profile)); \ (consider_profile)); \
ELF_DYNAMIC_DO_REL ((map), edr_lazy); \ ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc); \
ELF_DYNAMIC_DO_RELA ((map), edr_lazy); \ ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc); \
} while (0) } while (0)
#endif #endif

View File

@ -544,7 +544,7 @@ _dl_start (void *arg)
/* Relocate ourselves so we can do normal function calls and /* Relocate ourselves so we can do normal function calls and
data access using the global offset table. */ 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; 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. */ /* Relocate the main executable. */
struct relocate_args args = { .l = l, struct relocate_args args = { .l = l,
.reloc_mode = (GLRO(dl_lazy) .reloc_mode = ((GLRO(dl_lazy)
? RTLD_LAZY : 0) }; ? RTLD_LAZY : 0)
| __RTLD_NOIFUNC) };
_dl_receive_error (print_unresolved, relocate_doit, &args); _dl_receive_error (print_unresolved, relocate_doit, &args);
/* This loop depends on the dependencies of the executable to /* 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; struct relocate_args args;
unsigned int i; 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; i = main_map->l_searchlist.r_nlist;
while (i-- > 0) 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. */ /* Mark the link map as not yet relocated again. */
GL(dl_rtld_map).l_relocated = 0; GL(dl_rtld_map).l_relocated = 0;
_dl_relocate_object (&GL(dl_rtld_map), _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)) #define VERNEEDTAG (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX (DT_VERNEED))

View File

@ -10,6 +10,7 @@
#define __RTLD_CALLMAP 0x10000000 #define __RTLD_CALLMAP 0x10000000
#define __RTLD_AUDIT 0x08000000 #define __RTLD_AUDIT 0x08000000
#define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */ #define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */
#define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */
#define __LM_ID_CALLER -2 #define __LM_ID_CALLER -2

View File

@ -305,7 +305,7 @@ auto inline void
__attribute ((always_inline)) __attribute ((always_inline))
elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
const Elf32_Sym *sym, const struct r_found_version *version, 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; Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); 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 if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0) 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) (); value = ((Elf32_Addr (*) (void)) value) ();
switch (r_type) switch (r_type)
@ -482,7 +483,7 @@ auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version, 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; Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); 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 if (sym != NULL
&& __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
0)) && __builtin_expect (!skip_ifunc, 1))
value = ((Elf32_Addr (*) (void)) value) (); value = ((Elf32_Addr (*) (void)) value) ();
switch (ELF32_R_TYPE (reloc->r_info)) 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 auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); 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; ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
&map->l_versions[ndx], &map->l_versions[ndx],
(void *) (l_addr + r->r_offset)); (void *) (l_addr + r->r_offset), skip_ifunc);
} }
# ifndef RTLD_BOOTSTRAP # ifndef RTLD_BOOTSTRAP
else else
elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL, 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 # endif
} }
} }
else if (__builtin_expect (r_type == R_386_IRELATIVE, 0)) else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
{ {
Elf32_Addr value = map->l_addr + *reloc_addr; 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; *reloc_addr = value;
} }
else else
@ -722,7 +725,8 @@ elf_machine_lazy_rel (struct link_map *map,
auto inline void auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_lazy_rela (struct link_map *map, 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); Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); 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)) else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
{ {
Elf32_Addr value = map->l_addr + reloc->r_addend; 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; *reloc_addr = value;
} }
else else

View File

@ -372,7 +372,8 @@ elf_machine_rela (struct link_map *map,
const Elf64_Rela *reloc, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const Elf64_Sym *sym,
const struct r_found_version *version, 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; Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); 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 auto inline void
__attribute ((always_inline)) __attribute ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);

View File

@ -272,7 +272,7 @@ extern void _dl_reloc_overflow (struct link_map *map,
auto inline void __attribute__ ((always_inline)) auto inline void __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version, 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; Elf32_Addr *const reloc_addr = reloc_addr_arg;
const Elf32_Sym *const refsym = sym; const Elf32_Sym *const refsym = sym;
@ -307,7 +307,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
if (sym != NULL if (sym != NULL
&& __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 (sym->st_shndx != SHN_UNDEF, 1)) && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
&& __builtin_expect (!skip_ifunc, 1))
value = ((Elf32_Addr (*) (void)) value) (); value = ((Elf32_Addr (*) (void)) value) ();
/* A small amount of code is duplicated here for speed. In libc, /* 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)) auto inline void __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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. */ /* elf_machine_runtime_setup handles this. */
} }

View File

@ -556,7 +556,8 @@ elf_machine_rela (struct link_map *map,
const Elf64_Rela *reloc, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const Elf64_Sym *sym,
const struct r_found_version *version, 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; Elf64_Addr *const reloc_addr = reloc_addr_arg;
const int r_type = ELF64_R_TYPE (reloc->r_info); const int r_type = ELF64_R_TYPE (reloc->r_info);
@ -579,7 +580,8 @@ elf_machine_rela (struct link_map *map,
if (sym != NULL if (sym != NULL
&& __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 (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); value = resolve_ifunc (value, map, sym_map);
/* For relocs that don't edit code, return. /* For relocs that don't edit code, return.
@ -592,12 +594,14 @@ elf_machine_rela (struct link_map *map,
return; return;
case R_PPC64_IRELATIVE: 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; *reloc_addr = value;
return; return;
case R_PPC64_JMP_IREL: 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 */ /* Fall thru */
case R_PPC64_JMP_SLOT: case R_PPC64_JMP_SLOT:
#ifdef RESOLVE_CONFLICT_FIND_MAP #ifdef RESOLVE_CONFLICT_FIND_MAP
@ -846,7 +850,8 @@ elf_machine_rela (struct link_map *map,
auto inline void __attribute__ ((always_inline)) auto inline void __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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. */ /* elf_machine_runtime_setup handles this. */
} }

View File

@ -275,7 +275,7 @@ auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version, 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; Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); 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 auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);

View File

@ -247,7 +247,7 @@ auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version, 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; Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info); 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 auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info); const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);

View File

@ -262,7 +262,7 @@ auto inline void
__attribute ((always_inline)) __attribute ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version, 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; Elf32_Addr *const reloc_addr = reloc_addr_arg;
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); 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 auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
/* Check for unexpected PLT reloc type. */ /* Check for unexpected PLT reloc type. */

View File

@ -342,7 +342,7 @@ auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
const Elf32_Sym *sym, const struct r_found_version *version, 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; Elf32_Addr *const reloc_addr = reloc_addr_arg;
const Elf32_Sym *const refsym = sym; const Elf32_Sym *const refsym = sym;
@ -392,7 +392,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
if (sym != NULL if (sym != NULL
&& __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 (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)); 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 auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info); 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) else if (r_type == R_SPARC_JMP_IREL)
{ {
Elf32_Addr value = map->l_addr + reloc->r_addend; 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); sparc_fixup_plt (reloc, reloc_addr, value, 1, 1);
} }
else if (r_type == R_SPARC_NONE) else if (r_type == R_SPARC_NONE)

View File

@ -368,7 +368,7 @@ auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version, 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; Elf64_Addr *const reloc_addr = reloc_addr_arg;
#if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP #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 if (sym != NULL
&& __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 (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)); value = ((Elf64_Addr (*) (int)) value) (GLRO(dl_hwcap));
switch (r_type) switch (r_type)
@ -639,7 +640,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
auto inline void auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info); 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) || r_type == R_SPARC_IRELATIVE)
{ {
Elf64_Addr value = map->l_addr + reloc->r_addend; 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) if (r_type == R_SPARC_JMP_IREL)
{ {
/* 'high' is always zero, for large PLT entries the linker /* 'high' is always zero, for large PLT entries the linker

View File

@ -255,7 +255,7 @@ auto inline void
__attribute__ ((always_inline)) __attribute__ ((always_inline))
elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
const Elf64_Sym *sym, const struct r_found_version *version, 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; Elf64_Addr *const reloc_addr = reloc_addr_arg;
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); 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 if (sym != NULL
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
0) 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) (); value = ((Elf64_Addr (*) (void)) value) ();
switch (r_type) switch (r_type)
@ -459,7 +460,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
auto inline void auto inline void
__attribute ((always_inline)) __attribute ((always_inline))
elf_machine_lazy_rel (struct link_map *map, 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); Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); 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)) else if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 0))
{ {
Elf64_Addr value = map->l_addr + reloc->r_addend; 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; *reloc_addr = value;
} }
else else