Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Aug 2014 09:29:11 +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: r270798 - in head/libexec/rtld-elf: . amd64 arm i386 mips powerpc powerpc64 sparc64
Message-ID:  <201408290929.s7T9TBBI039170@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Fri Aug 29 09:29:10 2014
New Revision: 270798
URL: http://svnweb.freebsd.org/changeset/base/270798

Log:
  IFUNC symbol type shall be processed for non-PLT relocations,
  e.g. when a global variable is initialized with a pointer to ifunc.
  Add symbol type check and call resolver for STT_GNU_IFUNC symbol types
  when processing non-PLT relocations, but only after non-IFUNC
  relocations are done.  The two-phase proceessing is required since
  resolvers may reference other symbols, which must be ready to use when
  resolver calls are done.
  
  Restructure reloc_non_plt() on x86 to call find_symdef() and handle
  IFUNC in single place.
  
  For non-x86 reloc_non_plt(), check for call for IFUNC relocation and
  do nothing, to avoid processing relocs twice.
  
  PR:	193048
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 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/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	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/amd64/reloc.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -125,213 +125,186 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry 
 	const Elf_Rela *relalim;
 	const Elf_Rela *rela;
 	SymCache *cache;
-	int r = -1;
+	const Elf_Sym *def;
+	const Obj_Entry *defobj;
+	Elf_Addr *where, symval;
+	Elf32_Addr *where32;
+	int r;
 
+	r = -1;
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().
 	 */
 	if (obj != obj_rtld) {
-	    cache = calloc(obj->dynsymcount, sizeof(SymCache));
-	    /* No need to check for NULL here */
+		cache = calloc(obj->dynsymcount, sizeof(SymCache));
+		/* No need to check for NULL here */
 	} else
-	    cache = NULL;
+		cache = NULL;
 
-	relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
+	relalim = (const Elf_Rela *)((caddr_t)obj->rela + obj->relasize);
 	for (rela = obj->rela;  rela < relalim;  rela++) {
-	    Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
-	    Elf32_Addr *where32 = (Elf32_Addr *)where;
-
-	    switch (ELF_R_TYPE(rela->r_info)) {
-
-	    case R_X86_64_NONE:
-		break;
-
-	    case R_X86_64_64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where = (Elf_Addr) (defobj->relocbase + def->st_value + rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_PC32:
-		/*
-		 * I don't think the dynamic linker should ever see this
-		 * type of relocation.  But the binutils-2.6 tools sometimes
-		 * generate it.
-		 */
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where32 = (Elf32_Addr) (unsigned long) (defobj->relocbase +
-		        def->st_value + rela->r_addend - (Elf_Addr) where);
-		}
-		break;
-	/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
-
-	    case R_X86_64_COPY:
 		/*
-		 * These are deferred until all other relocations have
-		 * been done.  All we do here is make sure that the COPY
-		 * relocation is not in a shared library.  They are allowed
-		 * only in executable files.
+		 * First, resolve symbol for relocations which
+		 * reference symbols.
 		 */
-		if (!obj->mainprog) {
-		    _rtld_error("%s: Unexpected R_X86_64_COPY relocation"
-		      " in shared library", obj->path);
-		    goto done;
-		}
-		break;
-
-	    case R_X86_64_GLOB_DAT:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where = (Elf_Addr) (defobj->relocbase + def->st_value);
-		}
-		break;
-
-	    case R_X86_64_TPOFF64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    /*
-		     * We lazily allocate offsets for static TLS as we
-		     * see the first relocation that references the
-		     * TLS block. This allows us to support (small
-		     * amounts of) static TLS in dynamically loaded
-		     * modules. If we run out of space, we generate an
-		     * error.
-		     */
-		    if (!defobj->tls_done) {
-			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
-			    _rtld_error("%s: No space available for static "
-					"Thread Local Storage", obj->path);
-			    goto done;
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_X86_64_64:
+		case R_X86_64_PC32:
+		case R_X86_64_GLOB_DAT:
+		case R_X86_64_TPOFF64:
+		case R_X86_64_TPOFF32:
+		case R_X86_64_DTPMOD64:
+		case R_X86_64_DTPOFF64:
+		case R_X86_64_DTPOFF32:
+			def = find_symdef(ELF_R_SYM(rela->r_info), obj,
+			    &defobj, flags, cache, lockstate);
+			if (def == NULL)
+				goto done;
+			/*
+			 * If symbol is IFUNC, only perform relocation
+			 * when caller allowed it by passing
+			 * SYMLOOK_IFUNC flag.  Skip the relocations
+			 * otherwise.
+			 *
+			 * Also error out in case IFUNC relocations
+			 * are specified for TLS, which cannot be
+			 * usefully interpreted.
+			 */
+			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+				switch (ELF_R_TYPE(rela->r_info)) {
+				case R_X86_64_64:
+				case R_X86_64_PC32:
+				case R_X86_64_GLOB_DAT:
+					if ((flags & SYMLOOK_IFUNC) == 0)
+						continue;
+					symval = (Elf_Addr)rtld_resolve_ifunc(
+					    defobj, def);
+					break;
+				case R_X86_64_TPOFF64:
+				case R_X86_64_TPOFF32:
+				case R_X86_64_DTPMOD64:
+				case R_X86_64_DTPOFF64:
+				case R_X86_64_DTPOFF32:
+					_rtld_error("%s: IFUNC for TLS reloc",
+					    obj->path);
+					goto done;
+				}
+			} else {
+				if ((flags & SYMLOOK_IFUNC) != 0)
+					continue;
+				symval = (Elf_Addr)defobj->relocbase +
+				    def->st_value;
 			}
-		    }
-
-		    *where = (Elf_Addr) (def->st_value - defobj->tlsoffset +
-					 rela->r_addend);
+			break;
+		default:
+			if ((flags & SYMLOOK_IFUNC) != 0)
+				continue;
+			break;
 		}
