]> Zhao Yanbai Git Server - minix.git/commitdiff
Removing CSU patches 41/941/2
authorLionel Sambuc <lionel@minix3.org>
Fri, 13 Sep 2013 18:12:22 +0000 (20:12 +0200)
committerLionel Sambuc <lionel@minix3.org>
Tue, 18 Feb 2014 10:25:02 +0000 (11:25 +0100)
 * Removed startup code patches in lib/csu regarding kernel to userland
   ABI.

 * Aligned stack layout on NetBSD stack layout.

 * Generate valid stack pointers instead of offsets by taking into account
   _minix_kerninfo->kinfo->user_sp.

 * Refactored stack generation, by moving part of execve in two
   functions {minix_stack_params(), minix_stack_fill()} and using them
   in execve(), rs and vm.

 * Changed load offset of rtld (ld.so) to:
      execi.args.stack_high - execi.args.stack_size - 0xa00000
   which is 10MB below the main executable stack.

Change-Id: I839daf3de43321cded44105634102d419cb36cec

29 files changed:
include/lib.h
include/minix/com.h
include/minix/ipc.h
include/minix/syslib.h
kernel/arch/earm/memory.c
kernel/arch/earm/protect.c
kernel/arch/i386/memory.c
kernel/arch/i386/protect.c
kernel/proto.h
kernel/system/do_exec.c
lib/csu/arch/earm/crt0.S
lib/csu/arch/i386/crt0.S
lib/csu/common/crt0-common.c
lib/libc/sys-minix/Makefile.inc
lib/libc/sys-minix/execve.c
lib/libc/sys-minix/stack_utils.c [new file with mode: 0644]
lib/libexec/exec_general.c
lib/libexec/libexec.h
lib/libminc/Makefile
lib/libsys/sys_exec.c
servers/pm/exec.c
servers/pm/main.c
servers/pm/proto.h
servers/rs/exec.c
servers/vfs/exec.c
servers/vfs/main.c
servers/vfs/proto.h
servers/vm/main.c
test/Makefile

index fa2761a3b01f42aa48781b650170e508ba2a3450..512714f66a1ea352c75fd11037c0a9ce79868bc5 100644 (file)
 
 #include <minix/ipc.h>
 
+struct ps_strings; /* forward declaration for minix_stack_fill. */
+
+void minix_stack_params(const char *path, char * const *argv, char * const *envp,
+       size_t *stack_size,  char *overflow, int *argc, int *envc);
+void minix_stack_fill(const char *path, int argc, char * const *argv,
+       int envc, char * const *envp, size_t stack_size, char *frame,
+       int *vsp, struct ps_strings **psp);
+
 int __execve(const char *_path, char *const _argv[], char *const
        _envp[], int _nargs, int _nenvps);
 int _syscall(endpoint_t _who, int _syscallnr, message *_msgptr);
index 47c93bccdd408cd0736659d803abad1479d88ddd..860a8e448361840faf3025a689d3ddeab0103623 100644 (file)
 #define PR_STACK_PTR    m1_p1  /* used for stack ptr in sys_exec, sys_getsp */
 #define PR_NAME_PTR     m1_p2  /* tells where program name is for dmp */
 #define PR_IP_PTR       m1_p3  /* initial value for ip after exec */
+#define PR_PS_STR_PTR   m1_p4  /* pointer to ps_strings, expected by __start */
 #define PR_FORK_FLAGS  m1_i3   /* optional flags for fork operation */
 #define PR_FORK_MSGADDR m1_p1  /* reply message address of forked child */
 #define PR_CTX_PTR     m1_p1   /* pointer to mcontext_t structure */
 #define PMEXEC_FLAGS   m1_i3   /* PMEF_* */
 
 #define PMEF_AUXVECTORS        20
-#define PMEF_EXECNAMELEN1 256
-#define PMEF_AUXVECTORSPACE 0x01 /* space for PMEF_AUXVECTORS on stack */
-#define PMEF_EXECNAMESPACE1 0x02 /* space for PMEF_EXECNAMELEN1 execname */
+#define PMEF_EXECNAMELEN1 PATH_MAX
 
 /* Flags for PR_FORK_FLAGS. */
 #define PFF_VMINHIBIT  0x01    /* Don't schedule until release by VM. */
 #  define PM_FRAME             m7_p2   /* arguments and environment */
 #  define PM_FRAME_LEN         m7_i3   /* size of frame */
 #  define PM_EXECFLAGS         m7_i4   /* PMEXEC_FLAGS */
+#  define PM_PS_STR            m7_i5   /* ps_strings pointer */
 
 /* Additional parameters for PM_EXEC_REPLY and PM_CORE_REPLY */
 #  define PM_STATUS            m7_i2   /* OK or failure */
 #  define PM_PC                        m7_p1   /* program counter */
 #  define PM_NEWSP             m7_p2   /* possibly-changed stack ptr */
+#  define PM_NEWPS_STR         m7_i5   /* possibly-changed ps_strings ptr */
 
 /* Additional parameters for PM_FORK and PM_SRV_FORK */
 #  define PM_PPROC             m7_i2   /* parent process endpoint */
 #define EXC_RS_PROC    m1_i1           /* process that needs to be restarted */
 #define EXC_RS_RESULT  m1_i2           /* result of the exec */
 #define EXC_RS_PC      m1_p1           /* program counter */
+#define EXC_RS_PS_STR  m1_p2           /* ps_strings pointer */
 
 /*===========================================================================*
  *                Messages used from VFS to file servers                    *
index 24ef9eee208c94a40e7259c3f59b266cf57c293b..c703ad9256201f08b1407c6e3ffc0ba75adaa4d7 100644 (file)
@@ -15,7 +15,7 @@
 #define M3_STRING         16   /* legacy m3_ca1 size (must not be changed) */
 #define M3_LONG_STRING    16   /* current m3_ca1 size (may be increased) */
 
-typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1;
+typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3, *m1p4;} mess_1;
 typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1; 
         short m2s1;} mess_2;
 typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_LONG_STRING];} mess_3;
@@ -84,6 +84,7 @@ typedef struct {
 #define m1_p1  m_u.m_m1.m1p1
 #define m1_p2  m_u.m_m1.m1p2
 #define m1_p3  m_u.m_m1.m1p3
+#define m1_p4  m_u.m_m1.m1p4
 
 #define m2_i1  m_u.m_m2.m2i1
 #define m2_i2  m_u.m_m2.m2i2
index 0d1a922da328e6a33cfc04b560f5495472f8f789..c789acc7f6a96c0b9f0cb42a3c8be01db5327b08 100644 (file)
@@ -30,8 +30,8 @@ int _sendcall(endpoint_t who, int type, message *msgptr);
 
 int sys_abort(int how);
 int sys_enable_iop(endpoint_t proc_ep);
-int sys_exec(endpoint_t proc_ep, char *ptr, char *aout, vir_bytes
-       initpc);
+int sys_exec(endpoint_t proc_ep, char *stack_ptr, char *progname,
+       vir_bytes pc, vir_bytes ps_str);
 int sys_fork(endpoint_t parent, endpoint_t child, endpoint_t *, 
        u32_t vm, vir_bytes *);
 int sys_clear(endpoint_t proc_ep);
index 607a3a413fd64696ef665d33aa728b2d0f26df54..f3a4e260c6862d9c1b714c26aa146fdeb7e3249c 100644 (file)
@@ -672,7 +672,8 @@ void memory_init(void)
 /*===========================================================================*
  *                             arch_proc_init                               *
  *===========================================================================*/
-void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp, char *name)
+void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp,
+       const u32_t ps_str, char *name)
 {
        arch_proc_reset(pr);
        strcpy(pr->p_name, name);
@@ -680,6 +681,7 @@ void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp, char *name)
        /* set custom state we know */
        pr->p_reg.pc = ip;
        pr->p_reg.sp = sp;
+       pr->p_reg.retreg = ps_str; /* a.k.a r0*/
 }
 
 /* TODO keesj: rewrite the free running clock to use callbacks
index 73e37a33906e6ee0833fef80f11b62867f7cde5f..2db24007c48dbab89d156319a941357be592511f 100644 (file)
@@ -3,16 +3,17 @@
  * for local descriptors in the process table.
  */
 
-#include <string.h>
 #include <assert.h>
+#include <string.h>
+
 #include <machine/multiboot.h>
 
 #include "kernel/kernel.h"
-#include "kernel/proc.h"
-#include "archconst.h"
 
+#include "archconst.h"
 #include "arch_proto.h"
 
+#include <sys/exec.h>
 #include <libexec.h>
 
 struct tss_s tss[CONFIG_MAX_CPUS];
