add support for __MACHINE_STACK_GROWS_UP platforms. from fredette@
This commit is contained in:
parent
4153f58dfe
commit
ab17ec89d1
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user