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
This commit is contained in:
Justin Hibbits 2019-12-27 04:07:03 +00:00
parent e4399d169a
commit adea0d6368
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=356113
4 changed files with 127 additions and 14 deletions

View File

@ -382,6 +382,9 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
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,8 +410,29 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
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);
init_rtld((caddr_t) aux_info[AT_BASE]->a_un.a_ptr, aux_info);

View File

@ -1323,6 +1323,102 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
#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)
{
@ -1383,6 +1479,11 @@ __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--;
if (suword(base, imgp->args->argc) == -1)

View File

@ -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. */

View File

@ -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