Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Dec 2011 11:03:15 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r228435 - in head/libexec/rtld-elf: . amd64 arm i386 ia64 mips powerpc powerpc64 sparc64
Message-ID:  <201112121103.pBCB3FuT097580@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Mon Dec 12 11:03:14 2011
New Revision: 228435
URL: http://svn.freebsd.org/changeset/base/228435

Log:
  Add support for STT_GNU_IFUNC and R_MACHINE_IRELATIVE GNU extensions to
  rtld on 386 and amd64. This adds runtime bits neccessary for the use
  of the dispatch functions from the dynamically-linked executables and
  shared libraries.
  
  To allow use of external references from the dispatch function, resolution
  of the R_MACHINE_IRESOLVE relocations in PLT is postponed until GOT entries
  for PLT are prepared, and normal resolution of the GOT entries is finished.
  Similar to how it is done by GNU, IRELATIVE relocations are resolved in
  advance, instead of normal lazy handling for PLT.
  
  Move the init_pltgot() call before the relocations for the object are
  processed.
  
  MFC after:	3 weeks

Modified:
  head/libexec/rtld-elf/amd64/reloc.c
  head/libexec/rtld-elf/arm/reloc.c
  head/libexec/rtld-elf/i386/reloc.c
  head/libexec/rtld-elf/ia64/reloc.c
  head/libexec/rtld-elf/mips/reloc.c
  head/libexec/rtld-elf/powerpc/reloc.c
  head/libexec/rtld-elf/powerpc64/reloc.c
  head/libexec/rtld-elf/rtld.c
  head/libexec/rtld-elf/rtld.h
  head/libexec/rtld-elf/sparc64/reloc.c

Modified: head/libexec/rtld-elf/amd64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/amd64/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/amd64/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -344,11 +344,22 @@ reloc_plt(Obj_Entry *obj)
     for (rela = obj->pltrela;  rela < relalim;  rela++) {
 	Elf_Addr *where;
 
-	assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT);
-
-	/* Relocate the GOT slot pointing into the PLT. */
-	where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-	*where += (Elf_Addr)obj->relocbase;
+	switch(ELF_R_TYPE(rela->r_info)) {
+	case R_X86_64_JMP_SLOT:
+	  /* Relocate the GOT slot pointing into the PLT. */
+	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	  *where += (Elf_Addr)obj->relocbase;
+	  break;
+
+	case R_X86_64_IRELATIVE:
+	  obj->irelative = true;
+	  break;
+
+	default:
+	  _rtld_error("Unknown relocation type %x in PLT",
+	    (unsigned int)ELF_R_TYPE(rela->r_info));
+	  return (-1);
+	}
     }
     return 0;
 }
@@ -368,19 +379,91 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockS
 	const Elf_Sym *def;
 	const Obj_Entry *defobj;
 
-	assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT);
-	where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-	def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL,
-	    lockstate);
-	if (def == NULL)
-	    return -1;
-	target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend);
-	reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
+	switch (ELF_R_TYPE(rela->r_info)) {
+	case R_X86_64_JMP_SLOT:
+	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL,
+	      lockstate);
+	  if (def == NULL)
+	      return (-1);
+	  if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+	      obj->gnu_ifunc = true;
+	      continue;
+	  }
+	  target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend);
+	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
+	  break;
+
+	case R_X86_64_IRELATIVE:
+	  break;
+
+	default:
+	  _rtld_error("Unknown relocation type %x in PLT",
+	    (unsigned int)ELF_R_TYPE(rela->r_info));
+	  return (-1);
+	}
     }
     obj->jmpslots_done = true;
     return 0;
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
+{
+    const Elf_Rela *relalim;
+    const Elf_Rela *rela;
+
+    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
+    for (rela = obj->pltrela;  rela < relalim;  rela++) {
+	Elf_Addr *where, target, *ptr;
+
+	switch (ELF_R_TYPE(rela->r_info)) {
+	case R_X86_64_JMP_SLOT:
+	  break;
+
+	case R_X86_64_IRELATIVE:
+	  ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
+	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	  target = ((Elf_Addr (*)(void))ptr)();
+	  *where = target;
+	  break;
+	}
+    }
+    return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, RtldLockState *lockstate)
+{
+    const Elf_Rela *relalim;
+    const Elf_Rela *rela;
+
+    if (!obj->gnu_ifunc)
+	return (0);
+    relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize);
+    for (rela = obj->pltrela;  rela < relalim;  rela++) {
+	Elf_Addr *where, target;
+	const Elf_Sym *def;
+	const Obj_Entry *defobj;
+
+	switch (ELF_R_TYPE(rela->r_info)) {
+	case R_X86_64_JMP_SLOT:
+	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	  def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL,
+	      lockstate);
+	  if (def == NULL)
+	      return (-1);
+	  if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
+	      continue;
+	  target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
+	  reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela);
+	  break;
+	}
+    }
+    obj->gnu_ifunc = false;
+    return 0;
+}
+
 void
 allocate_initial_tls(Obj_Entry *objs)
 {

Modified: head/libexec/rtld-elf/arm/reloc.c
==============================================================================
--- head/libexec/rtld-elf/arm/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/arm/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -337,6 +337,22 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockS
 	return (0);
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
 Elf_Addr
 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
     		const Obj_Entry *obj, const Elf_Rel *rel)