@@ -114,6 +115,8 @@ static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len
 void arch_boot_proc(struct boot_image *ip, struct proc *rp)
 {
        multiboot_module_t *mod;
+       struct ps_strings *psp;
+       char *sp;
 
        if(rp->p_nr < 0) return;
 
@@ -134,24 +137,41 @@ void arch_boot_proc(struct boot_image *ip, struct proc *rp)
                execi.proc_e = ip->endpoint;
                execi.hdr = (char *) mod->mod_start; /* phys mem direct */
                execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start;
-               strcpy(execi.progname, ip->proc_name);
+               strlcpy(execi.progname, ip->proc_name, sizeof(execi.progname));
                execi.frame_len = 0;
 
                /* callbacks for use in the kernel */
                execi.copymem = libexec_copy_memcpy;
                execi.clearmem = libexec_clear_memset;
-               execi.allocmem_prealloc_cleared = libexec_pg_alloc;
                execi.allocmem_prealloc_junk = libexec_pg_alloc;
+               execi.allocmem_prealloc_cleared = libexec_pg_alloc;
                execi.allocmem_ondemand = libexec_pg_alloc;
                execi.clearproc = NULL;
 
                /* parse VM ELF binary and alloc/map it into bootstrap pagetable */
-               libexec_load_elf(&execi);
+               if(libexec_load_elf(&execi) != OK)
+                       panic("VM loading failed");
+
+               /* Setup a ps_strings struct on the stack, pointing to the
+                * following argv, envp. */
+               sp = (char *)execi.stack_high;
+               sp -= sizeof(struct ps_strings);
+               psp = (struct ps_strings *) sp;
 
-               /* Initialize the server stack pointer. Take it down three words
-                * to give startup code something to use as "argc", "argv" and "envp".
+               /* Take the stack pointer down three words to give startup code
+                * something to use as "argc", "argv" and "envp".
                 */
-               arch_proc_init(rp, execi.pc, kinfo.user_sp - 3*4, ip->proc_name);
+               sp -= (sizeof(void *) + sizeof(void *) + sizeof(int));
+
+               // linear address space, so it is available.
+               psp->ps_argvstr = (char **)(sp + sizeof(int));
+               psp->ps_nargvstr = 0;
+               psp->ps_envstr = psp->ps_argvstr + sizeof(void *);
+               psp->ps_nenvstr = 0;
+
+               arch_proc_init(rp, execi.pc, (vir_bytes)sp,
+                       execi.stack_high - sizeof(struct ps_strings),
+                       ip->proc_name);
 
                /* Free VM blob that was just copied into existence. */
                add_memmap(&kinfo, mod->mod_start, mod->mod_end-mod->mod_start);
index be3687aca3995fe73a8c3c607ac5ddc7807753c1..24b866f0b603df8d3d79a69a6851bba631ad3e62 100644 (file)
@@ -770,7 +770,8 @@ void memory_init(void)
 /*===========================================================================*
  *                             arch_proc_init                               *
  *===========================================================================*/
-void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp, char *name)
+void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp,
+       const u32_t ps_str, char *name)
 {
        arch_proc_reset(pr);
        strlcpy(pr->p_name, name, sizeof(pr->p_name));
@@ -778,6 +779,7 @@ void arch_proc_init(struct proc *pr, const u32_t ip, const u32_t sp, char *name)
        /* set custom state we know */
        pr->p_reg.pc = ip;
        pr->p_reg.sp = sp;
+       pr->p_reg.bx = ps_str;
 }
 
 static int oxpcie_mapping_index = -1,
index 0a9d2d25d16ffb5dcee53b08d3fb603ae4c85261..5baf44f83bab93fbfcd7d7e38bd768d08a1188ef 100644 (file)
@@ -3,16 +3,17 @@
  * for local descriptors in the process table.
  */
 
-#include <string.h>
 #include <assert.h>
+#include <string.h>
+
 #include <minix/cpufeature.h>
 #include <machine/multiboot.h>
-
 #include "kernel/kernel.h"
-#include "archconst.h"
 
+#include "archconst.h"
 #include "arch_proto.h"
 
+#include <sys/exec.h>
 #include <libexec.h>
 
 #define INT_GATE_TYPE  (INT_286_GATE | DESC_386_BIT)
