svn commit: r356113 - in head: libexec/rtld-elf sys/kern sys/sys
Justin Hibbits
jhibbits at FreeBSD.org
Fri Dec 27 04:07:04 UTC 2019
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
More information about the svn-src-all
mailing list