Modified: head/libexec/rtld-elf/i386/reloc.c
==============================================================================
--- head/libexec/rtld-elf/i386/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/i386/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -298,13 +298,24 @@ reloc_plt(Obj_Entry *obj)
 
     rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
     for (rel = obj->pltrel;  rel < rellim;  rel++) {
-	Elf_Addr *where;
+	Elf_Addr *where/*, val*/;
 
-	assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
-
-	/* Relocate the GOT slot pointing into the PLT. */
-	where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
-	*where += (Elf_Addr)obj->relocbase;
+	switch (ELF_R_TYPE(rel->r_info)) {
+	case R_386_JMP_SLOT:
+	  /* Relocate the GOT slot pointing into the PLT. */
+	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+	  *where += (Elf_Addr)obj->relocbase;
+	  break;
+
+	case R_386_IRELATIVE:
+	  obj->irelative = true;
+	  break;
+
+	default:
+	  _rtld_error("Unknown relocation type %x in PLT",
+	    ELF_R_TYPE(rel->r_info));
+	  return (-1);
+	}
     }
     return 0;
 }
@@ -324,19 +335,88 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockS
 	const Elf_Sym *def;
 	const Obj_Entry *defobj;
 
-	assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
-	where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
-	def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
-	    lockstate);
-	if (def == NULL)
-	    return -1;
-	target = (Elf_Addr)(defobj->relocbase + def->st_value);
-	reloc_jmpslot(where, target, defobj, obj, rel);
+	switch (ELF_R_TYPE(rel->r_info)) {
+	case R_386_JMP_SLOT:
+	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+	  def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
+	      lockstate);
+	  if (def == NULL)
+	      return (-1);
+	  if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+	      obj->gnu_ifunc = true;
+	      continue;
+	  }
+	  target = (Elf_Addr)(defobj->relocbase + def->st_value);
+	  reloc_jmpslot(where, target, defobj, obj, rel);
+	  break;
+
+	case R_386_IRELATIVE:
+	  break;
+
+	default:
+	  _rtld_error("Unknown relocation type %x in PLT",
+	    ELF_R_TYPE(rel->r_info));
+	  return (-1);
+	}
     }
