From 3a62d00d408e9ec19479b6c7d39e89021061f9cd Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 4 Oct 2011 16:10:16 +0200 Subject: [PATCH] Don't call ifunc functions in trace mode --- ChangeLog | 43 ++++++++++++++++++++++++++++++++++ elf/dl-conflict.c | 5 ++-- elf/dl-reloc.c | 3 ++- elf/do-rel.h | 10 ++++---- elf/dynamic-link.h | 41 ++++++++++++++++++-------------- elf/rtld.c | 12 ++++++---- include/dlfcn.h | 1 + sysdeps/i386/dl-machine.h | 27 ++++++++++++--------- sysdeps/ia64/dl-machine.h | 6 +++-- sysdeps/powerpc/powerpc32/dl-machine.h | 8 ++++--- sysdeps/powerpc/powerpc64/dl-machine.h | 15 ++++++++---- sysdeps/s390/s390-32/dl-machine.h | 5 ++-- sysdeps/s390/s390-64/dl-machine.h | 5 ++-- sysdeps/sh/dl-machine.h | 5 ++-- sysdeps/sparc/sparc32/dl-machine.h | 11 +++++---- sysdeps/sparc/sparc64/dl-machine.h | 11 +++++---- sysdeps/x86_64/dl-machine.h | 11 +++++---- 17 files changed, 149 insertions(+), 70 deletions(-) diff --git a/ChangeLog b/ChangeLog index a8ccdac..2fdde34 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +2011-10-04 Andreas Schwab + + * 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 * nss/nss_files/files-init.c (_nss_files_init): Use static diff --git a/elf/dl-conflict.c b/elf/dl-conflict.c index b730105..653e446 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 , 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 7294112..c57b0f0 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 990b961..6187b9e 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 9c16da4..2bdab45 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 324d979..e4e413f 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 af92483..9e76d35 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 d1a83ee..9469a2b 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 6f88005..6053b3b 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 e7052b6..b24fee0 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 ab90d1e..f4265bb 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 b1f6f41..ea7c6a6 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 913ea08..68015a7 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 4e09ea4..e02f47c 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 8f54f7e..0ef5d28 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 47579cd..501092e 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 4c31ac5..6d66ff6 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 -- 2.7.4