svn commit: r357895 - in head/libexec/rtld-elf: . aarch64 amd64 arm i386 mips powerpc powerpc64 riscv sparc64

Konstantin Belousov kib at FreeBSD.org
Thu Feb 13 23:42:11 UTC 2020


Author: kib
Date: Thu Feb 13 23:42:09 2020
New Revision: 357895
URL: https://svnweb.freebsd.org/changeset/base/357895

Log:
  Handle non-plt IRELATIVE relocations, at least for x86.
  
  lld 10.0 seems to generate this relocation for rdtsc_mb() ifunc in our libc.
  
  Reported, reviewed, and tested by:	dim (amd64, previous version)
  Discussed with:	emaste
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week
  Differential revision:	https://reviews.freebsd.org/D23652

Modified:
  head/libexec/rtld-elf/aarch64/reloc.c
  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/riscv/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/aarch64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/aarch64/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/aarch64/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -258,31 +258,56 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockStat
 	return (0);
 }
 
+static void
+reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela,
+    RtldLockState *lockstate)
+{
+	Elf_Addr *where, target, *ptr;
+
+	ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
+	where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	lock_release(rtld_bind_lock, lockstate);
+	target = call_ifunc_resolver(ptr);
+	wlock_acquire(rtld_bind_lock, lockstate);
+	*where = target;
+}
+
 int
 reloc_iresolve(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
 {
 	const Elf_Rela *relalim;
 	const Elf_Rela *rela;
-	Elf_Addr *where, target, *ptr;
 
 	if (!obj->irelative)
 		return (0);
-	relalim = (const Elf_Rela *)((const char *)obj->pltrela + obj->pltrelasize);
+	obj->irelative = false;
+	relalim = (const Elf_Rela *)((const char *)obj->pltrela +
+	    obj->pltrelasize);
 	for (rela = obj->pltrela;  rela < relalim;  rela++) {
-		if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE) {
-			ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
-			where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-			lock_release(rtld_bind_lock, lockstate);
-			target = call_ifunc_resolver(ptr);
-			wlock_acquire(rtld_bind_lock, lockstate);
-			*where = target;
-		}
+		if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE)
+			reloc_iresolve_one(obj, rela, lockstate);
 	}
-	obj->irelative = false;
 	return (0);
 }
 
 int