-		break;
-
-	    case R_X86_64_TPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
+		where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+		where32 = (Elf32_Addr *)where;
 
-		    /*
-		     * We lazily allocate offsets for static TLS as we
-		     * see the first relocation that references the
-		     * TLS block. This allows us to support (small
-		     * amounts of) static TLS in dynamically loaded
-		     * modules. If we run out of space, we generate an
-		     * error.
-		     */
-		    if (!defobj->tls_done) {
-			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
-			    _rtld_error("%s: No space available for static "
-					"Thread Local Storage", obj->path);
-			    goto done;
+		switch (ELF_R_TYPE(rela->r_info)) {
+		case R_X86_64_NONE:
+			break;
+		case R_X86_64_64:
+			*where = symval + rela->r_addend;
+			break;
+		case R_X86_64_PC32:
+			/*
+			 * I don't think the dynamic linker should
+			 * ever see this type of relocation.  But the
+			 * binutils-2.6 tools sometimes generate it.
+			 */
+			*where32 = (Elf32_Addr)(unsigned long)(symval +
+		            rela->r_addend - (Elf_Addr)where);
+			break;
+		/* missing: R_X86_64_GOT32 R_X86_64_PLT32 */
+		case R_X86_64_COPY:
+			/*
+			 * These are deferred until all other relocations have
+			 * been done.  All we do here is make sure that the COPY
+			 * relocation is not in a shared library.  They are allowed
+			 * only in executable files.
+			 */
+			if (!obj->mainprog) {
+				_rtld_error("%s: Unexpected R_X86_64_COPY "
+				    "relocation in shared library", obj->path);
+				goto done;
 			}
-		    }
-
-		    *where32 = (Elf32_Addr) (def->st_value -
-					     defobj->tlsoffset +
-					     rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_DTPMOD64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) defobj->tlsindex;
-		}
-		break;
-
-	    case R_X86_64_DTPOFF64:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) (def->st_value + rela->r_addend);
-		}
-		break;
-
-	    case R_X86_64_DTPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
+			break;
+		case R_X86_64_GLOB_DAT:
+			*where = symval;
+			break;
+		case R_X86_64_TPOFF64:
+			/*
+			 * We lazily allocate offsets for static TLS
+			 * as we see the first relocation that
+			 * references the TLS block. This allows us to
+			 * support (small amounts of) static TLS in
+			 * dynamically loaded modules. If we run out
+			 * of space, we generate an error.
+			 */
+			if (!defobj->tls_done) {
+				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+					_rtld_error("%s: No space available "
+					    "for static Thread Local Storage",
+					    obj->path);
+					goto done;
+				}
+			}
+			*where = (Elf_Addr)(def->st_value - defobj->tlsoffset +
+			    rela->r_addend);
+			break;
+		case R_X86_64_TPOFF32:
+			/*
+			 * We lazily allocate offsets for static TLS
+			 * as we see the first relocation that
+			 * references the TLS block. This allows us to
+			 * support (small amounts of) static TLS in
+			 * dynamically loaded modules. If we run out
+			 * of space, we generate an error.
+			 */
+			if (!defobj->tls_done) {
+				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+					_rtld_error("%s: No space available "
+					    "for static Thread Local Storage",
+					    obj->path);
+					goto done;
+				}
+			}
+			*where32 = (Elf32_Addr)(def->st_value -
+			    defobj->tlsoffset + rela->r_addend);
+			break;
+		case R_X86_64_DTPMOD64:
+			*where += (Elf_Addr)defobj->tlsindex;
+			break;
+		case R_X86_64_DTPOFF64:
+			*where += (Elf_Addr)(def->st_value + rela->r_addend);
+			break;
+		case R_X86_64_DTPOFF32:
+			*where32 += (Elf32_Addr)(def->st_value +
+			    rela->r_addend);
+			break;
+		case R_X86_64_RELATIVE:
+			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
+			break;
+		/*
+		 * missing:
+		 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16,
+		 * R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8
+		 */
+		default:
+			_rtld_error("%s: Unsupported relocation type %u"
+			    " in non-PLT relocations\n", obj->path,
+			    (unsigned int)ELF_R_TYPE(rela->r_info));
 			goto done;