@@ -388,6 +389,8 @@ static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len
 void arch_boot_proc(struct boot_image *ip, struct proc *rp)
 {
        multiboot_module_t *mod;
+       struct ps_strings *psp;
+       char *sp;
 
        if(rp->p_nr < 0) return;
 
@@ -404,7 +407,7 @@ void arch_boot_proc(struct boot_image *ip, struct proc *rp)
 
                /* exec parameters */
                execi.stack_high = kinfo.user_sp;
-               execi.stack_size = 64 * 1024;   /* not too crazy as it must be preallocated */
+               execi.stack_size = 64 * 1024;   /* not too crazy as it must be preallocated */
                execi.proc_e = ip->endpoint;
                execi.hdr = (char *) mod->mod_start; /* phys mem direct */
                execi.filesize = execi.hdr_len = mod->mod_end - mod->mod_start;
@@ -423,14 +426,30 @@ void arch_boot_proc(struct boot_image *ip, struct proc *rp)
                if(libexec_load_elf(&execi) != OK)
                        panic("VM loading failed");
 
-               /* Initialize the server stack pointer. Take it down three words
-                * to give startup code something to use as "argc", "argv" and "envp".
+               /* Setup a ps_strings struct on the stack, pointing to the
+                * following argv, envp. */
+               sp = (char *)execi.stack_high;
+               sp -= sizeof(struct ps_strings);
+               psp = (struct ps_strings *) sp;
+
+               /* Take the stack pointer down three words to give startup code
+                * something to use as "argc", "argv" and "envp".
                 */
-               arch_proc_init(rp, execi.pc, kinfo.user_sp - 3*4, ip->proc_name);
+               sp -= (sizeof(void *) + sizeof(void *) + sizeof(int));
+
+               // linear address space, so it is available.
+               psp->ps_argvstr = (char **)(sp + sizeof(int));
+               psp->ps_nargvstr = 0;
+               psp->ps_envstr = psp->ps_argvstr + sizeof(void *);
+               psp->ps_nenvstr = 0;
+
+               arch_proc_init(rp, execi.pc, (vir_bytes)sp,
+                       execi.stack_high - sizeof(struct ps_strings),
+                       ip->proc_name);
 
                /* Free VM blob that was just copied into existence. */
                add_memmap(&kinfo, mod->mod_start, mod->mod_end-mod->mod_start);
-                mod->mod_end = mod->mod_start = 0;
+               mod->mod_end = mod->mod_start = 0;
 
                /* Remember them */
                kinfo.vm_allocated_bytes = alloc_for_vm;
index 9ac2fd483b9049c2d95fec16d43350c07bedcfea..a26f9cb5648a3e1f95722852572ba18cb94a4145 100644 (file)
@@ -192,7 +192,7 @@ void do_ser_debug(void);
 int arch_get_params(char *parm, int max);
 void memory_init(void);
 void mem_clear_mapcache(void);
-void arch_proc_init(struct proc *pr, u32_t, u32_t, char *);
+void arch_proc_init(struct proc *pr, u32_t, u32_t, u32_t, char *);
 int arch_do_vmctl(message *m_ptr, struct proc *p);
 int vm_contiguous(const struct proc *targetproc, vir_bytes vir_buf,
        size_t count);
index 74370544b6d916286a2e97dd3b5c2d70a9b17ca2..9c038a131bbd26c930fcecd876537542b910403d 100644 (file)
@@ -41,7 +41,8 @@ int do_exec(struct proc * caller, message * m_ptr)
   name[sizeof(name)-1] = '\0';
 
   /* Set process state. */
-  arch_proc_init(rp, (u32_t) m_ptr->PR_IP_PTR, (u32_t) m_ptr->PR_STACK_PTR, name);
+  arch_proc_init(rp, (u32_t) m_ptr->PR_IP_PTR, (u32_t) m_ptr->PR_STACK_PTR,
+       (u32_t) m_ptr->PR_PS_STR_PTR, name);
 
   /* No reply to EXEC call */
   RTS_UNSET(rp, RTS_RECEIVING);
index 5c964807fa80192044444fd7c861a7d23e8bea6f..1359874bf91a1c1c4761f7dff66e771c81d1314c 100644 (file)
@@ -36,33 +36,16 @@ RCSID("$NetBSD: crt0.S,v 1.1 2012/08/13 02:49:04 matt Exp $")
 STRONG_ALIAS(_start,__start)
 
 _ENTRY(__start)
-#ifdef __minix
-       mov     r3, r2          /* cleanup */
-       mov     r4, r1          /* obj_main */
-       and     r5, r5, #0      /* ps_strings, always NULL on MINIX */
-
-       /* Get argc, argv, and envp from stack */
-       ldr     r0, [sp, #0]    /* get argc */
-       add     r1, sp, #4      /* argv = sp + 4 */
-       add     r2, r1, r0, lsl #2      /* envp = argv + argc*4 */
-       add     r2, r2, #4      /* skip NULL terminator */
-#else
        /*
         * We need to swap ps_strings and cleanup
         */
        mov     ip, r0          /* ps_strings -> tmp */
        mov     r0, r2          /* cleanup -> ps_strings */
        mov     r2, ip          /* tmp -> ps_strings */
-#endif /* __minix */
+
        /* Ensure the stack is properly aligned before calling C code. */
        bic     sp, sp, #7
 
-#ifdef __minix
-       /* Store obj and ps_strings on the stack */
-       sub     sp, sp, #8
-       str     r5, [sp, #4]
-       str     r4, [sp, #0]
-#endif
        /*
         * void ___start(void (*cleanup)(void),
         *    const Obj_Entry *obj,
index 1029f7a7d899e99bc65cae8d0b8b69748af9dbe9..9adabdd21976cd8fd4eb053a90a9bfe49b023a66 100644 (file)
@@ -46,12 +46,4 @@ _ENTRY(__start)
        pushl   %ebx
        pushl   %ecx
        pushl   %edx
-#ifdef __minix
-       movl    12(%esp),%eax
-       leal    16(%esp),%edx
-       leal    20(%esp,%eax,4),%ecx
-       pushl   %ecx
-       pushl   %edx
-       pushl   %eax
-#endif /* __minix */
        call    ___start
index 3766cac1cca93b585747e0b984e34b1c745dbe3d..98d60adbc1441af8f5a8d6ddbbd5ddd419efd17e 100644 (file)
@@ -80,15 +80,12 @@ struct ps_strings *__ps_strings = 0;
 static char     empty_string[] = "";
 char           *__progname = empty_string;
 
-#ifndef __minix
 __dead __dso_hidden void ___start(void (*)(void), const Obj_Entry *,
                         struct ps_strings *);
 
+#ifndef __minix
 #define        write(fd, s, n) __syscall(SYS_write, (fd), (s), (n))
 #else
-__dead __dso_hidden void ___start(int, char **, char **, void (*)(void),
-                       const Obj_Entry *, struct ps_strings *);
-
 #define        write(fd, s, n) /* NO write() from here on minix */
 #endif
 
@@ -129,30 +126,11 @@ _fini(void)
 #endif /* HAVE_INITFINI_ARRAY */
 
 void
-#ifdef __minix
-___start(int argc, char **argv, char **envp,
-    void (*cleanup)(void),                 /* from shared loader */
-#else
 ___start(void (*cleanup)(void),                        /* from shared loader */
-#endif /* __minix */
     const Obj_Entry *obj,                      /* from shared loader */
     struct ps_strings *ps_strings)
 {
-#ifdef __minix
-       /* LSC: We have not yet updated the way we pass arguments to 
-               the userspace, so here some code to adapt this to the new 
-               ways. */
-       struct ps_strings minix_ps_strings;
-
-       if (ps_strings == NULL) {
-               memset(&minix_ps_strings, 0, sizeof(minix_ps_strings));
-
-               minix_ps_strings.ps_envstr = envp;
-               minix_ps_strings.ps_argvstr = argv;
-               minix_ps_strings.ps_nargvstr = argc;
-               ps_strings = &minix_ps_strings;
-       }
-#endif /* __minix */
+
        if (ps_strings == NULL)
                _FATAL("ps_strings missing\n");
        __ps_strings = ps_strings;
index 38ef33de876c4713d2ffcfae2685c63d9e081df4..22c40942034b8964dc0dbcbbdade4db8a231bac2 100644 (file)
@@ -23,6 +23,6 @@ SRCS+=        accept.c access.c adjtime.c bind.c brk.c sbrk.c m_closefrom.c getsid.c \
        getrusage.c
 
 # Minix specific syscalls.
-SRCS+= cprofile.c lseek64.c sprofile.c _mcontext.c
+SRCS+= cprofile.c lseek64.c sprofile.c stack_utils.c _mcontext.c
 
 .include "${ARCHDIR}/sys-minix/Makefile.inc"
index 27b350584b74bb72322e5fa604582c28462b4df0..95ca5a9db88b0b42a12c6ce8e00775ee4b2d5f55 100644 (file)
@@ -1,6 +1,4 @@
-/*     execve() - basic program execution call         Author: Kees J. Bot
- *                                                             21 Jan 1994
- */
+/* execve() - basic program execution call */
 
 #include <sys/cdefs.h>
 #include "namespace.h"
@@ -9,7 +7,9 @@
 #include <unistd.h>
 #include <string.h>
 #include <stddef.h>
+#include <minix/param.h>
 #include <sys/exec_elf.h>
+#include <sys/exec.h>
 
 #ifdef __weak_alias
 __weak_alias(execve, _execve)
@@ -17,62 +17,21 @@ __weak_alias(execve, _execve)
 
 int execve(const char *path, char * const *argv, char * const *envp)
 {
-       char * const *ap;
-       char * const *ep;
-       char *frame;
-       char **vp;
-       char *sp;
-       size_t argc;
-       int extra;
-       int vectors;
-       size_t frame_size;
-       size_t string_off;
-       size_t n;
-       int ov;
        message m;
+       size_t frame_size = 0;  /* Size of the new initial stack. */
+       int argc = 0;           /* Argument count. */
+       int envc = 0;           /* Environment count */
+       char overflow = 0;      /* No overflow yet. */
+       char *frame;
+       struct ps_strings *psp;
+       int vsp = 0;    /* (virtual) Stack pointer in new address space. */
 
-       /* Assumptions: size_t and char *, it's all the same thing. */
-
-       /* Create a stack image that only needs to be patched up slightly
-        * by the kernel to be used for the process to be executed.
-        */
-
-       ov= 0;                  /* No overflow yet. */
-       frame_size= 0;          /* Size of the new initial stack. */
-       string_off= 0;          /* Offset to start of the strings. */
-       argc= 0;                /* Argument count. */
-
-       for (ap= argv; *ap != NULL; ap++) {
-               n = sizeof(*ap) + strlen(*ap) + 1;
-               frame_size+= n;
-               if (frame_size < n) ov= 1;
-               string_off+= sizeof(*ap);
-               argc++;
-       }
-
-       for (ep= envp; *ep != NULL; ep++) {
-               n = sizeof(*ep) + strlen(*ep) + 1;
-               frame_size+= n;
-               if (frame_size < n) ov= 1;
-               string_off+= sizeof(*ap);
-       }
-
-       /* Add an argument count, two terminating nulls and
-        * space for the ELF aux vectors, that must come before
-        * (i.e. at a higher address) then the strings.
-        */
-       vectors = sizeof(argc) + sizeof(*ap) + sizeof(*ep) +
-               sizeof(AuxInfo) * PMEF_AUXVECTORS;
-       extra = vectors + PMEF_EXECNAMELEN1;
-       frame_size+= extra;
-       string_off+= extra;
-
-       /* Align. */
-       frame_size= (frame_size + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
+       minix_stack_params(path, argv, envp, &frame_size, &overflow,
+               &argc, &envc);
 
        /* The party is off if there is an overflow. */
-       if (ov || frame_size < 3 * sizeof(char *)) {
-               errno= E2BIG;
+       if (overflow) {
+               errno = E2BIG;
                return -1;
        }
 
@@ -82,31 +41,8 @@ int execve(const char *path, char * const *argv, char * const *envp)
                return -1;
        }
 
-       /* Set arg count, init pointers to vector and string tables. */
-       * (size_t *) frame = argc;
-       vp = (char **) (frame + sizeof(argc));
-       sp = frame + string_off;
-
-       /* Load the argument vector and strings. */
-       for (ap= argv; *ap != NULL; ap++) {
-               *vp++= (char *) (sp - frame);
-               n= strlen(*ap) + 1;
-               memcpy(sp, *ap, n);
-               sp+= n;
-       }
-       *vp++= NULL;
-
-       /* Load the environment vector and strings. */
-       for (ep= envp; *ep != NULL; ep++) {
-               *vp++= (char *) (sp - frame);
-               n= strlen(*ep) + 1;
-               memcpy(sp, *ep, n);
-               sp+= n;
-       }
-       *vp++= NULL;
-
-       /* Padding. */
-       while (sp < frame + frame_size) *sp++= 0;
+       minix_stack_fill(path, argc, argv, envc, envp, frame_size, frame,
+               &vsp, &psp);
 
        /* Clear unused message fields */
        memset(&m, 0, sizeof(m));
@@ -116,15 +52,12 @@ int execve(const char *path, char * const *argv, char * const *envp)
        m.m1_i2 = frame_size;
        m.m1_p1 = (char *) __UNCONST(path);
        m.m1_p2 = frame;
-
-       /* Tell PM/VFS we have left space for the aux vectors
-        * and executable name
-        */
-       m.PMEXEC_FLAGS = PMEF_AUXVECTORSPACE | PMEF_EXECNAMESPACE1;
+       m.m1_p4 = (char *)(vsp + ((char *)psp - frame));
 
        (void) _syscall(PM_PROC_NR, EXEC, &m);
 
        /* Failure, return the memory used for the frame and exit. */
        (void) sbrk(-frame_size);
+
        return -1;
 }
diff --git a/lib/libc/sys-minix/stack_utils.c b/lib/libc/sys-minix/stack_utils.c
new file mode 100644 (file)
index 0000000..ef38078
--- /dev/null
@@ -0,0 +1,177 @@
+/* Utilities to generate a proper C stack.
+ *
+ * Author: Lionel A. Sambuc. 
+ */
+
+#include <sys/cdefs.h>
+#include "namespace.h"
+#include <lib.h>
+
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+#include <minix/param.h>
+#include <sys/exec_elf.h>
+#include <sys/exec.h>
+
+#ifdef __weak_alias
+__weak_alias(execve, _execve)
+#endif
+
+extern struct minix_kerninfo *_minix_kerninfo;
+
+/* Create a stack image that only needs to be patched up slightly by
+ * the kernel to be used for the process to be executed.
+ *
+ * Every pointers are stored here as offset from the frame base, and
+ * will be adapted as required for the new process address space.
+ *
+ * The following parameters are passed by register to either __start
+ * for static binaries, or _rtld_start for dynamic ones:
+ *     *fct, *ObjEntry, *ps_string
+ *
+ * The following stack layout is expected by _rtld():
+ *
+ * | XXXXXXXXXX | 0x0000_00000
+ * |  ...       |
+ * |  ...       | Top of the stack
+ * | argc       |
+ * | *argv1     | points to the first char of the argv1
+ * |  ...       |
+ * | *argvN     |
+ * | NULL       |
+ * | *env1      | 
+ * |  ...       |
+ * | *envN      |
+ * | NULL       |
+ * | ElfAuxV1   |
+ * |  ...       |
+ * | ElfAuxVX   |
+ * | AuxExecName| fully resolve executable name, as an ASCIIZ string,
+ *                at most PMEF_EXECNAMELEN1 long.
+ * 
+ * Here we put first the strings, then word-align, then ps_strings, to
+ * comply with the expected layout of NetBSD. This seems to matter for
+ * the NetBSD ps command, so let's make sure we are compatible...
+ *
+ * | strings    | Maybe followed by some padding to word-align.
+ * | **argv     | \
+ * | argc       |  +---> ps_string structure content.
+ * | **env      |  |
+ * | envc       | /
+ * | sigcode    | On NetBSD, there may be a compatibility stub here,
+ * +------------+    for native code, it is not present.
+ *   Stack Base , 0xF000_0000, descending stack.
+ */
+
+/* The minimum size of the frame is composed of:
+ * argc, the NULL terminator for argv as well as one for
+ * environ, the ELF Aux vectors, executable name and the
+ * ps_strings struct. */
+#define STACK_MIN_SZ \
+( \
+       sizeof(int) + sizeof(void *) * 2 + \
+       sizeof(AuxInfo) * PMEF_AUXVECTORS + PMEF_EXECNAMELEN1 + \
+       sizeof(struct ps_strings) \
+)
+
+/***************************************************************************** 
+ * Computes stack size, argc, envc, for a given set of path, argv, envp.     *
+ *****************************************************************************/
+void minix_stack_params(const char *path, char * const *argv, char * const *envp,
+       size_t *stack_size,  char *overflow, int *argc, int *envc)
+{
+       char * const *p;
+       size_t const min_size = STACK_MIN_SZ;
+
+       *stack_size = min_size; /* Size of the new initial stack. */
+       *overflow = 0;          /* No overflow yet. */
+       *argc = 0;              /* Argument count. */
+       *envc = 0;              /* Environment count */
+
+       /* Compute and add the size required to store argv and env. */
+       for (p = argv; *p != NULL; p++) {
+               size_t const n = sizeof(*p) + strlen(*p) + 1;
+               *stack_size += n;
+               if (*stack_size < n) {
+                       *overflow = 1;
+               }
+               (*argc)++;
+       }
+
+       for (p = envp; *p != NULL; p++) {
+               size_t const n = sizeof(*p) + strlen(*p) + 1;
+               *stack_size += n;
+               if (*stack_size < n) {
+                       *overflow = 1;
+               }
+               (*envc)++;
+       }
+
+       /* Compute the aligned frame size. */
+       *stack_size = (*stack_size + sizeof(void *) - 1) &
+                ~(sizeof(void *) - 1);
+
+       if (*stack_size < min_size) {
+               /* This is possible only in case of overflow. */
+               *overflow = 1;
+       }
+}
+
+/*****************************************************************************
+ * Generate a stack in the buffer frame, ready to be used.                   *
+ *****************************************************************************/
+void minix_stack_fill(const char *path, int argc, char * const *argv,
+       int envc, char * const *envp, size_t stack_size, char *frame,
+       int *vsp, struct ps_strings **psp)
+{
+       char * const *p;
+
+       /* Frame pointers (a.k.a stack pointer within the buffer in current
+        * address space.) */
+       char *fp;       /* byte aligned */
+       char **fpw;     /* word aligned */
+
+       size_t const min_size = STACK_MIN_SZ;
+
+       /* Virtual address of the stack pointer, in new memory space. */
+       *vsp = _minix_kerninfo->kinfo->user_sp - stack_size;
+
+       /* Fill in the frame now. */
+       fpw = (char **) frame;
+       *fpw++ = (char *) argc;
+
+       /* The strings themselves are stored after the aux vectors,
+        * cf. top comment. */
+       fp = frame + (min_size - sizeof(struct ps_strings)) + 
+               (envc + argc) * sizeof(char *);
+       
+       /* Fill in argv and the environment, as well as copy the strings
+        * themselves. */
+       for (p = argv; *p != NULL; p++) {
+               size_t const n = strlen(*p) + 1;
+               *fpw++= (char *)(*vsp + (fp - frame));
+               memcpy(fp, *p, n);
+               fp += n;
+       }
+       *fpw++ = NULL;
+
+       for (p = envp; *p != NULL; p++) {
+               size_t const n = strlen(*p) + 1;
+               *fpw++= (char *)(*vsp + (fp - frame));
+               memcpy(fp, *p, n);
+               fp += n;
+       }
+       *fpw++ = NULL;
+
+       /* Padding, because of the stack alignement. */
+       while ((size_t)fp % sizeof(void *)) *fp++= 0;
+
+       /* Fill in the ps_string struct*/
+       *psp = (struct ps_strings *) fp;
+
+       (*psp)->ps_argvstr = (char **)(*vsp + sizeof(argc));
+       (*psp)->ps_nargvstr = argc;
+       (*psp)->ps_envstr = (*psp)->ps_argvstr + argc + 1;
+       (*psp)->ps_nenvstr = envc;
+}
index e9145c6110131dccfa4798a452edbf9913ff7447..3a38516b9f5ded130cb7e70971afc5a2b001adc5 100644 (file)
@@ -75,33 +75,6 @@ int libexec_clear_memset(struct exec_info *execi, vir_bytes vaddr, size_t len)
        return OK;
 }
 
-void libexec_patch_ptr(char stack[ARG_MAX], vir_bytes base)
-{
-/* When doing an exec(name, argv, envp) call, the user builds up a stack
- * image with arg and env pointers relative to the start of the stack.  Now
- * these pointers must be relocated, since the stack is not positioned at
- * address 0 in the user's address space.
- */
-
-  char **ap, flag;
-  vir_bytes v;
-
-  flag = 0;                     /* counts number of 0-pointers seen */
-  ap = (char **) stack;         /* points initially to 'nargs' */
-  ap++;                         /* now points to argv[0] */
-  while (flag < 2) {
-        if (ap >= (char **) &stack[ARG_MAX]) return;    /* too bad */
-        if (*ap != NULL) {
-                v = (vir_bytes) *ap;    /* v is relative pointer */
-                v += base;              /* relocate it */
-                *ap = (char *) v;       /* put it back */
-        } else {
-                flag++;
-        }
-        ap++;
-  }
-}
-
 int libexec_pm_newexec(endpoint_t proc_e, struct exec_info *e)
 {
   int r;
index b9ba03ee50c582d873fb50af355e38bf54db5c48..f7e218fd15b848a86e8f6c8086c4e2883c95c8ed 100644 (file)
@@ -55,7 +55,6 @@ struct exec_info {
 int elf_has_interpreter(char *exec_hdr, int hdr_len, char *interp, int maxsz);
 int elf_phdr(char *exec_hdr, int hdr_len, vir_bytes *phdr);
 
-void libexec_patch_ptr(char stack[ARG_MAX], vir_bytes base);
 int libexec_pm_newexec(endpoint_t proc_e, struct exec_info *execi);
 
 typedef int (*libexec_exec_loadfunc_t)(struct exec_info *execi);
index 18da0cf027187abd9b20b58b8e6cf366e2ffe57e..2530ed93843b392267d6b88b198e7baf4fcab060 100644 (file)
@@ -146,8 +146,8 @@ CPPFLAGS.${i}+= -I${LIBCDIR}/locale
 .for i in access.c brk.c close.c environ.c execve.c fork.c \
        getgid.c getpid.c geteuid.c getuid.c gettimeofday.c getvfsstat.c \
        link.c loadname.c _mcontext.c mknod.c mmap.c nanosleep.c open.c \
-       read.c reboot.c sbrk.c select.c setuid.c sigprocmask.c stat.c \
-       stime.c syscall.c _ucontext.c umask.c unlink.c waitpid.c \
+       read.c reboot.c sbrk.c select.c setuid.c sigprocmask.c stack_utils.c \
+       stat.c stime.c syscall.c _ucontext.c umask.c unlink.c waitpid.c \
        brksize.S _ipc.S _senda.S ucontext.S mmap.c init.c
 .PATH.c: ${LIBCDIR}/sys-minix
 .PATH.S: ${ARCHDIR}/sys-minix
index cd84d6a39b605d82e4df5baffa1e25152a244ec3..342dd4a440e76ce912909eda902de16e138357d8 100644 (file)
@@ -1,18 +1,17 @@
 #include "syslib.h"
 
-int sys_exec(proc_ep, ptr, prog_name, initpc)
-endpoint_t proc_ep;            /* process that did exec */
-char *ptr;                     /* new stack pointer */
-char *prog_name;               /* name of the new program */
-vir_bytes initpc;
+int sys_exec(endpoint_t proc_ep, char *stack_ptr, char *progname,
+       vir_bytes pc, vir_bytes ps_str)
 {
 /* A process has exec'd.  Tell the kernel. */
 
-  message m;
+       message m;
 
-  m.PR_ENDPT = proc_ep;
-  m.PR_STACK_PTR = ptr;
-  m.PR_NAME_PTR = prog_name;
-  m.PR_IP_PTR = (char *)initpc;
-  return(_kernel_call(SYS_EXEC, &m));
+       m.PR_ENDPT = proc_ep;
+       m.PR_STACK_PTR = stack_ptr;
+       m.PR_NAME_PTR = progname;
+       m.PR_IP_PTR = (char *)pc;
+       m.PR_PS_STR_PTR = (char *)ps_str; 
+
+       return _kernel_call(SYS_EXEC, &m);
 }
index 4691c731bf0b5d509c960b624aa285138c9439a3..89285920b1d2d4cda0ee865024ad4ec0e4574e12 100644 (file)
@@ -48,6 +48,7 @@ int do_exec()
        m.PM_FRAME = m_in.frame_ptr;
        m.PM_FRAME_LEN = m_in.msg_frame_len;
        m.PM_EXECFLAGS = m_in.PMEXEC_FLAGS;
+       m.PM_PS_STR = (vir_bytes)m_in.m1_p4; /* ps_strings pointer into the frame. */
 
        tell_vfs(mp, &m);
 
@@ -59,7 +60,7 @@ int do_exec()
 /*===========================================================================*
  *                             do_newexec                                   *
  *===========================================================================*/
-int do_newexec()
+int do_newexec(void)
 {
        int proc_e, proc_n, allow_setuid;
        char *ptr;
@@ -127,24 +128,25 @@ int do_newexec()
 /*===========================================================================*
  *                             do_execrestart                               *
  *===========================================================================*/
-int do_execrestart()
+int do_execrestart(void)
 {
        int proc_e, proc_n, result;
        struct mproc *rmp;
-       vir_bytes pc;
+       vir_bytes pc, ps_str;
 
        if (who_e != RS_PROC_NR)
                return EPERM;
 
-       proc_e= m_in.EXC_RS_PROC;
+       proc_e = m_in.EXC_RS_PROC;
        if (pm_isokendpt(proc_e, &proc_n) != OK) {
                panic("do_execrestart: got bad endpoint: %d", proc_e);
        }
-       rmp= &mproc[proc_n];
-       result= m_in.EXC_RS_RESULT;
-       pc= (vir_bytes)m_in.EXC_RS_PC;
+       rmp = &mproc[proc_n];
+       result = m_in.EXC_RS_RESULT;
+       pc = (vir_bytes)m_in.EXC_RS_PC;
+       ps_str = (vir_bytes)m_in.EXC_RS_PS_STR;
 
-       exec_restart(rmp, result, pc, rmp->mp_frame_addr);
+       exec_restart(rmp, result, pc, rmp->mp_frame_addr, ps_str);
 
        return OK;
 }
@@ -153,11 +155,8 @@ int do_execrestart()
 /*===========================================================================*
  *                             exec_restart                                 *
  *===========================================================================*/
-void exec_restart(rmp, result, pc, vfs_newsp)
-struct mproc *rmp;
-int result;
-vir_bytes pc;
-vir_bytes vfs_newsp;
+void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp,
+       vir_bytes ps_str)
 {
        int r, sn;
 
@@ -199,7 +198,7 @@ vir_bytes vfs_newsp;
 #endif /* USE_TRACE */
 
        /* Call kernel to exec with SP and PC set by VFS. */
-       r= sys_exec(rmp->mp_endpoint, (char *) vfs_newsp, rmp->mp_name, pc);
+       r = sys_exec(rmp->mp_endpoint, (char *) sp, rmp->mp_name, pc, ps_str);
        if (r != OK) panic("sys_exec failed: %d", r);
 }
 
index ace611bf40a52abb36d0c90c2f84006b6ae1df57..98103af26812b3f5bb6d2166f5576be0027a8396 100644 (file)
@@ -434,7 +434,7 @@ static void handle_vfs_reply()
 
   case PM_EXEC_REPLY:
        exec_restart(rmp, m_in.PM_STATUS, (vir_bytes)m_in.PM_PC,
-               (vir_bytes)m_in.PM_NEWSP);
+               (vir_bytes)m_in.PM_NEWSP, (vir_bytes)m_in.PM_NEWPS_STR);
 
        break;
 
index 0dc30709f069a070bb407cccc6354329f2f0e60f..6ee81edf6fde7f403c47e1b8298bce097d518aed 100644 (file)
@@ -20,7 +20,8 @@ int do_brk(void);
 int do_exec(void);
 int do_newexec(void);
 int do_execrestart(void);
-void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp);
+void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp,
+       vir_bytes ps_str);
 
 /* forkexit.c */
 int do_fork(void);
index 942b30fe22367b3ea59b4e8b53c6230b3d44ea26..9e28d5a9edd7ec5ef39b085dcb77d0404558d8f8 100644 (file)
@@ -1,14 +1,15 @@
 #include "inc.h"
 #include <assert.h>
+#include <sys/exec.h>
 #include <libexec.h>
+#include <minix/param.h>
 #include <machine/vmparam.h>
 
 static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
-       char *frame, int frame_len);
-static int exec_restart(int proc_e, int result, vir_bytes pc);
+       char *frame, int frame_len, vir_bytes ps_str);
+static int exec_restart(int proc_e, int result, vir_bytes pc, vir_bytes ps_str);
 static int read_seg(struct exec_info *execi, off_t off,
         vir_bytes seg_addr, size_t seg_bytes);
-static int exec_restart(int proc_e, int result, vir_bytes pc);
 
 /* Array of loaders for different object formats */
 static struct exec_loaders {
@@ -19,98 +20,51 @@ static struct exec_loaders {
 };
 
 int srv_execve(int proc_e, char *exec, size_t exec_len, char **argv,
-       char **UNUSED(Xenvp))
+       char **envp)
 {
-       char * const *ap;
-       char * const *ep;
+       size_t frame_size = 0;  /* Size of the new initial stack. */
+       int argc = 0;           /* Argument count. */
+       int envc = 0;           /* Environment count */
+       char overflow = 0;      /* No overflow yet. */
        char *frame;
-       char **vp;
-       char *sp, *progname;
-       size_t argc;
-       size_t frame_size;
-       size_t string_off;
-       size_t n;
-       int ov;
-       int r;
-
-       /* Assumptions: size_t and char *, it's all the same thing. */
-
-       /* Create a stack image that only needs to be patched up slightly
-        * by the kernel to be used for the process to be executed.
-        */
-
-       ov= 0;                  /* No overflow yet. */
-       frame_size= 0;          /* Size of the new initial stack. */
-       string_off= 0;          /* Offset to start of the strings. */
-       argc= 0;                /* Argument count. */
+       struct ps_strings *psp;
+       int vsp = 0;    /* (virtual) Stack pointer in new address space. */
 
-       for (ap= argv; *ap != NULL; ap++) {
-               n = sizeof(*ap) + strlen(*ap) + 1;
-               frame_size+= n;
-               if (frame_size < n) ov= 1;
-               string_off+= sizeof(*ap);
-               argc++;
-       }
-
-       /* Add an argument count and two terminating nulls. */
-       frame_size+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
-       string_off+= sizeof(argc) + sizeof(*ap) + sizeof(*ep);
+       char *progname;
+       int r;
 
-       /* Align. */
-       frame_size= (frame_size + sizeof(char *) - 1) & ~(sizeof(char *) - 1);
+       minix_stack_params(argv[0], argv, envp, &frame_size, &overflow,
+               &argc, &envc);
 
        /* The party is off if there is an overflow. */
-       if (ov || frame_size < 3 * sizeof(char *)) {
-               errno= E2BIG;
+       if (overflow) {
+               errno = E2BIG;
                return -1;
        }
 
        /* Allocate space for the stack frame. */
-       frame = (char *) malloc(frame_size);
-       if (!frame) {
+       if ((frame = (char *) sbrk(frame_size)) == (char *) -1) {
                errno = E2BIG;
                return -1;
        }
 
-       /* Set arg count, init pointers to vector and string tables. */
-       * (size_t *) frame = argc;
-       vp = (char **) (frame + sizeof(argc));
-       sp = frame + string_off;
-
-       /* Load the argument vector and strings. */
-       for (ap= argv; *ap != NULL; ap++) {
-               *vp++= (char *) (sp - frame);
-               n= strlen(*ap) + 1;
-               memcpy(sp, *ap, n);
-               sp+= n;
-       }
-       *vp++= NULL;
-
-#if 0
-       /* Load the environment vector and strings. */
-       for (ep= envp; *ep != NULL; ep++) {
-               *vp++= (char *) (sp - frame);
-               n= strlen(*ep) + 1;
-               memcpy(sp, *ep, n);
-               sp+= n;
-       }
-#endif
-       *vp++= NULL;
-
-       /* Padding. */
-       while (sp < frame + frame_size) *sp++= 0;
+       minix_stack_fill(argv[0], argc, argv, envc, envp, frame_size, frame,
+               &vsp, &psp);
 
        (progname=strrchr(argv[0], '/')) ? progname++ : (progname=argv[0]);
-       r = do_exec(proc_e, exec, exec_len, progname, frame, frame_size);
 
-       /* Return the memory used for the frame and exit. */
-       free(frame);
+       r = do_exec(proc_e, exec, exec_len, progname, frame, frame_size,
+               vsp + ((char *)psp - frame));
+
+       /* Failure, return the memory used for the frame and exit. */
+       (void) sbrk(-frame_size);
+
        return r;
 }
 
 
 static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
-       char *frame, int frame_len)
+       char *frame, int frame_len, vir_bytes ps_str)
 {
        int r;
        vir_bytes vsp;
@@ -153,35 +107,36 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
                return r;
 
        /* Patch up stack and copy it from RS to new core image. */
-       vsp = execi.stack_high;
-       vsp -= frame_len;
-       libexec_patch_ptr(frame, vsp);
+       vsp = execi.stack_high - frame_len;
        r = sys_datacopy(SELF, (vir_bytes) frame,
                proc_e, (vir_bytes) vsp, (phys_bytes)frame_len);
        if (r != OK) {
                printf("do_exec: copying out new stack failed: %d\n", r);
-               exec_restart(proc_e, r, execi.pc);
+               exec_restart(proc_e, r, execi.pc, ps_str);
                return r;
        }
 
-       return exec_restart(proc_e, OK, execi.pc);
+       return exec_restart(proc_e, OK, execi.pc, ps_str);
 }
 
 /*===========================================================================*
  *                             exec_restart                                 *
  *===========================================================================*/
-static int exec_restart(int proc_e, int result, vir_bytes pc)
+static int exec_restart(int proc_e, int result, vir_bytes pc, vir_bytes ps_str)
 {
        int r;
        message m;
 
-       m.m_type= EXEC_RESTART;
-       m.EXC_RS_PROC= proc_e;
-       m.EXC_RS_RESULT= result;
-       m.EXC_RS_PC= (void*)pc;
-       r= sendrec(PM_PROC_NR, &m);
+       m.m_type = EXEC_RESTART;
+       m.EXC_RS_PROC = proc_e;
+       m.EXC_RS_RESULT = result;
+       m.EXC_RS_PC = (void *)pc;
+       m.EXC_RS_PS_STR = (void *)ps_str;
+
+       r = sendrec(PM_PROC_NR, &m);
        if (r != OK)
                return r;
+
        return m.m_type;
 }
 
index 925c82ad7086758661eccf6b335080fa0e82136f..6f829ef1371604e6abe142a144e8d5cd29714cb5 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <dirent.h>
+#include <sys/exec.h>
 #include <sys/param.h>
 #include "fproc.h"
 #include "path.h"
@@ -56,13 +57,13 @@ struct vfs_exec_info {
 static void lock_exec(void);
 static void unlock_exec(void);
 static int patch_stack(struct vnode *vp, char stack[ARG_MAX],
-       size_t *stk_bytes, char path[PATH_MAX]);
+       size_t *stk_bytes, char path[PATH_MAX], vir_bytes *vsp);
 static int is_script(struct vfs_exec_info *execi);
 static int insert_arg(char stack[ARG_MAX], size_t *stk_bytes, char *arg,
-       int replace);
+       vir_bytes *vsp, char replace);
 static void clo_exec(struct fproc *rfp);
 static int stack_prepare_elf(struct vfs_exec_info *execi,
-       char *curstack, size_t *frame_len, vir_bytes *vsp, int *extrabase);
+       char *curstack, size_t *frame_len, vir_bytes *vsp);
 static int map_header(struct vfs_exec_info *execi);
 static int read_seg(struct exec_info *execi, off_t off, vir_bytes seg_addr, size_t seg_bytes);
 
@@ -71,7 +72,7 @@ static int read_seg(struct exec_info *execi, off_t off, vir_bytes seg_addr, size
 /* Array of loaders for different object file formats */
 typedef int (*exechook_t)(struct vfs_exec_info *execpackage);
 typedef int (*stackhook_t)(struct vfs_exec_info *execi, char *curstack,
-       size_t *frame_len, vir_bytes *, int *extrabase);
+       size_t *frame_len, vir_bytes *vsp);
 struct exec_loaders {
        libexec_exec_loadfunc_t load_object;     /* load executable into memory */
        stackhook_t setup_stack; /* prepare stack before argc and argv push */
@@ -214,16 +215,19 @@ static int vfs_memmap(struct exec_info *execi,
  *===========================================================================*/
 int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
                   vir_bytes frame, size_t frame_len, vir_bytes *pc,
-                  vir_bytes *newsp, int user_exec_flags)
+                  vir_bytes *newsp, vir_bytes *UNUSED(ps_str), int user_exec_flags)
+                  //vir_bytes *newsp, vir_bytes *ps_str, int user_exec_flags)
 {
 /* Perform the execve(name, argv, envp) call.  The user library builds a
  * complete stack image, including pointers, args, environ, etc.  The stack
  * is copied to a buffer inside VFS, and then to the new core image.
+ *
+ * ps_str is not currently used, but may be if the ps_strings structure has to
+ * be moved to another location.
  */
   int r, slot;
   vir_bytes vsp;
   struct fproc *rfp;
-  int extrabase = 0;
   static char mbuf[ARG_MAX];   /* buffer for stack and zeroes */
   struct vfs_exec_info execi;
   int i;
@@ -234,8 +238,6 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
   struct lookup resolve;
   struct fproc *vmfp = &fproc[VM_PROC_NR];
   stackhook_t makestack = NULL;
-  static int n;
-  n++;
   struct filp *newfilp = NULL;
 
   lock_exec();
@@ -271,6 +273,10 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
        FAILCHECK(r);
   }
 
+  /* Compute the current virtual stack pointer, has to be done before calling
+   * patch_stack, which needs it, and will adapt as required. */
+  vsp = execi.args.stack_high - frame_len;
+
   /* The default is to keep the original user and group IDs */
   execi.args.new_uid = rfp->fp_effuid;
   execi.args.new_gid = rfp->fp_effgid;
@@ -297,7 +303,8 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
         * name into fullpath.
         */
        FAILCHECK(fetch_name(path, path_len, fullpath));
-       FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath));
+       FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath, &vsp));
+
        strlcpy(finalexec, fullpath, PATH_MAX);
        strlcpy(firstexec, fullpath, PATH_MAX);
        Get_read_vp(execi, fullpath, 1, 0, &resolve, fp);