+
     obj->jmpslots_done = true;
     return 0;
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
+{
+    const Elf_Rel *rellim;
+    const Elf_Rel *rel;
+    Elf_Addr *where, target;
+
+    rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
+    for (rel = obj->pltrel;  rel < rellim;  rel++) {
+	switch (ELF_R_TYPE(rel->r_info)) {
+	case R_386_IRELATIVE:
+	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+	  target = ((Elf_Addr (*)(void))(*where))();
+	  *where = target;
+	  break;
+	}
+    }
+    return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, RtldLockState *lockstate)
+{
+    const Elf_Rel *rellim;
+    const Elf_Rel *rel;
+
+    if (!obj->gnu_ifunc)
+	return (0);
+    rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize);
+    for (rel = obj->pltrel;  rel < rellim;  rel++) {
+	Elf_Addr *where, target;
+	const Elf_Sym *def;
+	const Obj_Entry *defobj;
+
+	switch (ELF_R_TYPE(rel->r_info)) {
+	case R_386_JMP_SLOT:
+	  where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+	  def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL,
+	      lockstate);
+	  if (def == NULL)
+	      return (-1);
+	  if (ELF_ST_TYPE(def->st_info) != STT_GNU_IFUNC)
+	      continue;
+	  target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
+	  reloc_jmpslot(where, target, defobj, obj, rel);
+	  break;
+	}
+    }
+
+    obj->gnu_ifunc = false;
+    return (0);
+}
+
 void
 allocate_initial_tls(Obj_Entry *objs)
 {

Modified: head/libexec/rtld-elf/ia64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/ia64/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/ia64/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -435,6 +435,22 @@ reloc_plt(Obj_Entry *obj)
 	return 0;
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
 /* Relocate the jump slots in an object. */
 int
 reloc_jmpslots(Obj_Entry *obj, RtldLockState *lockstate)

Modified: head/libexec/rtld-elf/mips/reloc.c
==============================================================================
--- head/libexec/rtld-elf/mips/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/mips/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -498,6 +498,22 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockS
 	return (0);
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
 Elf_Addr
 reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj,
     		const Obj_Entry *obj, const Elf_Rel *rel)

Modified: head/libexec/rtld-elf/powerpc/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/powerpc/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -504,6 +504,21 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr
 	return (target);
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
 
 /*
  * Setup the plt glue routines.

Modified: head/libexec/rtld-elf/powerpc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc64/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/powerpc64/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -456,6 +456,22 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr
 	return (target);
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
 void
 init_pltgot(Obj_Entry *obj)
 {

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/rtld.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -561,6 +561,17 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_
     return (func_ptr_type) obj_main->entry;
 }
 
+void *
+rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def)
+{
+	void *ptr;
+	Elf_Addr target;
+
+	ptr = (void *)make_function_pointer(def, obj);
+	target = ((Elf_Addr (*)(void))ptr)();
+	return ((void *)target);
+}
+
 Elf_Addr
 _rtld_bind(Obj_Entry *obj, Elf_Size reloff)
 {
@@ -584,8 +595,10 @@ _rtld_bind(Obj_Entry *obj, Elf_Size relo
 	&lockstate);
     if (def == NULL)
 	die();
-
-    target = (Elf_Addr)(defobj->relocbase + def->st_value);
+    if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC)
+	target = (Elf_Addr)rtld_resolve_ifunc(defobj, def);
+    else
+	target = (Elf_Addr)(defobj->relocbase + def->st_value);
 
     dbg("\"%s\" in \"%s\" ==> %p in \"%s\"",
       defobj->strtab + def->st_name, basename(obj->path),
@@ -1944,6 +1957,10 @@ relocate_objects(Obj_Entry *first, bool 
 	    }
 	}
 
+
+	/* Set the special PLT or GOT entries. */
+	init_pltgot(obj);
+
 	/* Process the PLT relocations. */
 	if (reloc_plt(obj) == -1)
 	    return -1;
@@ -1952,7 +1969,6 @@ relocate_objects(Obj_Entry *first, bool 
 	    if (reloc_jmpslots(obj, lockstate) == -1)
 		return -1;
 
-
 	/*
 	 * Set up the magic number and version in the Obj_Entry.  These
 	 * were checked in the crt1.o from the original ElfKit, so we
@@ -1960,11 +1976,26 @@ relocate_objects(Obj_Entry *first, bool 
 	 */
 	obj->magic = RTLD_MAGIC;
 	obj->version = RTLD_VERSION;
-
-	/* Set the special PLT or GOT entries. */
-	init_pltgot(obj);
     }
 
+    /*
+     * The handling of R_MACHINE_IRELATIVE relocations and jumpslots
+     * referencing STT_GNU_IFUNC symbols is postponed till the other
+     * relocations are done.  The indirect functions specified as
+     * ifunc are allowed to call other symbols, so we need to have
+     * objects relocated before asking for resolution from indirects.
+     *
+     * The R_MACHINE_IRELATIVE slots are resolved in greedy fashion,
+     * instead of the usual lazy handling of PLT slots.  It is
+     * consistent with how GNU does it.
+     */
+    for (obj = first;  obj != NULL;  obj = obj->next) {
+	if (obj->irelative && reloc_iresolve(obj, lockstate) == -1)
+	    return (-1);
+	if ((obj->bind_now || bind_now) && obj->gnu_ifunc &&
+	  reloc_gnu_ifunc(obj, lockstate) == -1)
+	    return (-1);
+    }
     return 0;
 }
 