-
-		    *where32 += (Elf32_Addr) (def->st_value + rela->r_addend);
 		}
-		break;
-
-	    case R_X86_64_RELATIVE:
-		*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
-		break;
-
-	/* missing: R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8 */
-
-	    default:
-		_rtld_error("%s: Unsupported relocation type %u"
-		  " in non-PLT relocations\n", obj->path,
-		  (unsigned int)ELF_R_TYPE(rela->r_info));
-		goto done;
-	    }
 	}
 	r = 0;
 done:
-	if (cache != NULL)
-	    free(cache);
+	free(cache);
 	return (r);
 }
 

Modified: head/libexec/rtld-elf/arm/reloc.c
==============================================================================
--- head/libexec/rtld-elf/arm/reloc.c	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/arm/reloc.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -324,6 +324,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry 
 	/* The relocation for the dynamic loader has already been done. */
 	if (obj == obj_rtld)
 		return (0);
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
 	/*
  	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().

Modified: head/libexec/rtld-elf/i386/reloc.c
==============================================================================
--- head/libexec/rtld-elf/i386/reloc.c	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/i386/reloc.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -126,168 +126,142 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry 
 	const Elf_Rel *rellim;
 	const Elf_Rel *rel;
 	SymCache *cache;
-	int r = -1;
+	const Elf_Sym *def;
+	const Obj_Entry *defobj;
+	Elf_Addr *where, symval, add;
+	int r;
 
+	r = -1;
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().
 	 */
 	if (obj != obj_rtld) {
-	    cache = calloc(obj->dynsymcount, sizeof(SymCache));
-	    /* No need to check for NULL here */
+		cache = calloc(obj->dynsymcount, sizeof(SymCache));
+		/* No need to check for NULL here */
 	} else
-	    cache = NULL;
+		cache = NULL;
 
-	rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
+	rellim = (const Elf_Rel *)((caddr_t) obj->rel + obj->relsize);
 	for (rel = obj->rel;  rel < rellim;  rel++) {
-	    Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
-
-	    switch (ELF_R_TYPE(rel->r_info)) {
-
-	    case R_386_NONE:
-		break;
-
-	    case R_386_32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) (defobj->relocbase + def->st_value);
-		}
-		break;
-
-	    case R_386_PC32:
-		/*
-		 * I don't think the dynamic linker should ever see this
-		 * type of relocation.  But the binutils-2.6 tools sometimes
-		 * generate it.
-		 */
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where +=
-		      (Elf_Addr) (defobj->relocbase + def->st_value) -
-		      (Elf_Addr) where;
-		}
-		break;
-
-	    case R_386_COPY:
-		/*
-		 * These are deferred until all other relocations have
-		 * been done.  All we do here is make sure that the COPY
-		 * relocation is not in a shared library.  They are allowed
-		 * only in executable files.
-		 */
-		if (!obj->mainprog) {
-		    _rtld_error("%s: Unexpected R_386_COPY relocation"
-		      " in shared library", obj->path);
-		    goto done;
-		}
-		break;
-
-	    case R_386_GLOB_DAT:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where = (Elf_Addr) (defobj->relocbase + def->st_value);
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_386_32:
+		case R_386_PC32:
+		case R_386_GLOB_DAT:
+		case R_386_TLS_TPOFF:
+		case R_386_TLS_TPOFF32:
+		case R_386_TLS_DTPMOD32:
+		case R_386_TLS_DTPOFF32:
+			def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+			    flags, cache, lockstate);
+			if (def == NULL)
+				goto done;
+			if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
+				switch (ELF_R_TYPE(rel->r_info)) {
+				case R_386_32:
+				case R_386_PC32:
+				case R_386_GLOB_DAT:
+					if ((flags & SYMLOOK_IFUNC) == 0)
+						continue;
+					symval = (Elf_Addr)rtld_resolve_ifunc(
+					    defobj, def);
+					break;
+				case R_386_TLS_TPOFF:
+				case R_386_TLS_TPOFF32:
+				case R_386_TLS_DTPMOD32:
+				case R_386_TLS_DTPOFF32:
+					_rtld_error("%s: IFUNC for TLS reloc",
+					    obj->path);
+					goto done;
+				}
+			} else {
+				if ((flags & SYMLOOK_IFUNC) != 0)
+					continue;
+				symval = (Elf_Addr)defobj->relocbase +
+				    def->st_value;
+			}
+			break;
+		default:
+			if ((flags & SYMLOOK_IFUNC) != 0)
+				continue;
+			break;
 		}