@@ -324,8 +331,10 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
 
        /* ld.so is linked at 0, but it can relocate itself; we
         * want it higher to trap NULL pointer dereferences. 
+        * Let's put it below the stack, and reserve 10MB for ld.so.
         */
-       execi.args.load_offset = 0x10000;
+       execi.args.load_offset =
+                execi.args.stack_high - execi.args.stack_size - 0xa00000;
 
        /* Remember it */
        strlcpy(execi.execname, finalexec, PATH_MAX);
@@ -389,11 +398,9 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
   *pc = execi.args.pc;
 
   /* call a stack-setup function if this executable type wants it */
-  vsp = execi.args.stack_high - frame_len;
-  if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase));
+  if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp));
 
-  /* Patch up stack and copy it from VFS to new core image. */
-  libexec_patch_ptr(mbuf, vsp + extrabase);
+  /* Copy the stack from VFS to new core image. */
   FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
                   (phys_bytes)frame_len));
 
@@ -433,102 +440,118 @@ pm_execfinal:
   return(r);
 }
 
-static int stack_prepare_elf(struct vfs_exec_info *execi, char *frame, size_t *framelen,
-       vir_bytes *newsp, int *extrabase)
+/* This is a copy-paste of the same macro in libc/sys-minix/stack_utils.c. Keep it
+ * synchronized. */
+#define STACK_MIN_SZ \
+( \
+       sizeof(int) + sizeof(void *) * 2 + \
+       sizeof(AuxInfo) * PMEF_AUXVECTORS + PMEF_EXECNAMELEN1 + \
+       sizeof(struct ps_strings) \
+)
+
+static int stack_prepare_elf(struct vfs_exec_info *execi, char *frame, size_t *frame_size,
+       vir_bytes *vsp)
 {
-       AuxInfo *a, *term;
-       Elf_Ehdr *elf_header;
-       int nulls;
-       char    **mysp = (char **) frame,
-               **mysp_end = (char **) ((char *)frame + *framelen);
+       AuxInfo *aux_vec, *aux_vec_end;
+       vir_bytes vap; /* Address in proc space of the first AuxVec. */
+       Elf_Ehdr const * const elf_header = (Elf_Ehdr *) execi->args.hdr;
+       struct ps_strings const * const psp = (struct ps_strings *)
+               (frame + (*frame_size - sizeof(struct ps_strings)));
 
-       if(!execi->is_dyn)
+       size_t const execname_len = strlen(execi->execname);
+
+       if (!execi->is_dyn)
                return OK;
 
-       assert(execi->args.hdr_len >= sizeof(*elf_header));
-       elf_header = (Elf_Ehdr *) execi->args.hdr;
+       if (execi->args.hdr_len < sizeof(*elf_header)) {
+               printf("VFS: malformed ELF headers for exec\n");
+               return ENOEXEC;
+       }
 
-       /* exec() promises stack space. Now find it. */
-       mysp++; /* skip argc */
+       if (*frame_size < STACK_MIN_SZ) {
+               printf("VFS: malformed stack for exec(), smaller than minimum"
+                       " possible size.\n");
+               return ENOEXEC;
+       }
 
-       /* find a terminating NULL entry twice: one for argv[], one for envp[]. */
-       for(nulls = 0; nulls < 2; nulls++) {
-               assert(mysp < mysp_end);
-               while(*mysp && mysp < mysp_end) mysp++; /* find terminating NULL */
-               if(mysp >= mysp_end) {
-                       printf("VFS: malformed stack for exec()\n");
-                       return ENOEXEC;
-               }
-               assert(!*mysp);
-               mysp++;
+       /* Find first Aux vector in the stack frame. */ 
+       vap = (vir_bytes)(psp->ps_envstr + (psp->ps_nenvstr + 1));
+       aux_vec = (AuxInfo *) (frame + (vap - *vsp));
+       aux_vec_end = aux_vec + PMEF_AUXVECTORS;
+
+       if (((char *)aux_vec < frame) || 
+               ((char *)aux_vec > (frame + *frame_size))) {
+               printf("VFS: malformed stack for exec(), first AuxVector is"
+                      " not on the stack.\n");
+               return ENOEXEC;
+       }
+
+       if (((char *)aux_vec_end < frame) ||
+               ((char *)aux_vec_end > (frame + *frame_size))) {
+               printf("VFS: malformed stack for exec(), last AuxVector is"
+                      " not on the stack.\n");
+               return ENOEXEC;
        }
 
        /* Userland provides a fully filled stack frame, with argc, argv, envp
-        * and then all the argv and envp strings; consistent with ELF ABI, except
-        * for a list of Aux vectors that should be between envp points and the
-        * start of the strings.
+        * and then all the argv and envp strings; consistent with ELF ABI,
+        * except for a list of Aux vectors that should be between envp points
+        * and the start of the strings.
         *
-        * It would take some very unpleasant hackery to insert the aux vectors before
-        * the strings, and correct all the pointers, so the exec code in libc makes
-        * space for us first and indicates the fact it did this with this flag.
+        * It would take some very unpleasant hackery to insert the aux vectors
+        * before the strings, and correct all the pointers, so the exec code
+        * in libc makes space for us.
         */
-       if(!(execi->userflags & PMEF_AUXVECTORSPACE)) {
-               char *f = (char *) mysp;
-               int remain;
-               vir_bytes extrabytes = sizeof(*a) * PMEF_AUXVECTORS;
-               
-               /* Create extrabytes more space */
-               remain = *framelen - (int)(f - frame);
-               if(*framelen + extrabytes >= ARG_MAX)
-                       return ENOMEM;
-               *framelen += extrabytes;
-               *newsp -= extrabytes;
-               *extrabase += extrabytes;
-               memmove(f+extrabytes, f, remain);
-               memset(f, 0, extrabytes);
-       }
 
-       /* Ok, what mysp points to now we can use for the aux vectors. */
-       a = (AuxInfo *) mysp;
-#define AUXINFO(type, value) \
-       { assert((char *) a < (char *) mysp_end); a->a_type = type; a->a_v = value; a++; }
-#if 0
-       AUXINFO(AT_PHENT, elf_header->e_phentsize);
-       AUXINFO(AT_PHNUM, elf_header->e_phnum);
-#endif
-       AUXINFO(AT_BASE, execi->args.load_base);
-       AUXINFO(AT_ENTRY, execi->args.pc);
-       AUXINFO(AT_PAGESZ, PAGE_SIZE);
-       AUXINFO(AT_EXECFD, execi->elf_main_fd);
+#define AUXINFO(a, type, value) \
+       do { \
+               if (a < aux_vec_end) { \
+                       a->a_type = type; \
+                       a->a_v = value; \
+                       a++; \
+               } else { \
+                       printf("VFS: No more room for ELF AuxVec type %d, skipping it for %s\n", type, execi->execname); \
+                       (aux_vec_end - 1)->a_type = AT_NULL; \
+                       (aux_vec_end - 1)->a_v = 0; \
+               } \
+       } while(0)
 
-       /* This is where we add the AT_NULL */
-       term = a;
+       AUXINFO(aux_vec, AT_BASE, execi->args.load_base);
+       AUXINFO(aux_vec, AT_ENTRY, execi->args.pc);
+       AUXINFO(aux_vec, AT_EXECFD, execi->elf_main_fd);
+#if 0
+       AUXINFO(aux_vec, AT_PHDR, XXX ); /* should be &phdr[0] */
+       AUXINFO(aux_vec, AT_PHENT, elf_header->e_phentsize);
+       AUXINFO(aux_vec, AT_PHNUM, elf_header->e_phnum);
 
-       /* Always terminate with AT_NULL */
-       AUXINFO(AT_NULL, 0);
+       AUXINFO(aux_vec, AT_RUID, XXX);
+       AUXINFO(aux_vec, AT_RGID, XXX);
+#endif
+       AUXINFO(aux_vec, AT_EUID, execi->args.new_uid);
+       AUXINFO(aux_vec, AT_EGID, execi->args.new_gid);
+       AUXINFO(aux_vec, AT_PAGESZ, PAGE_SIZE);
 
-       /* Empty space starts here, if any. */
-       if((execi->userflags & PMEF_EXECNAMESPACE1)
-          && strlen(execi->execname) < PMEF_EXECNAMELEN1) {
+       if(execname_len < PMEF_EXECNAMELEN1) {
                char *spacestart;
                vir_bytes userp;
 
-               /* Make space for the real closing AT_NULL entry. */
-               AUXINFO(AT_NULL, 0);
-
-               /* Empty space starts here; we can put the name here. */
-               spacestart = (char *) a;
-               strlcpy(spacestart, execi->execname, PATH_MAX);
+               /* Empty space starts after aux_vec table; we can put the name
+                * here. */
+               spacestart = (char *) aux_vec + 2 * sizeof(AuxInfo);
+               strlcpy(spacestart, execi->execname, PMEF_EXECNAMELEN1);
+               memset(spacestart + execname_len, '\0',
+                       PMEF_EXECNAMELEN1 - execname_len);
 
                /* What will the address of the string for the user be */
-               userp = *newsp + (spacestart-frame);
+               userp = *vsp + (spacestart - frame);
 
                /* Move back to where the AT_NULL is */
-               a = term;
-               AUXINFO(AT_SUN_EXECNAME, userp);
-               AUXINFO(AT_NULL, 0);
+               AUXINFO(aux_vec, AT_SUN_EXECNAME, userp);
        }
 
+       /* Always terminate with AT_NULL */
+       AUXINFO(aux_vec, AT_NULL, 0);
+
        return OK;
 }
 
@@ -547,11 +570,12 @@ static int is_script(struct vfs_exec_info *execi)
 /*===========================================================================*
  *                             patch_stack                                  *
  *===========================================================================*/
-static int patch_stack(vp, stack, stk_bytes, path)
+static int patch_stack(vp, stack, stk_bytes, path, vsp)
 struct vnode *vp;              /* pointer for open script file */
 char stack[ARG_MAX];           /* pointer to stack image within VFS */
 size_t *stk_bytes;             /* size of initial stack */
 char path[PATH_MAX];           /* path to script file */
+vir_bytes *vsp;
 {
 /* Patch the argument vector to include the path name of the script to be
  * interpreted, and all strings on the #! line.  Returns the path name of
@@ -565,13 +589,14 @@ char path[PATH_MAX];              /* path to script file */
   char buf[_MAX_BLOCK_SIZE];
 
   /* Make 'path' the new argv[0]. */
-  if (!insert_arg(stack, stk_bytes, path, REPLACE)) return(ENOMEM);
+  if (!insert_arg(stack, stk_bytes, path, vsp, REPLACE)) return(ENOMEM);
 
   pos = 0;     /* Read from the start of the file */
 
   /* Issue request */
   r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, pos, READING, VFS_PROC_NR,
                        (vir_bytes) buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io);
+
   if (r != OK) return(r);
 
   n = vp->v_size;
@@ -600,7 +625,7 @@ char path[PATH_MAX];                /* path to script file */
        while (sp > path && sp[-1] != ' ' && sp[-1] != '\t') --sp;
 
        interp = sp;
-       if (!insert_arg(stack, stk_bytes, sp, INSERT)) {
+       if (!insert_arg(stack, stk_bytes, sp, vsp, INSERT)) {
                printf("VFS: patch_stack: insert_arg failed\n");
                return(ENOMEM);
        }
@@ -609,71 +634,91 @@ char path[PATH_MAX];              /* path to script file */
   if(!interp)
        return ENOEXEC;
 
-  /* Round *stk_bytes up to the size of a pointer for alignment contraints. */
-  *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE;
-
   if (interp != path)
        memmove(path, interp, strlen(interp)+1);
+
   return(OK);
 }
 
 /*===========================================================================*
  *                             insert_arg                                   *
  *===========================================================================*/
-static int insert_arg(
-char stack[ARG_MAX],           /* pointer to stack image within PM */
-size_t *stk_bytes,             /* size of initial stack */
-char *arg,                     /* argument to prepend/replace as new argv[0] */
-int replace
-)
+static int insert_arg(char stack[ARG_MAX], size_t *stk_bytes, char *arg,
+       vir_bytes *vsp, char replace)
 {
-/* Patch the stack so that arg will become argv[0].  Be careful, the stack may
- * be filled with garbage, although it normally looks like this:
- *     nargs argv[0] ... argv[nargs-1] NULL envp[0] ... NULL
- * followed by the strings "pointed" to by the argv[i] and the envp[i].  The
- * pointers are really offsets from the start of stack.
- * Return true iff the operation succeeded.
- */
-  int offset;
-  vir_bytes a0, a1;
-  size_t old_bytes = *stk_bytes;
-
-  /* Prepending arg adds at least one string and a zero byte. */
-  offset = strlen(arg) + 1;
-
-  a0 = (int) ((char **) stack)[1];     /* argv[0] */
-  if (a0 < 4 * PTRSIZE || a0 >= old_bytes) return(FALSE);
-
-  a1 = a0;                     /* a1 will point to the strings to be moved */
-  if (replace) {
-       /* Move a1 to the end of argv[0][] (argv[1] if nargs > 1). */
-       do {
-               if (a1 == old_bytes) return(FALSE);
-               --offset;
-       } while (stack[a1++] != 0);
-  } else {
-       offset += PTRSIZE;      /* new argv[0] needs new pointer in argv[] */
-       a0 += PTRSIZE;          /* location of new argv[0][]. */
-  }
+       /* Patch the stack so that arg will become argv[0]. Be careful, the
+        * stack may be filled with garbage, although it normally looks like
+        * this:
+        *      nargs argv[0] ... argv[nargs-1] NULL envp[0] ... NULL
+        * followed by the strings "pointed" to by the argv[i] and the envp[i].
+        * The * pointers are in the new process address space.
+        *
+        * Return true iff the operation succeeded.
+        */
+       struct ps_strings *psp;
+       int offset;
+       size_t old_bytes = *stk_bytes;
+
+       int const arg_len = strlen(arg) + 1;
+
+       /* Offset to argv[0][0] in the stack frame. */
+       int const a0 = (int)(((char **)stack)[1] - *vsp);
 
-  /* stack will grow by offset bytes (or shrink by -offset bytes) */
-  if ((*stk_bytes += offset) > ARG_MAX) return(FALSE);
+       /* Check that argv[0] points within the stack frame. */
+       if ((a0 < 0) || (a0 >= old_bytes)) {
+               printf("vfs:: argv[0][] not within stack range!! %i\n", a0);
+               return FALSE;
+       }
 
-  /* Reposition the strings by offset bytes */
-  memmove(stack + a1 + offset, stack + a1, old_bytes - a1);
+       if (!replace) {
+               /* Prepending arg adds one pointer, one string and a zero byte. */
+               offset = arg_len + PTRSIZE;
+       } else {
+               /* replacing argv[0] with arg adds the difference in length of
+                * the two strings. Make sure we don't go beyond the stack size
+                * when computing the length of the current argv[0]. */
+               offset = arg_len - strnlen(stack + a0, ARG_MAX - a0 - 1);
+       }
 
-  strlcpy(stack + a0, arg, PATH_MAX); /* Put arg in the new space. */
+       /* As ps_strings follows the strings, ensure the offset is word aligned. */
+       offset = offset + (PTRSIZE - ((PTRSIZE + offset) % PTRSIZE));
 
-  if (!replace) {
-       /* Make space for a new argv[0]. */
-       memmove(stack + 2 * PTRSIZE, stack + 1 * PTRSIZE, a0 - 2 * PTRSIZE);
+       /* The stack will grow (or shrink) by offset bytes. */
+       if ((*stk_bytes += offset) > ARG_MAX) {
+               printf("vfs:: offset too big!! %d (max %d)\n", *stk_bytes,
+                       ARG_MAX);
+               return FALSE;
+       }
 
-       ((char **) stack)[0]++; /* nargs++; */
-  }
-  /* Now patch up argv[] and envp[] by offset. */
-  libexec_patch_ptr(stack, (vir_bytes) offset);
-  ((char **) stack)[1] = (char *) a0;  /* set argv[0] correctly */
-  return(TRUE);
+       /* Reposition the strings by offset bytes */
+       memmove(stack + a0 + offset, stack + a0, old_bytes - a0);
+
+       /* Put arg in the new space, leaving padding in front of it. */
+       strlcpy(stack + a0 + offset - arg_len, arg, arg_len);
+
+       if (!replace) {
+               /* Make space for a new argv[0]. */
+               memmove(stack + 2 * PTRSIZE,
+                       stack + 1 * PTRSIZE, a0 - 2 * PTRSIZE);
+
+               ((char **) stack)[0]++; /* nargs++; */
+       }
+
+       /* set argv[0] correctly */
+       ((char **) stack)[1] = (char *) a0 - arg_len + *vsp;
+
+       /* Update stack pointer in the process address space. */
+       *vsp -= offset;
+
+       /* Update argv and envp in ps_strings */
+       psp = (struct ps_strings *) (stack + *stk_bytes - sizeof(struct ps_strings));
+       psp->ps_argvstr -= (offset / PTRSIZE);
+       if (!replace) {
+               psp->ps_nargvstr++;
+       }
+       psp->ps_envstr = psp->ps_argvstr + psp->ps_nargvstr + 1;
+
+       return TRUE;
 }
 
 /*===========================================================================*
index 8a9ab6e8165bd084c0f117fd834d6126790b1249..386afa1313958b5e1cdad09378f5288710eec5c1 100644 (file)
@@ -845,24 +845,27 @@ static void service_pm_postponed(void)
     case PM_EXEC:
        {
                endpoint_t proc_e;
-               vir_bytes exec_path, stack_frame;
+               vir_bytes exec_path, stack_frame, ps_str;
                size_t exec_path_len, stack_frame_len;
 
                proc_e = job_m_in.PM_PROC;
-               exec_path = (vir_bytes) job_m_in.PM_PATH;
-               exec_path_len = (size_t) job_m_in.PM_PATH_LEN;
-               stack_frame = (vir_bytes) job_m_in.PM_FRAME;
-               stack_frame_len = (size_t) job_m_in.PM_FRAME_LEN;
+               exec_path = (vir_bytes)job_m_in.PM_PATH;
+               exec_path_len = (size_t)job_m_in.PM_PATH_LEN;
+               stack_frame = (vir_bytes)job_m_in.PM_FRAME;
+               stack_frame_len = (size_t)job_m_in.PM_FRAME_LEN;
+               ps_str = (vir_bytes)job_m_in.PM_PS_STR;
 
                r = pm_exec(proc_e, exec_path, exec_path_len, stack_frame,
-                           stack_frame_len, &pc, &newsp, job_m_in.PM_EXECFLAGS);
+                           stack_frame_len, &pc, &newsp, &ps_str,
+                           job_m_in.PM_EXECFLAGS);
 
                /* Reply status to PM */
                m_out.m_type = PM_EXEC_REPLY;
                m_out.PM_PROC = proc_e;
-               m_out.PM_PC = (void*) pc;
+               m_out.PM_PC = (void *)pc;
                m_out.PM_STATUS = r;
-               m_out.PM_NEWSP = (void *) newsp;
+               m_out.PM_NEWSP = (void *)newsp;
+               m_out.PM_NEWPS_STR = ps_str;
        }
        break;
 
index 0dfc90dbd988dbb1bfe32499f52b6456f61ea487..919867c20c21cf2a521f0057bd1674cc53e7e70b 100644 (file)
@@ -78,7 +78,8 @@ void write_elf_core_file(struct filp *f, int csig, char *exe_name);
 
 /* exec.c */
 int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, vir_bytes frame,
-       size_t frame_len, vir_bytes *pc, vir_bytes *newsp, int flags);
+       size_t frame_len, vir_bytes *pc, vir_bytes *newsp, vir_bytes *ps_str,
+       int flags);
 
 /* filedes.c */
 void *do_filp_gc(void *arg);
