Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 27 Dec 2019 04:07:03 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356113 - in head: libexec/rtld-elf sys/kern sys/sys
Message-ID:  <201912270407.xBR473Zh054687@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Fri Dec 27 04:07:03 2019
New Revision: 356113
URL: https://svnweb.freebsd.org/changeset/base/356113

Log:
  Eliminate the last MI difference in AT_* definitions (for powerpc).
  
  Summary:
  As a transition aide, implement an alternative elfN_freebsd_fixup which
  is called for old powerpc binaries.  Similarly, add a translation to rtld to
  convert old values to new ones (as expected by a new rtld).
  
  Translation of old<->new values  is incomplete, but sufficient to allow an
  installworld of a new userspace from an old one when a new kernel is running.
  
  Test Plan:
  Someone needs to see how a new kernel/rtld/libc works with an old
  binary.  If if works we can probalby ship this.  If not we probalby need
  some more compat bits.
  
  Submitted by:	brooks
  Reviewed by:	jhibbits
  Differential Revision:	https://reviews.freebsd.org/D20799

Modified:
  head/libexec/rtld-elf/rtld.c
  head/sys/kern/imgact_elf.c
  head/sys/sys/elf_common.h
  head/sys/sys/param.h

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Fri Dec 27 04:00:04 2019	(r356112)
+++ head/libexec/rtld-elf/rtld.c	Fri Dec 27 04:07:03 2019	(r356113)
@@ -382,6 +382,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
     caddr_t imgentry;
     char buf[MAXPATHLEN];
     int argc, fd, i, phnum, rtld_argc;
+#ifdef __powerpc__
+    int old_auxv_format = 1;
+#endif
     bool dir_enable, explicit_fd, search_in_path;
 
     /*
@@ -407,7 +410,28 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entr
     for (auxp = aux;  auxp->a_type != AT_NULL;  auxp++) {
 	if (auxp->a_type < AT_COUNT)
 	    aux_info[auxp->a_type] = auxp;
+#ifdef __powerpc__
+	if (auxp->a_type == 23) /* AT_STACKPROT */
+	    old_auxv_format = 0;
+#endif
     }
+
+#ifdef __powerpc__
+    if (old_auxv_format) {
+	/* Remap from old-style auxv numbers. */
+	aux_info[23] = aux_info[21];	/* AT_STACKPROT */
+	aux_info[21] = aux_info[19];	/* AT_PAGESIZESLEN */
+	aux_info[19] = aux_info[17];	/* AT_NCPUS */
+	aux_info[17] = aux_info[15];	/* AT_CANARYLEN */
+	aux_info[15] = aux_info[13];	/* AT_EXECPATH */
+	aux_info[13] = NULL;		/* AT_GID */
+
+	aux_info[20] = aux_info[18];	/* AT_PAGESIZES */
+	aux_info[18] = aux_info[16];	/* AT_OSRELDATE */
+	aux_info[16] = aux_info[14];	/* AT_CANARY */
+	aux_info[14] = NULL;		/* AT_EGID */
+    }
+#endif
 
     /* Initialize and relocate ourselves. */
     assert(aux_info[AT_BASE] != NULL);

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Fri Dec 27 04:00:04 2019	(r356112)
+++ head/sys/kern/imgact_elf.c	Fri Dec 27 04:07:03 2019	(r356113)
@@ -1323,6 +1323,102 @@ ret:
 
 #define	suword __CONCAT(suword, __ELF_WORD_SIZE)
 