+reloc_iresolve_nonplt(Obj_Entry *obj, struct Struct_RtldLockState *lockstate)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
+
+	if (!obj->irelative_nonplt)
+		return (0);
+	obj->irelative_nonplt = false;
+	relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize);
+	for (rela = obj->rela;  rela < relalim;  rela++) {
+		if (ELF_R_TYPE(rela->r_info) == R_AARCH64_IRELATIVE)
+			reloc_iresolve_one(obj, rela, lockstate);
+	}
+	return (0);
+}
+
+int
 reloc_gnu_ifunc(Obj_Entry *obj, int flags,
    struct Struct_RtldLockState *lockstate)
 {
@@ -497,6 +522,9 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int
 			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
 			break;
 		case R_AARCH64_NONE:
+			break;
+		case R_AARCH64_IRELATIVE:
+			obj->irelative_nonplt = true;
 			break;
 		default:
 			rtld_printf("%s: Unhandled relocation %lu\n",

Modified: head/libexec/rtld-elf/amd64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/amd64/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/amd64/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -303,6 +303,10 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int
 		case R_X86_64_RELATIVE:
 			*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
 			break;
+		case R_X86_64_IRELATIVE:
+			obj->irelative_nonplt = true;
+			break;
+
 		/*
 		 * missing:
 		 * R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16,
@@ -410,34 +414,53 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
 	return (target);
 }
 
+static void
+reloc_iresolve_one(Obj_Entry *obj, const Elf_Rela *rela,
+    RtldLockState *lockstate)
+{
+	Elf_Addr *where, target, *ptr;
+
+	ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
+	where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
+	lock_release(rtld_bind_lock, lockstate);
+	target = call_ifunc_resolver(ptr);
+	wlock_acquire(rtld_bind_lock, lockstate);
+	*where = target;
+}
+
 int
 reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
 {
-    const Elf_Rela *relalim;
-    const Elf_Rela *rela;
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
 
-    if (!obj->irelative)
+	if (!obj->irelative)
+		return (0);
+	obj->irelative = false;
+	relalim = (const Elf_Rela *)((const char *)obj->pltrela +
+	    obj->pltrelasize);
+	for (rela = obj->pltrela;  rela < relalim;  rela++) {
+		if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE)
+			reloc_iresolve_one(obj, rela, lockstate);
+	}
 	return (0);
-    relalim = (const Elf_Rela *)((const 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;
+int
+reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate)
+{
+	const Elf_Rela *relalim;
+	const Elf_Rela *rela;
 
-	case R_X86_64_IRELATIVE:
-	  ptr = (Elf_Addr *)(obj->relocbase + rela->r_addend);
-	  where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
-	  lock_release(rtld_bind_lock, lockstate);
-	  target = call_ifunc_resolver(ptr);
-	  wlock_acquire(rtld_bind_lock, lockstate);
-	  *where = target;
-	  break;
+	if (!obj->irelative_nonplt)
+		return (0);
+	obj->irelative_nonplt = false;
+	relalim = (const Elf_Rela *)((const char *)obj->rela + obj->relasize);
+	for (rela = obj->rela;  rela < relalim;  rela++) {
+		if (ELF_R_TYPE(rela->r_info) == R_X86_64_IRELATIVE)
+			reloc_iresolve_one(obj, rela, lockstate);
 	}
-    }
-    obj->irelative = false;
-    return (0);
+	return (0);
 }
 
 int

Modified: head/libexec/rtld-elf/arm/reloc.c
==============================================================================
--- head/libexec/rtld-elf/arm/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/arm/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -452,6 +452,15 @@ reloc_iresolve(Obj_Entry *obj __unused,
 }
 
 int
+reloc_iresolve_nonplt(Obj_Entry *obj __unused,
+    struct Struct_RtldLockState *lockstate __unused)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused,
     struct Struct_RtldLockState *lockstate __unused)
 {

Modified: head/libexec/rtld-elf/i386/reloc.c
==============================================================================
--- head/libexec/rtld-elf/i386/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/i386/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -263,6 +263,9 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int
 		case R_386_TLS_DTPOFF32:
 			*where += (Elf_Addr) def->st_value;
 			break;
+		case R_386_IRELATIVE:
+			obj->irelative_nonplt = true;
+			break;
 		default:
 			_rtld_error("%s: Unsupported relocation type %d"
 			    " in non-PLT relocations\n", obj->path,
@@ -365,29 +368,51 @@ reloc_jmpslot(Elf_Addr *where, Elf_Addr target,
 	return (target);
 }
 
+static void
+reloc_iresolve_one(Obj_Entry *obj, const Elf_Rel *rel,
+    RtldLockState *lockstate)
+{
+	Elf_Addr *where, target;
+
+	where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
+	lock_release(rtld_bind_lock, lockstate);
+	target = call_ifunc_resolver(obj->relocbase + *where);
+	wlock_acquire(rtld_bind_lock, lockstate);
+	*where = target;
+}
+
 int
 reloc_iresolve(Obj_Entry *obj, RtldLockState *lockstate)
 {
-    const Elf_Rel *rellim;
-    const Elf_Rel *rel;
-    Elf_Addr *where, target;
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
 
-    if (!obj->irelative)
+	if (!obj->irelative)
+		return (0);
+	obj->irelative = false;
+	rellim = (const Elf_Rel *)((const char *)obj->pltrel + obj->pltrelsize);
+	for (rel = obj->pltrel;  rel < rellim;  rel++) {
+		if (ELF_R_TYPE(rel->r_info) == R_386_RELATIVE)
+			reloc_iresolve_one(obj, rel, lockstate);
+	}
 	return (0);
-    rellim = (const Elf_Rel *)((const 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);
-	  lock_release(rtld_bind_lock, lockstate);
-	  target = call_ifunc_resolver(obj->relocbase + *where);
-	  wlock_acquire(rtld_bind_lock, lockstate);
-	  *where = target;
-	  break;
+}
+
+int
+reloc_iresolve_nonplt(Obj_Entry *obj, RtldLockState *lockstate)
+{
+	const Elf_Rel *rellim;
+	const Elf_Rel *rel;
+
+	if (!obj->irelative_nonplt)
+		return (0);
+	obj->irelative_nonplt = false;
+	rellim = (const Elf_Rel *)((const char *)obj->rel + obj->relsize);
+	for (rel = obj->rel;  rel < rellim;  rel++) {
+		if (ELF_R_TYPE(rel->r_info) == R_386_IRELATIVE)
+			reloc_iresolve_one(obj, rel, lockstate);
 	}
-    }
-    obj->irelative = false;
-    return (0);
+	return (0);
 }
 
 int

Modified: head/libexec/rtld-elf/mips/reloc.c
==============================================================================
--- head/libexec/rtld-elf/mips/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/mips/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -723,6 +723,15 @@ reloc_iresolve(Obj_Entry *obj __unused,
 }
 
 int
+reloc_iresolve_nonplt(Obj_Entry *obj __unused,
+    struct Struct_RtldLockState *lockstate __unused)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused,
     struct Struct_RtldLockState *lockstate __unused)
 {

Modified: head/libexec/rtld-elf/powerpc/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/powerpc/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -653,6 +653,13 @@ reloc_iresolve(Obj_Entry *obj,
 }
 
 int
+reloc_iresolve_nonplt(Obj_Entry *obj __unused,
+    struct Struct_RtldLockState *lockstate __unused)
+{
+	return (0);
+}
+
+int
 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused,
     struct Struct_RtldLockState *lockstate __unused)
 {

Modified: head/libexec/rtld-elf/powerpc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/powerpc64/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/powerpc64/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -652,6 +652,13 @@ reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __u
 #endif
 }
 
+int
+reloc_iresolve_nonplt(Obj_Entry *obj __unused,
+    struct Struct_RtldLockState *lockstate __unused)
+{
+	return (0);
+}
+
 void
 init_pltgot(Obj_Entry *obj)
 {

Modified: head/libexec/rtld-elf/riscv/reloc.c
==============================================================================
--- head/libexec/rtld-elf/riscv/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/riscv/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -212,6 +212,15 @@ reloc_iresolve(Obj_Entry *obj __unused,
 }
 
 int
+reloc_iresolve_nonplt(Obj_Entry *obj __unused,
+    struct Struct_RtldLockState *lockstate __unused)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused,
    struct Struct_RtldLockState *lockstate __unused)
 {

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/rtld.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -3034,10 +3034,13 @@ resolve_object_ifunc(Obj_Entry *obj, bool bind_now, in
 	if (obj->ifuncs_resolved)
 		return (0);
 	obj->ifuncs_resolved = true;
-	if (!obj->irelative && !((obj->bind_now || bind_now) && obj->gnu_ifunc))
+	if (!obj->irelative && !obj->irelative_nonplt &&
+	    !((obj->bind_now || bind_now) && obj->gnu_ifunc))
 		return (0);
 	if (obj_disable_relro(obj) == -1 ||
 	    (obj->irelative && reloc_iresolve(obj, lockstate) == -1) ||
+	    (obj->irelative_nonplt && reloc_iresolve_nonplt(obj,
+	    lockstate) == -1) ||
 	    ((obj->bind_now || bind_now) && obj->gnu_ifunc &&
 	    reloc_gnu_ifunc(obj, flags, lockstate) == -1) ||
 	    obj_enforce_relro(obj) == -1)

Modified: head/libexec/rtld-elf/rtld.h
==============================================================================
--- head/libexec/rtld-elf/rtld.h	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/rtld.h	Thu Feb 13 23:42:09 2020	(r357895)
@@ -264,6 +264,7 @@ typedef struct Struct_Obj_Entry {
     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 irelative_nonplt : 1;	/* Object has R_MACHDEP_IRELATIVE non-plt relocs */
     bool gnu_ifunc : 1;		/* Object has references to STT_GNU_IFUNC */
     bool non_plt_gnu_ifunc : 1;	/* Object has non-plt IFUNC references */
     bool ifuncs_resolved : 1;	/* Object ifuncs were already resolved */
@@ -406,6 +407,7 @@ int reloc_non_plt(Obj_Entry *, Obj_Entry *, int flags,
 int reloc_plt(Obj_Entry *, int flags, struct Struct_RtldLockState *);
 int reloc_jmpslots(Obj_Entry *, int flags, struct Struct_RtldLockState *);
 int reloc_iresolve(Obj_Entry *, struct Struct_RtldLockState *);
+int reloc_iresolve_nonplt(Obj_Entry *, struct Struct_RtldLockState *);
 int reloc_gnu_ifunc(Obj_Entry *, int flags, struct Struct_RtldLockState *);
 void ifunc_init(Elf_Auxinfo[__min_size(AT_COUNT)]);
 void pre_init(void);

Modified: head/libexec/rtld-elf/sparc64/reloc.c
==============================================================================
--- head/libexec/rtld-elf/sparc64/reloc.c	Thu Feb 13 23:22:12 2020	(r357894)
+++ head/libexec/rtld-elf/sparc64/reloc.c	Thu Feb 13 23:42:09 2020	(r357895)
@@ -570,6 +570,15 @@ reloc_iresolve(Obj_Entry *obj __unused,
 }
 
 int
+reloc_iresolve_nonplt(Obj_Entry *obj __unused,
+    struct Struct_RtldLockState *lockstate __unused)
+{
+
+	/* XXX not implemented */
+	return (0);
+}
+
+int
 reloc_gnu_ifunc(Obj_Entry *obj __unused, int flags __unused,
     struct Struct_RtldLockState *lockstate __unused)
 {


More information about the svn-src-head mailing list