index 1cef6c7adb7468b24388a4717f8288b6d0f5a111..c882cf068ee9e18dcaeb7919e7af3d6eb27bb58c 100644 (file)
@@ -17,6 +17,8 @@
 #include <minix/bitmap.h>
 #include <minix/rs.h>
 
+#include <sys/exec.h>
+
 #include <libexec.h>
 #include <ctype.h>
 #include <errno.h>
@@ -41,6 +43,7 @@ extern int missing_spares;
 #include "kernel/proc.h"
 
 #include <signal.h>
+#include <lib.h>
 
 /* Table of calls and a macro to test for being in range. */
 struct {
@@ -214,13 +217,13 @@ struct vm_exec_info {
 };
 
 static int libexec_copy_physcopy(struct exec_info *execi,
-        off_t off, vir_bytes vaddr, size_t len)
+       off_t off, vir_bytes vaddr, size_t len)
 {
        vir_bytes end;
        struct vm_exec_info *ei = execi->opaque;
        end = ei->ip->start_addr + ei->ip->len;
-        assert(ei->ip->start_addr + off + len <= end);
-        return sys_physcopy(NONE, ei->ip->start_addr + off,
+       assert(ei->ip->start_addr + off + len <= end);
+       return sys_physcopy(NONE, ei->ip->start_addr + off,
                execi->proc_e, vaddr, len);
 }
 
@@ -256,6 +259,18 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
        struct exec_info *execi = &vmexeci.execi;
        char hdr[VM_PAGE_SIZE];
 
+       size_t frame_size = 0;  /* Size of the new initial stack. */
+       int argc = 0;           /* Argument count. */
+       int envc = 0;           /* Environment count */
+       char overflow = 0;      /* No overflow yet. */
+       struct ps_strings *psp;
+
+       int vsp = 0;    /* (virtual) Stack pointer in new address space. */
+       char *argv[] = { ip->proc_name, NULL };
+       char *envp[] = { NULL };
+       char *path = ip->proc_name;
+       char frame[VM_PAGE_SIZE];
+
        memset(&vmexeci, 0, sizeof(vmexeci));
 
        if(pt_new(&vmp->vm_pt) != OK)
@@ -268,34 +283,55 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
                (vir_bytes) hdr, sizeof(hdr)) != OK)
                panic("can't look at boot proc header");
 