@@ -2376,9 +2407,11 @@ do_dlsym(void *handle, const char *name,
 	 * the relocated value of the symbol.
 	 */
 	if (ELF_ST_TYPE(def->st_info) == STT_FUNC)
-	    return make_function_pointer(def, defobj);
+	    return (make_function_pointer(def, defobj));
+	else if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC)
+	    return (rtld_resolve_ifunc(defobj, def));
 	else
-	    return defobj->relocbase + def->st_value;
+	    return (defobj->relocbase + def->st_value);
     }
 
     _rtld_error("Undefined symbol \"%s\"", name);
@@ -2822,6 +2855,8 @@ get_program_var_addr(const char *name, R
     if (ELF_ST_TYPE(req.sym_out->st_info) == STT_FUNC)
 	return ((const void **)make_function_pointer(req.sym_out,
 	  req.defobj_out));
+    else if (ELF_ST_TYPE(req.sym_out->st_info) == STT_GNU_IFUNC)
+	return ((const void **)rtld_resolve_ifunc(req.defobj_out, req.sym_out));
     else
 	return ((const void **)(req.defobj_out->relocbase +
 	  req.sym_out->st_value));
@@ -3088,6 +3123,7 @@ symlook_obj1(SymLook *req, const Obj_Ent
 	case STT_FUNC:
 	case STT_NOTYPE:
 	case STT_OBJECT:
+	case STT_GNU_IFUNC:
 	    if (symp->st_value == 0)
 		continue;
 		/* fallthrough */

Modified: head/libexec/rtld-elf/rtld.h
==============================================================================
--- head/libexec/rtld-elf/rtld.h	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/rtld.h	Mon Dec 12 11:03:14 2011	(r228435)
@@ -230,6 +230,8 @@ typedef struct Struct_Obj_Entry {
     bool on_fini_list: 1;	/* Object is already on fini list. */
     bool dag_inited : 1;	/* Object has its DAG initialized. */
     bool filtees_loaded : 1;	/* Filtees loaded */
+    bool irelative : 1;		/* Object has R_MACHDEP_IRELATIVE relocs */
+    bool gnu_ifunc : 1;		/* Object has references to STT_GNU_IFUNC */
 
     struct link_map linkmap;	/* For GDB and dlinfo() */
     Objlist dldags;		/* Object belongs to these dlopened DAGs (%) */
@@ -317,6 +319,7 @@ void lockdflt_init(void);
 void obj_free(Obj_Entry *);
 Obj_Entry *obj_new(void);
 void _rtld_bind_start(void);
+void *rtld_resolve_ifunc(const Obj_Entry *obj, const Elf_Sym *def);
 void symlook_init(SymLook *, const char *);
 int symlook_obj(SymLook *, const Obj_Entry *);
 void *tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset);
@@ -334,6 +337,8 @@ int do_copy_relocations(Obj_Entry *);
 int reloc_non_plt(Obj_Entry *, Obj_Entry *, struct Struct_RtldLockState *);
 int reloc_plt(Obj_Entry *);
 int reloc_jmpslots(Obj_Entry *, struct Struct_RtldLockState *);
+int reloc_iresolve(Obj_Entry *, struct Struct_RtldLockState *);
+int reloc_gnu_ifunc(Obj_Entry *, struct Struct_RtldLockState *);
 void allocate_initial_tls(Obj_Entry *);
 
 #endif /* } */

Modified: head/libexec/rtld-elf/sparc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/sparc64/reloc.c	Mon Dec 12 10:10:49 2011	(r228434)
+++ head/libexec/rtld-elf/sparc64/reloc.c	Mon Dec 12 11:03:14 2011	(r228435)
@@ -550,6 +550,22 @@ reloc_jmpslots(Obj_Entry *obj, RtldLockS
 	return (0);
 }
 
+int
+reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
+reloc_gnu_ifunc(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
 Elf_Addr
 reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *obj,
     const Obj_Entry *refobj, const Elf_Rel *rel)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112121103.pBCB3FuT097580>