+#ifdef __powerpc__
+#define	OLD_AT_NULL		AT_NULL
+#define	OLD_AT_IGNORE		AT_IGNORE
+#define	OLD_AT_EXECFD		AT_EXECFD
+#define	OLD_AT_PHDR		AT_PHDR
+#define	OLD_AT_PHENT		AT_PHENT
+#define	OLD_AT_PHNUM		AT_PHNUM
+#define	OLD_AT_PAGESZ		AT_PAGESZ
+#define	OLD_AT_BASE		AT_BASE
+#define	OLD_AT_FLAGS		AT_FLAGS
+#define	OLD_AT_ENTRY		AT_ENTRY
+#define	OLD_AT_NOTELF		AT_NOTELF
+#define	OLD_AT_UID		AT_UID
+#define	OLD_AT_EUID		AT_EUID
+#define	OLD_AT_EXECPATH		13
+#define	OLD_AT_CANARY		14
+#define	OLD_AT_CANARYLEN	15
+#define	OLD_AT_OSRELDATE	16
+#define	OLD_AT_NCPUS		17
+#define	OLD_AT_PAGESIZES	18
+#define	OLD_AT_PAGESIZESLEN	19
+#define	OLD_AT_STACKPROT	21
+#define	OLD_AT_TIMEKEEP		AT_TIMEKEEP
+#define	OLD_AT_EHDRFLAGS	AT_EHDRFLAGS
+#define	OLD_AT_HWCAP		AT_HWCAP
+#define	OLD_AT_HWCAP2		AT_HWCAP2
+
+#define	OLD_AT_COUNT	27	/* Count of defined aux entry types. */
+
+static int
+__elfN(freebsd_fixup_old_auxargs)(register_t **stack_base,
+    struct image_params *imgp)
+{
+	Elf_Auxargs *args = (Elf_Auxargs *)imgp->auxargs;
+	Elf_Auxinfo *argarray, *pos;
+	Elf_Addr *base, *auxbase;
+	int error;
+
+	base = (Elf_Addr *)*stack_base;
+	auxbase = base + imgp->args->argc + 1 + imgp->args->envc + 1;
+	argarray = pos = malloc(OLD_AT_COUNT * sizeof(*pos), M_TEMP,
+	    M_WAITOK | M_ZERO);
+
+	if (args->execfd != -1)
+		AUXARGS_ENTRY(pos, OLD_AT_EXECFD, args->execfd);
+	AUXARGS_ENTRY(pos, OLD_AT_PHDR, args->phdr);
+	AUXARGS_ENTRY(pos, OLD_AT_PHENT, args->phent);
+	AUXARGS_ENTRY(pos, OLD_AT_PHNUM, args->phnum);
+	AUXARGS_ENTRY(pos, OLD_AT_PAGESZ, args->pagesz);
+	AUXARGS_ENTRY(pos, OLD_AT_FLAGS, args->flags);
+	AUXARGS_ENTRY(pos, OLD_AT_ENTRY, args->entry);
+	AUXARGS_ENTRY(pos, OLD_AT_BASE, args->base);
+	AUXARGS_ENTRY(pos, OLD_AT_EHDRFLAGS, args->hdr_eflags);
+	if (imgp->execpathp != 0)
+		AUXARGS_ENTRY(pos, OLD_AT_EXECPATH, imgp->execpathp);
+	AUXARGS_ENTRY(pos, OLD_AT_OSRELDATE,
+	    imgp->proc->p_ucred->cr_prison->pr_osreldate);
+	if (imgp->canary != 0) {
+		AUXARGS_ENTRY(pos, OLD_AT_CANARY, imgp->canary);
+		AUXARGS_ENTRY(pos, OLD_AT_CANARYLEN, imgp->canarylen);
+	}
+	AUXARGS_ENTRY(pos, OLD_AT_NCPUS, mp_ncpus);
+	if (imgp->pagesizes != 0) {
+		AUXARGS_ENTRY(pos, OLD_AT_PAGESIZES, imgp->pagesizes);
+		AUXARGS_ENTRY(pos, OLD_AT_PAGESIZESLEN, imgp->pagesizeslen);
+	}
+	if (imgp->sysent->sv_timekeep_base != 0) {
+		AUXARGS_ENTRY(pos, OLD_AT_TIMEKEEP,
+		    imgp->sysent->sv_timekeep_base);
+	}
+	AUXARGS_ENTRY(pos, OLD_AT_STACKPROT, imgp->sysent->sv_shared_page_obj
+	    != NULL && imgp->stack_prot != 0 ? imgp->stack_prot :
+	    imgp->sysent->sv_stackprot);
+	if (imgp->sysent->sv_hwcap != NULL)
+		AUXARGS_ENTRY(pos, OLD_AT_HWCAP, *imgp->sysent->sv_hwcap);
+	if (imgp->sysent->sv_hwcap2 != NULL)
+		AUXARGS_ENTRY(pos, OLD_AT_HWCAP2, *imgp->sysent->sv_hwcap2);
+	AUXARGS_ENTRY(pos, OLD_AT_NULL, 0);
+
+	free(imgp->auxargs, M_TEMP);
+	imgp->auxargs = NULL;
+	KASSERT(pos - argarray <= OLD_AT_COUNT, ("Too many auxargs"));
+
+	error = copyout(argarray, auxbase, sizeof(*argarray) * OLD_AT_COUNT);
+	free(argarray, M_TEMP);
+	if (error != 0)
+		return (error);
+
+	base--;
+	if (suword(base, imgp->args->argc) == -1)
+		return (EFAULT);
+	*stack_base = (register_t *)base;
+	return (0);
+}
+#endif /* __powerpc__ */
+
 int
 __elfN(freebsd_copyout_auxargs)(struct image_params *imgp, uintptr_t base)
 {
@@ -1382,6 +1478,11 @@ int
 __elfN(freebsd_fixup)(uintptr_t *stack_base, struct image_params *imgp)
 {
 	Elf_Addr *base;
+
+#ifdef __powerpc__
+	if (imgp->proc->p_osrel < P_OSREL_POWERPC_NEW_AUX_ARGS)
+		return (__elfN(freebsd_fixup_old_auxargs)(stack_base, imgp));
+#endif /* __powerpc__ */
 
 	base = (Elf_Addr *)*stack_base;
 	base--;

Modified: head/sys/sys/elf_common.h
==============================================================================
--- head/sys/sys/elf_common.h	Fri Dec 27 04:00:04 2019	(r356112)
+++ head/sys/sys/elf_common.h	Fri Dec 27 04:07:03 2019	(r356113)
@@ -935,7 +935,6 @@ typedef struct {
 #define	AT_NOTELF	10	/* Program is not ELF ?? */
 #define	AT_UID		11	/* Real uid. */
 #define	AT_EUID		12	/* Effective uid. */
-#ifndef __powerpc__
 #define	AT_GID		13	/* Real gid. */
 #define	AT_EGID		14	/* Effective gid. */
 #define	AT_EXECPATH	15	/* Path to the executable. */
@@ -945,20 +944,8 @@ typedef struct {
 #define	AT_NCPUS	19	/* Number of CPUs. */
 #define	AT_PAGESIZES	20	/* Pagesizes. */
 #define	AT_PAGESIZESLEN	21	/* Number of pagesizes. */
-#else /* defined(__powerpc__) */
-#define	AT_EXECPATH	13
-#define	AT_CANARY	14
-#define	AT_CANARYLEN	15
-#define	AT_OSRELDATE	16
-#define	AT_NCPUS	17
-#define	AT_PAGESIZES	18
-#define	AT_PAGESIZESLEN	19
-#define	AT_STACKPROT	21
-#endif /* defined(__powerpc__) */
 #define	AT_TIMEKEEP	22	/* Pointer to timehands. */
-#ifndef __powerpc__
 #define	AT_STACKPROT	23	/* Initial stack protection. */
-#endif
 #define	AT_EHDRFLAGS	24	/* e_flags field from elf hdr */
 #define	AT_HWCAP	25	/* CPU feature flags. */
 #define	AT_HWCAP2	26	/* CPU feature flags 2. */

Modified: head/sys/sys/param.h
==============================================================================
--- head/sys/sys/param.h	Fri Dec 27 04:00:04 2019	(r356112)
+++ head/sys/sys/param.h	Fri Dec 27 04:07:03 2019	(r356113)
@@ -60,7 +60,7 @@
  *		in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1300069	/* Master, propagated to newvers */
+#define __FreeBSD_version 1300070	/* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
@@ -90,6 +90,7 @@
 #define	P_OSREL_VMTOTAL64		1200054
 #define	P_OSREL_CK_SUPERBLOCK		1300000
 #define	P_OSREL_CK_INODE		1300005
+#define	P_OSREL_POWERPC_NEW_AUX_ARGS	1300070
 
 #define	P_OSREL_MAJOR(x)		((x) / 100000)
 #endif



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