summary refs log tree commit diff
path: root/sysdeps/s390/s390-32/dl-machine.h
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>2012-07-12 13:04:55 +0200
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>2012-07-19 15:46:34 +0200
commit08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96 (patch)
tree17318764c9e7b5e6c151def3bdab1fc30af377ed /sysdeps/s390/s390-32/dl-machine.h
parenta98430587c57da2832fa9abe336c5a8f8137e89c (diff)
downloadglibc-08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96.tar.gz
glibc-08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96.tar.xz
glibc-08f43f9bbf97c03ec4d2754c69fd9d7efce6ef96.zip
S/390: Add support for STT_GNU_IFUNC symbols.
Add support for STT_GNU_IFUNC symbols and the new R_390_IRELATIVE
relocation.  Provide optimized version of memcpy, memset, and memcmp
for z10 and z196.
Diffstat (limited to 'sysdeps/s390/s390-32/dl-machine.h')
-rw-r--r--sysdeps/s390/s390-32/dl-machine.h24
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 3eb7e41159..e56ad676cd 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);
 }