-		break;
-
-	    case R_386_RELATIVE:
-		*where += (Elf_Addr) obj->relocbase;
-		break;
-
-	    case R_386_TLS_TPOFF:
-	    case R_386_TLS_TPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-		    Elf_Addr add;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
+		where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
 
+		switch (ELF_R_TYPE(rel->r_info)) {
+		case R_386_NONE:
+			break;
+		case R_386_32:
+			*where += symval;
+			break;
+		case R_386_PC32:
 		    /*
-		     * We lazily allocate offsets for static TLS as we
-		     * see the first relocation that references the
-		     * TLS block. This allows us to support (small
-		     * amounts of) static TLS in dynamically loaded
-		     * modules. If we run out of space, we generate an
-		     * error.
+		     * I don't think the dynamic linker should ever
+		     * see this type of relocation.  But the
+		     * binutils-2.6 tools sometimes generate it.
 		     */
-		    if (!defobj->tls_done) {
-			if (!allocate_tls_offset((Obj_Entry*) defobj)) {
-			    _rtld_error("%s: No space available for static "
-					"Thread Local Storage", obj->path);
-			    goto done;
+		    *where += symval - (Elf_Addr)where;
+		    break;
+		case R_386_COPY:
+			/*
+			 * These are deferred until all other
+			 * relocations have been done.  All we do here
+			 * is make sure that the COPY relocation is
+			 * not in a shared library.  They are allowed
+			 * only in executable files.
+			 */
+			if (!obj->mainprog) {
+				_rtld_error("%s: Unexpected R_386_COPY "
+				    "relocation in shared library", obj->path);
+				goto done;
 			}
-		    }
-		    add = (Elf_Addr) (def->st_value - defobj->tlsoffset);
-		    if (ELF_R_TYPE(rel->r_info) == R_386_TLS_TPOFF)
-			*where += add;
-		    else
-			*where -= add;
-		}
-		break;
-
-	    case R_386_TLS_DTPMOD32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
-			goto done;
-
-		    *where += (Elf_Addr) defobj->tlsindex;
-		}
-		break;
-
-	    case R_386_TLS_DTPOFF32:
-		{
-		    const Elf_Sym *def;
-		    const Obj_Entry *defobj;
-
-		    def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
-		      flags, cache, lockstate);
-		    if (def == NULL)
+			break;
+		case R_386_GLOB_DAT:
+			*where = symval;
+			break;
+		case R_386_RELATIVE:
+			*where += (Elf_Addr)obj->relocbase;
+			break;
+		case R_386_TLS_TPOFF:
+		case R_386_TLS_TPOFF32:
+			/*
+			 * We lazily allocate offsets for static TLS
+			 * as we see the first relocation that
+			 * references the TLS block. This allows us to
+			 * support (small amounts of) static TLS in
+			 * dynamically loaded modules. If we run out
+			 * of space, we generate an error.
+			 */
+			if (!defobj->tls_done) {
+				if (!allocate_tls_offset((Obj_Entry*) defobj)) {
+					_rtld_error("%s: No space available "
+					    "for static Thread Local Storage",
+					    obj->path);
+					goto done;
+				}
+			}
+			add = (Elf_Addr)(def->st_value - defobj->tlsoffset);
+			if (ELF_R_TYPE(rel->r_info) == R_386_TLS_TPOFF)
+				*where += add;
+			else
+				*where -= add;
+			break;
+		case R_386_TLS_DTPMOD32:
+			*where += (Elf_Addr)defobj->tlsindex;
+			break;
+		case R_386_TLS_DTPOFF32:
+			*where += (Elf_Addr) def->st_value;
+			break;
+		default:
+			_rtld_error("%s: Unsupported relocation type %d"
+			    " in non-PLT relocations\n", obj->path,
+			    ELF_R_TYPE(rel->r_info));
 			goto done;
