Skip to content

Commit

Permalink
Don't call ifunc functions in trace mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Andreas Schwab committed Oct 5, 2011
1 parent 6857791 commit 3a62d00
Show file tree
Hide file tree
Showing 17 changed files with 149 additions and 70 deletions.
43 changes: 43 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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
Expand Down
5 changes: 3 additions & 2 deletions elf/dl-conflict.c
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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
}
3 changes: 2 additions & 1 deletion elf/dl-reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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))
Expand Down
10 changes: 5 additions & 5 deletions elf/do-rel.h
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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
}
}
Expand Down
41 changes: 23 additions & 18 deletions elf/dynamic-link.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -69,19 +69,21 @@ 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);
# endif
# 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

Expand Down Expand Up @@ -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; \
Expand Down Expand Up @@ -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; \
Expand Down Expand Up @@ -324,15 +327,17 @@ 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; \
for (ranges_index = 0; ranges_index < 2; ++ranges_index) \
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
Expand All @@ -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
12 changes: 7 additions & 5 deletions elf/rtld.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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))
Expand Down
1 change: 1 addition & 0 deletions include/dlfcn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
27 changes: 16 additions & 11 deletions sysdeps/i386/dl-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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))
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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
Expand Down
6 changes: 4 additions & 2 deletions sysdeps/ia64/dl-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 3a62d00

Please sign in to comment.