-        execi->stack_high = kernel_boot_info.user_sp;
-        execi->stack_size = DEFAULT_STACK_LIMIT;
-        execi->proc_e = vmp->vm_endpoint;
-        execi->hdr = hdr;
-        execi->hdr_len = sizeof(hdr);
-        strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname));
-        execi->frame_len = 0;
+       execi->stack_high = kernel_boot_info.user_sp;
+       execi->stack_size = DEFAULT_STACK_LIMIT;
+       execi->proc_e = vmp->vm_endpoint;
+       execi->hdr = hdr;
+       execi->hdr_len = sizeof(hdr);
+       strlcpy(execi->progname, ip->proc_name, sizeof(execi->progname));
+       execi->frame_len = 0;
        execi->opaque = &vmexeci;
        execi->filesize = ip->len;
 
        vmexeci.ip = ip;
        vmexeci.vmp = vmp;
 
-        /* callback functions and data */
-        execi->copymem = libexec_copy_physcopy;
-        execi->clearproc = NULL;
-        execi->clearmem = libexec_clear_sys_memset;
+       /* callback functions and data */
+       execi->copymem = libexec_copy_physcopy;
+       execi->clearproc = NULL;
+       execi->clearmem = libexec_clear_sys_memset;
        execi->allocmem_prealloc_junk = libexec_alloc_vm_prealloc;
        execi->allocmem_prealloc_cleared = libexec_alloc_vm_prealloc;