-
-		    *where += (Elf_Addr) def->st_value;
 		}
-		break;
-
-	    default:
-		_rtld_error("%s: Unsupported relocation type %d"
-		  " in non-PLT relocations\n", obj->path,
-		  ELF_R_TYPE(rel->r_info));
-		goto done;
-	    }
 	}
 	r = 0;
 done:
-	if (cache != NULL)
-	    free(cache);
+	free(cache);
 	return (r);
 }
 

Modified: head/libexec/rtld-elf/mips/reloc.c
==============================================================================
--- head/libexec/rtld-elf/mips/reloc.c	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/mips/reloc.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -275,6 +275,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry 
 	if (obj == obj_rtld)
 		return (0);
 
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
 #ifdef SUPPORT_OLD_BROKEN_LD
 	broken = 0;
 	sym = obj->symtab;

Modified: head/libexec/rtld-elf/powerpc/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc/reloc.c	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/powerpc/reloc.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -294,6 +294,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry 
 	SymCache *cache;
 	int r = -1;
 
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().

Modified: head/libexec/rtld-elf/powerpc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc64/reloc.c	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/powerpc64/reloc.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -290,6 +290,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry 
 	int bytes = obj->dynsymcount * sizeof(SymCache);
 	int r = -1;
 
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/rtld.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -2546,7 +2546,7 @@ relocate_object(Obj_Entry *obj, bool bin
 		}
 	}
 
-	/* Process the non-PLT relocations. */
+	/* Process the non-PLT non-IFUNC relocations. */
 	if (reloc_non_plt(obj, rtldobj, flags, lockstate))
 		return (-1);
 
@@ -2559,7 +2559,6 @@ relocate_object(Obj_Entry *obj, bool bin
 		}
 	}
 
-
 	/* Set the special PLT or GOT entries. */
 	init_pltgot(obj);
 
@@ -2571,6 +2570,15 @@ relocate_object(Obj_Entry *obj, bool bin
 		if (reloc_jmpslots(obj, flags, lockstate) == -1)
 			return (-1);
 
+	/*
+	 * Process the non-PLT IFUNC relocations.  The relocations are
+	 * processed in two phases, because IFUNC resolvers may
+	 * reference other symbols, which must be readily processed
+	 * before resolvers are called.
+	 */
+	if (reloc_non_plt(obj, rtldobj, flags | SYMLOOK_IFUNC, lockstate))
+		return (-1);
+
 	if (obj->relro_size > 0) {
 		if (mprotect(obj->relro_page, obj->relro_size,
 		    PROT_READ) == -1) {

Modified: head/libexec/rtld-elf/rtld.h
==============================================================================
--- head/libexec/rtld-elf/rtld.h	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/rtld.h	Fri Aug 29 09:29:10 2014	(r270798)
@@ -293,6 +293,8 @@ typedef struct Struct_Obj_Entry {
 #define SYMLOOK_DLSYM	0x02	/* Return newest versioned symbol. Used by
 				   dlsym. */
 #define	SYMLOOK_EARLY	0x04	/* Symlook is done during initialization. */
+#define	SYMLOOK_IFUNC	0x08	/* Allow IFUNC processing in
+				   reloc_non_plt(). */
 
 /* Flags for load_object(). */
 #define	RTLD_LO_NOLOAD	0x01	/* dlopen() specified RTLD_NOLOAD. */

Modified: head/libexec/rtld-elf/sparc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/sparc64/reloc.c	Fri Aug 29 09:04:24 2014	(r270797)
+++ head/libexec/rtld-elf/sparc64/reloc.c	Fri Aug 29 09:29:10 2014	(r270798)
@@ -300,6 +300,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry 
 	SymCache *cache;
 	int r = -1;
 
+	if ((flags & SYMLOOK_IFUNC) != 0)
+		/* XXX not implemented */
+		return (0);
+
 	/*
 	 * The dynamic loader may be called from a thread, we have
 	 * limited amounts of stack available so we cannot use alloca().



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