diff options
Diffstat (limited to 'sysdeps/s390/s390-32/dl-machine.h')
-rw-r--r-- | sysdeps/s390/s390-32/dl-machine.h | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h index 3eb7e41..e56ad67 100644 --- a/sysdeps/s390/s390-32/dl-machine.h +++ b/sysdeps/s390/s390-32/dl-machine.h @@ -1,6 +1,5 @@ /* Machine-dependent ELF dynamic relocation inline functions. S390 Version. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2012 Free Software Foundation, Inc. Contributed by Carl Pederson & Martin Schwidefsky. This file is part of the GNU C Library. @@ -27,6 +26,7 @@ #include <string.h> #include <link.h> #include <sysdeps/s390/dl-procinfo.h> +#include <dl-irel.h> /* This is an older, now obsolete value. */ #define EM_S390_OLD 0xA390 @@ -305,8 +305,21 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value; + 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 (!skip_ifunc, 1)) + value = elf_ifunc_invoke (value); + switch (r_type) { + case R_390_IRELATIVE: + value = map->l_addr + reloc->r_addend; + if (__builtin_expect (!skip_ifunc, 1)) + value = elf_ifunc_invoke (value); + *reloc_addr = value; + break; + case R_390_GLOB_DAT: case R_390_JMP_SLOT: *reloc_addr = value + reloc->r_addend; @@ -444,6 +457,13 @@ elf_machine_lazy_rel (struct link_map *map, map->l_mach.plt + (((Elf32_Addr) reloc_addr) - map->l_mach.gotplt) * 8; } + else if (__builtin_expect (r_type == R_390_IRELATIVE, 1)) + { + Elf32_Addr value = map->l_addr + reloc->r_addend; + if (__builtin_expect (!skip_ifunc, 1)) + value = elf_ifunc_invoke (value); + *reloc_addr = value; + } else _dl_reloc_bad_type (map, r_type, 1); } |