Don't call ifunc functions in trace mode
authorAndreas Schwab <schwab@redhat.com>
Tue, 4 Oct 2011 14:10:16 +0000 (16:10 +0200)
committerAndreas Schwab <schwab@redhat.com>
Wed, 5 Oct 2011 12:35:40 +0000 (14:35 +0200)
17 files changed:
ChangeLog
elf/dl-conflict.c
elf/dl-reloc.c
elf/do-rel.h
elf/dynamic-link.h
elf/rtld.c
include/dlfcn.h
sysdeps/i386/dl-machine.h
sysdeps/ia64/dl-machine.h
sysdeps/powerpc/powerpc32/dl-machine.h
sysdeps/powerpc/powerpc64/dl-machine.h
sysdeps/s390/s390-32/dl-machine.h
sysdeps/s390/s390-64/dl-machine.h
sysdeps/sh/dl-machine.h
sysdeps/sparc/sparc32/dl-machine.h
sysdeps/sparc/sparc64/dl-machine.h
sysdeps/x86_64/dl-machine.h

index a8ccdac..2fdde34 100644 (file)
--- 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
index b730105..653e446 100644 (file)
@@ -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
 }
index 7294112..c57b0f0 100644 (file)
@@ -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))
index 990b961..6187b9e 100644 (file)
@@ -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
     }
 }
index 9c16da4..2bdab45 100644 (file)
@@ -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
index 324d979..e4e413f 100644 (file)
@@ -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))
index af92483..9e76d35 100644 (file)
@@ -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
 
index d1a83ee..9469a2b 100644 (file)
@@ -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
index 6f88005..6053b3b 100644 (file)
@@ -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);
index e7052b6..b24fee0 100644 (file)
@@ -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. */
 }
index ab90d1e..f4265bb 100644 (file)
@@ -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.  */
 }
index b1f6f41..ea7c6a6 100644 (file)
@@ -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);
index 913ea08..68015a7 100644 (file)
@@ -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);
index 4e09ea4..e02f47c 100644 (file)
@@ -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.  */
index 8f54f7e..0ef5d28 100644 (file)
@@ -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)
index 47579cd..501092e 100644 (file)
@@ -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
index 4c31ac5..6d66ff6 100644 (file)
@@ -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