/*
* Now try to exec the program. If can't for any reason
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/kern_exec.c,v
retrieving revision 1.152
diff -u -r1.152 kern_exec.c
--- sys/kern/kern_exec.c 2002/04/23 15:11:25 1.152
+++ sys/kern/kern_exec.c 2002/07/08 00:50:22
@@ -545,7 +545,36 @@
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)(&pack, &arginfo, &stack, argp);
if (error) {
@@ -553,11 +582,11 @@
goto exec_abort;
}
/* Move the stack back to original point */
- stack = (char *) (vm->vm_minsaddr - len);
+ stack = (char *)__STACK_GROW(vm->vm_minsaddr, len);
/*
+ * 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 __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
+
+/*
* Priorities. Note that with 32 run queues, differences less than 4 are
* insignificant.
*/