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
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to