-        execi->allocmem_ondemand = libexec_alloc_vm_ondemand;
+       execi->allocmem_ondemand = libexec_alloc_vm_ondemand;
 
-       if(libexec_load_elf(execi) != OK)
+       if (libexec_load_elf(execi) != OK)
                panic("vm: boot process load of process %s (ep=%d) failed\n", 
-                       execi->progname,vmp->vm_endpoint);
+                       execi->progname, vmp->vm_endpoint);
+
+       /* Setup a minimal stack. */
+       minix_stack_params(path, argv, envp, &frame_size, &overflow, &argc,
+               &envc);
 
-        if(sys_exec(vmp->vm_endpoint, (char *) execi->stack_high - 12,
-               (char *) ip->proc_name, execi->pc) != OK)
-               panic("vm: boot process exec of process %s (ep=%d) failed\n", 
+       /* The party is off if there is an overflow, or it is too big for our
+        * pre-allocated space. */
+       if(overflow || frame_size > sizeof(frame))
+               panic("vm: could not alloc stack for boot process %s (ep=%d)\n",
+                       execi->progname, vmp->vm_endpoint);
+
+       minix_stack_fill(path, argc, argv, envc, envp, frame_size, frame, &vsp,
+               &psp);
+
+       if(handle_memory(vmp, vsp, frame_size, 1, NULL, NULL, 0) != OK)
+               panic("vm: could not map stack for boot process %s (ep=%d)\n",
+                       execi->progname, vmp->vm_endpoint);
+
+       if(sys_datacopy(SELF, (vir_bytes)frame, vmp->vm_endpoint, vsp, frame_size) != OK)
+               panic("vm: could not copy stack for boot process %s (ep=%d)\n",
+                       execi->progname, vmp->vm_endpoint);
+
+       if(sys_exec(vmp->vm_endpoint, (char *)vsp, execi->progname, execi->pc,
+               vsp + ((int)psp - (int)frame)) != OK)
+               panic("vm: boot process exec of process %s (ep=%d) failed\n",
                        execi->progname,vmp->vm_endpoint);
 
        /* make it runnable */
@@ -352,6 +388,11 @@ void init_vm(void)
        init_proc(VM_PROC_NR);
        pt_init();
 
+       /* Acquire kernel ipc vectors that weren't available
+        * before VM had determined kernel mappings
+        */
+       __minix_init();
+
        /* The kernel's freelist does not include boot-time modules; let
         * the allocator know that the total memory is bigger.
         */
@@ -450,15 +491,10 @@ void init_vm(void)
 
        /* Initialize the structures for queryexit */
        init_query_exit();
-
-       /* Acquire kernel ipc vectors that weren't available
-        * before VM had determined kernel mappings
-        */
-       __minix_init();
 }
 
 /*===========================================================================*
- *                         sef_cb_signal_handler                            *
+ *                         sef_cb_signal_handler                             *
  *===========================================================================*/
 static void sef_cb_signal_handler(int signo)
 {
@@ -482,7 +518,7 @@ static void sef_cb_signal_handler(int signo)
 }
 
 /*===========================================================================*
- *                            map_service                                   *
+ *                             map_service                                   *
  *===========================================================================*/
 static int map_service(struct rprocpub *rpub)
 {
index 4bfbb587092fd479bc95ac63b9661e44081a169b..71e1501c6804c9aa9b6343301529243c7231b6b9 100644 (file)
@@ -61,12 +61,6 @@ MINIX_TESTS+= \
    62
 .endif #  ${MACHINE_ARCH} == "i386"
 
-.if ${MACHINE_ARCH} == "earm"
-# LSC Not yet supported on ARM
-MKPIC:=                no
-LDSTATIC:=     -static
-.endif
-
 .for t in ${MINIX_TESTS}
 PROGS+= test${t}
 .endfor