about summary refs log tree commit diff
path: root/sysdeps/i386/dl-machine.h
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2009-05-31 23:45:33 -0700
committerUlrich Drepper <drepper@redhat.com>2009-05-31 23:45:33 -0700
commit74414708355a922a514d5c76183eca6931c4488a (patch)
tree60dd084df2e9f02464f66b0da2068f4561856458 /sysdeps/i386/dl-machine.h
parent963cb6fcb47ca212c0c57cc57bd7510f6549579c (diff)
downloadglibc-74414708355a922a514d5c76183eca6931c4488a.tar.gz
glibc-74414708355a922a514d5c76183eca6931c4488a.tar.xz
glibc-74414708355a922a514d5c76183eca6931c4488a.zip
Finish IFUNC support for x86 and x86-64.
Add support for the IRELAIVE relocation and IFUNC in static executables.
Diffstat (limited to 'sysdeps/i386/dl-machine.h')
-rw-r--r--sysdeps/i386/dl-machine.h24
1 files changed, 24 insertions, 0 deletions
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 0e15878d4e..efa929e57f 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -345,6 +345,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
       Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
 
       if (sym != NULL
+	  && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
 	  && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
 			       0))
 	value = ((Elf32_Addr (*) (void)) value) ();
@@ -471,6 +472,11 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	  memcpy (reloc_addr_arg, (void *) value,
 		  MIN (sym->st_size, refsym->st_size));
 	  break;
+	case R_386_IRELATIVE:
+	  value = map->l_addr + *reloc_addr;
+	  value = ((Elf32_Addr (*) (void)) value) ();
+	  *reloc_addr = value;
+	  break;
 	default:
 	  _dl_reloc_bad_type (map, r_type, 0);
 	  break;
@@ -500,6 +506,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
       Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
 
       if (sym != NULL
+	  && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
 	  && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC,
 			       0))
 	value = ((Elf32_Addr (*) (void)) value) ();
@@ -609,6 +616,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 		  MIN (sym->st_size, refsym->st_size));
 	  break;
 #  endif /* !RESOLVE_CONFLICT_FIND_MAP */
+	case R_386_IRELATIVE:
+	  value = map->l_addr + reloc->r_addend;
+	  value = ((Elf32_Addr (*) (void)) value) ();
+	  *reloc_addr = value;
+	  break;
 	default:
 	  /* We add these checks in the version to relocate ld.so only
 	     if we are still debugging.  */
@@ -703,6 +715,12 @@ elf_machine_lazy_rel (struct link_map *map,
 # endif
 	}
     }
+  else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
+    {
+      Elf32_Addr value = map->l_addr + *reloc_addr;
+      value = ((Elf32_Addr (*) (void)) value) ();
+      *reloc_addr = value;
+    }
   else
     _dl_reloc_bad_type (map, r_type, 1);
 }
@@ -726,6 +744,12 @@ elf_machine_lazy_rela (struct link_map *map,
       td->arg = (void*)reloc;
       td->entry = _dl_tlsdesc_resolve_rela;
     }
+  else if (__builtin_expect (r_type == R_386_IRELATIVE, 0))
+    {
+      Elf32_Addr value = map->l_addr + reloc->r_addend;
+      value = ((Elf32_Addr (*) (void)) value) ();
+      *reloc_addr = value;
+    }
   else
     _dl_reloc_bad_type (map, r_type, 1);
 }