add support for __MACHINE_STACK_GROWS_UP platforms. from fredette@

This commit is contained in:
chs 2002-11-17 22:53:46 +00:00
parent 4153f58dfe
commit ab17ec89d1
4 changed files with 110 additions and 44 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: exec_elf_common.c,v 1.15 2002/05/31 16:49:12 atatat Exp $ */
/* $NetBSD: exec_elf_common.c,v 1.16 2002/11/17 22:53:46 chs Exp $ */
/*-
* Copyright (c) 1994 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: exec_elf_common.c,v 1.15 2002/05/31 16:49:12 atatat Exp $");
__KERNEL_RCSID(0, "$NetBSD: exec_elf_common.c,v 1.16 2002/11/17 22:53:46 chs Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@ -62,6 +62,9 @@ __KERNEL_RCSID(0, "$NetBSD: exec_elf_common.c,v 1.15 2002/05/31 16:49:12 atatat
int
exec_elf_setup_stack(struct proc *p, struct exec_package *epp)
{
u_long max_stack_size;
u_long access_linear_min, access_size;
u_long noaccess_linear_min, noaccess_size;
#ifndef USRSTACK32
#define USRSTACK32 (0x00000000ffffffffL&~PGOFSET)
@ -69,11 +72,13 @@ exec_elf_setup_stack(struct proc *p, struct exec_package *epp)
if (epp->ep_flags & EXEC_32) {
epp->ep_minsaddr = USRSTACK32;
epp->ep_maxsaddr = epp->ep_minsaddr - MAXSSIZ;
max_stack_size = MAXSSIZ;
} else {
epp->ep_maxsaddr = USRSTACK - MAXSSIZ;
epp->ep_minsaddr = USRSTACK;
max_stack_size = MAXSSIZ;
}
epp->ep_maxsaddr = (u_long)STACK_GROW(epp->ep_minsaddr,
max_stack_size);
epp->ep_ssize = p->p_rlimit[RLIMIT_STACK].rlim_cur;
/*
@ -83,15 +88,16 @@ exec_elf_setup_stack(struct proc *p, struct exec_package *epp)
*
* arguably, it could be made into one, but that would require the
* addition of another mapping proc, which is unnecessary
*
* note that in memory, things assumed to be: 0 ... ep_maxsaddr
* <stack> ep_minsaddr
*/
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero,
((epp->ep_minsaddr - epp->ep_ssize) - epp->ep_maxsaddr),
epp->ep_maxsaddr, NULLVP, 0, VM_PROT_NONE);
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, epp->ep_ssize,
(epp->ep_minsaddr - epp->ep_ssize), NULLVP, 0,
access_size = epp->ep_ssize;
access_linear_min = (u_long)STACK_ALLOC(epp->ep_minsaddr, access_size);
noaccess_size = max_stack_size - access_size;
noaccess_linear_min = (u_long)STACK_ALLOC(STACK_GROW(epp->ep_minsaddr,
access_size), noaccess_size);
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, noaccess_size,
noaccess_linear_min, NULLVP, 0, VM_PROT_NONE);
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, access_size,
access_linear_min, NULLVP, 0,
VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
return 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: init_main.c,v 1.210 2002/11/05 01:24:35 thorpej Exp $ */
/* $NetBSD: init_main.c,v 1.211 2002/11/17 22:53:46 chs Exp $ */
/*
* Copyright (c) 1995 Christopher G. Demetriou. All rights reserved.
@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.210 2002/11/05 01:24:35 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.211 2002/11/17 22:53:46 chs Exp $");
#include "fs_nfs.h"
#include "opt_nfsserver.h"
@ -622,14 +622,14 @@ start_init(void *arg)
/*
* Need just enough stack to hold the faked-up "execve()" arguments.
*/
addr = USRSTACK - PAGE_SIZE;
addr = (vaddr_t)STACK_ALLOC(USRSTACK, PAGE_SIZE);
if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
NULL, UVM_UNKNOWN_OFFSET, 0,
UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
UVM_ADV_NORMAL,
UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW)) != 0)
panic("init: couldn't allocate argument space");
p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
p->p_vmspace->vm_maxsaddr = (caddr_t)STACK_MAX(addr, PAGE_SIZE);
ipx = 0;
while (1) {
@ -653,7 +653,7 @@ start_init(void *arg)
break;
}
ucp = (char *)(addr + PAGE_SIZE);
ucp = (char *)USRSTACK;
/*
* Construct the boot flag argument.
@ -682,8 +682,9 @@ start_init(void *arg)
#ifdef DEBUG
printf("init: copying out flags `%s' %d\n", flags, i);
#endif
(void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
arg1 = ucp;
arg1 = STACK_ALLOC(ucp, i);
ucp = STACK_MAX(arg1, i);
(void)copyout((caddr_t)flags, arg1, i);
}
/*
@ -696,29 +697,27 @@ start_init(void *arg)
if (boothowto & RB_ASKNAME || path != initpaths[0])
printf("init: trying %s\n", path);
#endif
(void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
arg0 = ucp;
arg0 = STACK_ALLOC(ucp, i);
ucp = STACK_MAX(arg0, i);
(void)copyout((caddr_t)path, arg0, i);
/*
* Move out the arg pointers.
*/
uap = (char **)((long)ucp & ~ALIGNBYTES);
(void)suword((caddr_t)--uap, 0); /* terminator */
if (options != 0)
(void)suword((caddr_t)--uap, (long)arg1);
slash = strrchr(path, '/');
if (slash)
(void)suword((caddr_t)--uap,
(long)arg0 + (slash + 1 - path));
else
(void)suword((caddr_t)--uap, (long)arg0);
/*
* Point at the arguments.
*/
ucp = (caddr_t)STACK_ALIGN(ucp, ALIGNBYTES);
uap = (char **)STACK_ALLOC(ucp, sizeof(char *) * 3);
SCARG(&args, path) = arg0;
SCARG(&args, argp) = uap;
SCARG(&args, envp) = NULL;
slash = strrchr(path, '/');
if (slash)
(void)suword((caddr_t)uap++,
(long)arg0 + (slash + 1 - path));
else
(void)suword((caddr_t)uap++, (long)arg0);
if (options != 0)
(void)suword((caddr_t)uap++, (long)arg1);
(void)suword((caddr_t)uap++, 0); /* terminator */
/*
* Now try to exec the program. If can't for any reason

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_exec.c,v 1.162 2002/11/07 00:22:30 manu Exp $ */
/* $NetBSD: kern_exec.c,v 1.163 2002/11/17 22:53:46 chs Exp $ */
/*-
* Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.162 2002/11/07 00:22:30 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.163 2002/11/17 22:53:46 chs Exp $");
#include "opt_ktrace.h"
#include "opt_syscall_debug.h"
@ -568,7 +568,36 @@ sys_execve(struct proc *p, void *v, register_t *retval)
arginfo.ps_nargvstr = argc;
arginfo.ps_nenvstr = envc;
stack = (char *) (vm->vm_minsaddr - len);
stack = (char *)STACK_ALLOC(STACK_GROW(vm->vm_minsaddr,
sizeof(struct ps_strings) + szsigcode),
len - (sizeof(struct ps_strings) + szsigcode));
#ifdef __MACHINE_STACK_GROWS_UP
/*
* The copyargs call always copies into lower addresses
* first, moving towards higher addresses, starting with
* the stack pointer that we give. When the stack grows
* down, this puts argc/argv/envp very shallow on the
* stack, right at the first user stack pointer, and puts
* STACKGAPLEN very deep in the stack. When the stack
* grows up, the situation is reversed.
*
* Normally, this is no big deal. But the ld_elf.so _rtld()
* function expects to be called with a single pointer to
* a region that has a few words it can stash values into,
* followed by argc/argv/envp. When the stack grows down,
* it's easy to decrement the stack pointer a little bit to
* allocate the space for these few words and pass the new
* stack pointer to _rtld. When the stack grows up, however,
* a few words before argc is part of the signal trampoline,
* so we have a problem.
*
* Instead of changing how _rtld works, we take the easy way
* out and steal 32 bytes before we call copyargs. This
* space is effectively stolen from STACKGAPLEN.
*/
stack += 32;
#endif /* __MACHINE_STACK_GROWS_UP */
/* Now copy argc, args & environ to new stack */
error = (*pack.ep_es->es_copyargs)(p, &pack, &arginfo, &stack, argp);
if (error) {
@ -576,11 +605,11 @@ sys_execve(struct proc *p, void *v, register_t *retval)
goto exec_abort;
}
/* Move the stack back to original point */
stack = (char *) (vm->vm_minsaddr - len);
stack = (char *)STACK_GROW(vm->vm_minsaddr, len);
/* fill process ps_strings info */
p->p_psstr = (struct ps_strings *)(vm->vm_minsaddr
- sizeof(struct ps_strings));
p->p_psstr = (struct ps_strings *)STACK_ALLOC(vm->vm_minsaddr,
sizeof(struct ps_strings));
p->p_psargv = offsetof(struct ps_strings, ps_argvstr);
p->p_psnargv = offsetof(struct ps_strings, ps_nargvstr);
p->p_psenv = offsetof(struct ps_strings, ps_envstr);
@ -596,9 +625,10 @@ sys_execve(struct proc *p, void *v, register_t *retval)
/* copy out the process's signal trampoline code */
if (szsigcode) {
p->p_sigctx.ps_sigcode = STACK_ALLOC(STACK_MAX(p->p_psstr,
sizeof(struct ps_strings)), szsigcode);
if ((error = copyout((char *)pack.ep_es->es_emul->e_sigcode,
p->p_sigctx.ps_sigcode = (char *)p->p_psstr - szsigcode,
szsigcode)) != 0) {
p->p_sigctx.ps_sigcode, szsigcode)) != 0) {
DPRINTF(("execve: sig trampoline copyout failed\n"));
goto exec_abort;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: param.h,v 1.152 2002/11/01 12:49:49 mrg Exp $ */
/* $NetBSD: param.h,v 1.153 2002/11/17 22:53:46 chs Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@ -144,6 +144,37 @@
#include <machine/param.h>
#include <machine/limits.h>
/*
* Stack macros. On most architectures, the stack grows down,
* towards lower addresses; it is the rare architecture where
* it grows up, towards higher addresses.
*
* STACK_GROW and STACK_SHRINK adjust a stack pointer by some
* size, no questions asked. STACK_ALIGN aligns a stack pointer.
*
* STACK_ALLOC returns a pointer to allocated stack space of
* some size; given such a pointer and a size, STACK_MAX gives
* the maximum (in the "maxsaddr" sense) stack address of the
* allocated memory.
*/
#ifdef _KERNEL
#ifdef __MACHINE_STACK_GROWS_UP
#define STACK_GROW(sp, _size) (((caddr_t)(sp)) + (_size))
#define STACK_SHRINK(sp, _size) (((caddr_t)(sp)) - (_size))
#define STACK_ALIGN(sp, bytes) \
((caddr_t)((((unsigned long)(sp)) + (bytes)) & ~(bytes)))
#define STACK_ALLOC(sp, _size) ((caddr_t)(sp))
#define STACK_MAX(p, _size) (((caddr_t)(p)) + (_size))
#else
#define STACK_GROW(sp, _size) (((caddr_t)(sp)) - (_size))
#define STACK_SHRINK(sp, _size) (((caddr_t)(sp)) + (_size))
#define STACK_ALIGN(sp, bytes) \
((caddr_t)(((unsigned long)(sp)) & ~(bytes)))
#define STACK_ALLOC(sp, _size) (((caddr_t)(sp)) - (_size))
#define STACK_MAX(p, _size) ((caddr_t)(p))
#endif
#endif /* _KERNEL */
/*
* Priorities. Note that with 32 run queues, differences less than 4 are
* insignificant.