]> Zhao Yanbai Git Server - minix.git/commitdiff
exec() cleanup, generalization, improvement
authorBen Gras <ben@minix3.org>
Wed, 30 May 2012 17:34:07 +0000 (19:34 +0200)
committerBen Gras <ben@minix3.org>
Thu, 7 Jun 2012 13:15:01 +0000 (15:15 +0200)
. make exec() callers (i.e. vfs and rs) determine the
  memory layout by explicitly reserving regions using
  mmap() calls on behalf of the exec()ing process,
  i.e. handling all of the exec logic, thereby eliminating
  all special exec() knowledge from VM.
. the new procedure is: clear the exec()ing process
  first, then call third-party mmap()s to reserve memory, then
  copy the executable file section contents in, all using callbacks
  tailored to the caller's way of starting an executable
. i.e. no more explicit EXEC_NEWMEM-style calls in PM or VM
  as with rigid 2-section arguments
. this naturally allows generalizing exec() by simply loading
  all ELF sections
. drop/merge of lots of duplicate exec() code into libexec
. not copying the code sections to vfs and into the executable
  again is a measurable performance improvement (about 3.3% faster
  for 'make' in src/servers/)

29 files changed:
include/arch/i386/include/vmparam.h
include/minix/callnr.h
include/minix/sys_config.h
include/minix/type.h
include/minix/vm.h
kernel/arch/i386/pre_init.c
lib/libexec/Makefile
lib/libexec/exec_elf.c
lib/libexec/exec_general.c [new file with mode: 0644]
lib/libexec/libexec.h
lib/libminc/Makefile
lib/libsys/Makefile
lib/libsys/vm_exec_newmem.c [deleted file]
lib/libsys/vm_procctl.c
servers/pm/exec.c
servers/pm/param.h
servers/pm/proto.h
servers/pm/table.c
servers/rs/exec.c
servers/rs/exec.h [deleted file]
servers/vfs/exec.c
servers/vfs/exec.h [deleted file]
servers/vm/arch/i386/memory.h
servers/vm/exec.c
servers/vm/exit.c
servers/vm/main.c
servers/vm/mmap.c
servers/vm/proto.h
servers/vm/signal.c

index 63aef5c2c0e0c7dc818b3b0d62184b5329908cb6..a8e217d49fcda850b58c282de6dc53a863ebd690 100644 (file)
@@ -49,4 +49,9 @@
 #define        PAGE_SIZE       (1 << PAGE_SHIFT)
 #define        PAGE_MASK       (PAGE_SIZE - 1)
 
+/* As visible from the user space process, where is the top of the
+ * stack (first non-stack byte), when in paged mode?
+ */
+#define VM_STACKTOP     0x80000000
+
 #endif /* _I386_VMPARAM_H_ */
index 519ca41540e5945c0dca6af20a90afbae7e88050..6f145cf886113ff39479d530433ed1ddacdeee0d 100644 (file)
@@ -97,9 +97,7 @@
 #define CPROF             99    /* to PM */
 
 /* Calls provided by PM and FS that are not part of the API */
-#define EXEC_NEWMEM    100     /* from VFS or RS to PM: new memory map for
-                                * exec
-                                */
+#define PM_NEWEXEC     100     /* from VFS or RS to PM: new exec */
 #define SRV_FORK       101     /* to PM: special fork call for RS */
 #define EXEC_RESTART   102     /* to PM: final part of exec for RS */
 #define GETPROCNR      104     /* to PM */
index 37083a5496bd4abb54702d143ac4367b3ba961ee..168923cab56fcfc814836a68d030db6cc6ea9e99 100644 (file)
@@ -54,4 +54,7 @@ error "_MINIX_MACHINE has incorrect value (0)"
 
 #define _KMESS_BUF_SIZE  10000
 
+/* Default stack size (limit) */
+#define DEFAULT_STACK_LIMIT (64 * 1024 * 1024)
+
 #endif /* _MINIX_SYS_CONFIG_H */
index bb038f27ce6e6b46fbddff3ad8c8ca884724f2dd..3ed23852e219f7b380c8e14c6a5084a22f99d7c8 100644 (file)
@@ -166,26 +166,6 @@ struct mem_range
        phys_bytes mr_limit;    /* Highest memory address in range */
 };
 
-/* For EXEC_NEWMEM */
-struct exec_newmem
-{
-       vir_bytes text_addr;    /* Starting address of text section */
-       vir_bytes text_bytes;   /* Length of text section (in bytes) */
-       vir_bytes data_addr;    /* Starting address of data section */
-       vir_bytes data_bytes;   /* Length of data section (in bytes) */
-       vir_bytes tot_bytes;    /* Minimum stack region size (in bytes) */
-       vir_bytes args_bytes;   /* Arguments/environ size on stack (in bytes) */
-       int sep_id;             /* Separate I&D?  */
-       int is_elf;             /* Is ELF exe? */
-       dev_t st_dev;           /* Device holding executable file */
-       ino_t st_ino;           /* Inode of executable file */
-       time_t enst_ctime;      /* Last changed time of executable file */
-       uid_t new_uid;          /* Process UID after exec */
-       gid_t new_gid;          /* Process GID after exec */
-       int setugid;            /* Process is setuid or setgid */
-       char progname[16];      /* Should be at least PROC_NAME_LEN */
-};
-
 /* Memory chunks. */
 struct memory {
        phys_bytes      base;
index 3d46c53648ca3bab8552ec85d7b0299b52c02889..4f0978c1b0d6c0058ed8ce34ebab45e12492a2a5 100644 (file)
@@ -9,8 +9,6 @@
 int vm_exit(endpoint_t ep);
 int vm_fork(endpoint_t ep, int slotno, endpoint_t *child_ep);
 int vm_brk(endpoint_t ep, char *newaddr);
-int vm_exec_newmem(endpoint_t ep, struct exec_newmem *args, int
-       args_bytes, char **ret_stack_top, int *ret_flags);
 int vm_push_sig(endpoint_t ep, vir_bytes *old_sp);
 int vm_willexit(endpoint_t ep);
 int vm_adddma(endpoint_t proc_e, phys_bytes start, phys_bytes size);
index 65fb69826c72bf99a4e3fe5fdfba399af159d3cd..0a294669ff7e96cf62f7f06bdcdf204d9c70345f 100644 (file)
@@ -368,7 +368,7 @@ static void mb_extract_image(multiboot_info_t mbi)
        off_t text_offset, data_offset;
 
        /* Save memory map for kernel tasks */
-       r = read_header_elf((const char *)MULTIBOOT_KERNEL_ADDR,
+       r = read_header_elf((char *) MULTIBOOT_KERNEL_ADDR,
                                4096, /* everything is there */
                            &text_vaddr, &text_paddr,
                            &text_filebytes, &text_membytes,
@@ -401,7 +401,7 @@ static void mb_extract_image(multiboot_info_t mbi)
 
        /* Load boot image services into memory and save memory map */
        for (i = 0; module < &mb_module_info[mods_count]; ++module, ++i) {
-           r = read_header_elf((const char *)module->mod_start,
+           r = read_header_elf((char *) module->mod_start,
                                module->mod_end - module->mod_start + 1,
                                &text_vaddr, &text_paddr,
                                &text_filebytes, &text_membytes,
index d1f7b1d3490d7dc6a2e42c3b09e2450822b36195..e02e248f869936c5492be5afff60c1f922b8a7d4 100644 (file)
@@ -2,7 +2,7 @@
 
 LIB=   exec
 INCS=  libexec.h
-SRCS=  exec_aout.c exec_elf.c
+SRCS=  exec_aout.c exec_elf.c exec_general.c
 
 .if (${NBSD_LIBC} != "no")
 INCSDIR= /usr/include
index 1f332685f30c0ab28cc62931a6d03f3b0dccba34..9bd3073ebd1b8f3cb15a218e7299cdd2d49497d2 100644 (file)
@@ -2,13 +2,18 @@
 
 #include <minix/type.h>
 #include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
 #include <sys/param.h>
+#include <sys/mman.h>
 #include <assert.h>
 #include <unistd.h>
 #include <errno.h>
 #include <libexec.h>
 #include <string.h>
 #include <machine/elf.h>
+#include <machine/vmparam.h>
+#include <machine/memory.h>
 
 /* For verbose logging */
 #define ELF_DEBUG 0
@@ -18,9 +23,9 @@
 
 #define SECTOR_SIZE 512
 
-static int check_header(const Elf_Ehdr *hdr);
+static int check_header(Elf_Ehdr *hdr);
 
-static int elf_sane(const Elf_Ehdr *hdr)
+static int elf_sane(Elf_Ehdr *hdr)
 {
   if (check_header(hdr) != OK) {
      return 0;
@@ -41,7 +46,7 @@ static int elf_sane(const Elf_Ehdr *hdr)
   return 1;
 }
 
-static int elf_ph_sane(const Elf_Phdr *phdr)
+static int elf_ph_sane(Elf_Phdr *phdr)
 {
   if (rounddown((uintptr_t)phdr, sizeof(Elf_Addr)) != (uintptr_t)phdr) {
      return 0;
@@ -49,17 +54,17 @@ static int elf_ph_sane(const Elf_Phdr *phdr)
   return 1;
 }
 
-static int elf_unpack(const char *exec_hdr,
-       int hdr_len, const Elf_Ehdr **hdr, const Elf_Phdr **phdr)
+static int elf_unpack(char *exec_hdr,
+       int hdr_len, Elf_Ehdr **hdr, Elf_Phdr **phdr)
 {
-  *hdr = (const Elf_Ehdr *)exec_hdr;
+  *hdr = (Elf_Ehdr *) exec_hdr;
   if(!elf_sane(*hdr)) {
 #if ELF_DEBUG
        printf("elf_sane failed\n");
 #endif
        return ENOEXEC;
   }
-  *phdr = (const Elf_Phdr *)(exec_hdr + (*hdr)->e_phoff);
+  *phdr = (Elf_Phdr *)(exec_hdr + (*hdr)->e_phoff);
   if(!elf_ph_sane(*phdr)) {
 #if ELF_DEBUG
        printf("elf_ph_sane failed\n");
@@ -73,23 +78,23 @@ static int elf_unpack(const char *exec_hdr,
 }
 
 int read_header_elf(
-  const char *exec_hdr,                /* executable header */
-  int hdr_len,                 /* significant bytes in exec_hdr */
-  vir_bytes *text_vaddr,       /* text virtual address */
-  phys_bytes *text_paddr,      /* text physical address */
-  vir_bytes *text_filebytes,   /* text segment size (in the file) */
-  vir_bytes *text_membytes,    /* text segment size (in memory) */
-  vir_bytes *data_vaddr,       /* data virtual address */
-  phys_bytes *data_paddr,      /* data physical address */
-  vir_bytes *data_filebytes,   /* data segment size (in the file) */
-  vir_bytes *data_membytes,    /* data segment size (in memory) */
-  vir_bytes *pc,               /* program entry point (initial PC) */
-  off_t *text_offset,          /* file offset to text segment */
-  off_t *data_offset           /* file offset to data segment */
+  char *exec_hdr,                /* executable header */
+  int hdr_len,                 /* significant bytes in exec_hdr */
+  vir_bytes *text_vaddr,       /* text virtual address */
+  phys_bytes *text_paddr,      /* text physical address */
+  vir_bytes *text_filebytes,   /* text segment size (in the file) */
+  vir_bytes *text_membytes,    /* text segment size (in memory) */
+  vir_bytes *data_vaddr,       /* data virtual address */
+  phys_bytes *data_paddr,      /* data physical address */
+  vir_bytes *data_filebytes,   /* data segment size (in the file) */
+  vir_bytes *data_membytes,    /* data segment size (in memory) */
+  vir_bytes *pc,               /* program entry point (initial PC) */
+  off_t *text_offset,          /* file offset to text segment */
+  off_t *data_offset           /* file offset to data segment */
 )
 {
-  const Elf_Ehdr *hdr = NULL;
-  const Elf_Phdr *phdr = NULL;
+  Elf_Ehdr *hdr = NULL;
+  Elf_Phdr *phdr = NULL;
   unsigned long seg_filebytes, seg_membytes;
   int e, i = 0;
 
@@ -101,9 +106,9 @@ int read_header_elf(
 
   if((e=elf_unpack(exec_hdr, hdr_len, &hdr, &phdr)) != OK) {
 #if ELF_DEBUG
-       printf("elf_unpack failed\n");
+       printf("elf_unpack failed\n");
 #endif
-       return e;
+       return e;
    }
 
 #if ELF_DEBUG
@@ -120,30 +125,30 @@ int read_header_elf(
   for (i = 0; i < hdr->e_phnum; i++) {
       switch (phdr[i].p_type) {
       case PT_LOAD:
-         if (phdr[i].p_memsz == 0)
-             break;
-         seg_filebytes = phdr[i].p_filesz;
-         seg_membytes = round_page(phdr[i].p_memsz + phdr[i].p_vaddr -
-                                   trunc_page(phdr[i].p_vaddr));
-
-         if (hdr->e_entry >= phdr[i].p_vaddr &&
-             hdr->e_entry < (phdr[i].p_vaddr + phdr[i].p_memsz)) {
-             *text_vaddr = phdr[i].p_vaddr;
-             *text_paddr = phdr[i].p_paddr;
-             *text_filebytes = seg_filebytes;
-             *text_membytes = seg_membytes;
-             *pc = (vir_bytes)hdr->e_entry;
-             *text_offset = phdr[i].p_offset;
-         } else {
-             *data_vaddr = phdr[i].p_vaddr;
-             *data_paddr = phdr[i].p_paddr;
-             *data_filebytes = seg_filebytes;
-             *data_membytes = seg_membytes;
-             *data_offset = phdr[i].p_offset;
-         }
-         break;
+         if (phdr[i].p_memsz == 0)
+             break;
+         seg_filebytes = phdr[i].p_filesz;
+         seg_membytes = round_page(phdr[i].p_memsz + phdr[i].p_vaddr -
+                                   trunc_page(phdr[i].p_vaddr));
+
+         if (hdr->e_entry >= phdr[i].p_vaddr &&
+             hdr->e_entry < (phdr[i].p_vaddr + phdr[i].p_memsz)) {
+             *text_vaddr = phdr[i].p_vaddr;
+             *text_paddr = phdr[i].p_paddr;
+             *text_filebytes = seg_filebytes;
+             *text_membytes = seg_membytes;
+             *pc = (vir_bytes)hdr->e_entry;
+             *text_offset = phdr[i].p_offset;
+         } else {
+             *data_vaddr = phdr[i].p_vaddr;
+             *data_paddr = phdr[i].p_paddr;
+             *data_filebytes = seg_filebytes;
+             *data_membytes = seg_membytes;
+             *data_offset = phdr[i].p_offset;
+         }
+         break;
       default:
-         break;
+         break;
       }
   }
 
@@ -169,7 +174,7 @@ int read_header_elf(
                         (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
                         (ehdr).e_ident[EI_MAG3] == ELFMAG3)
 
-static int check_header(const Elf_Ehdr *hdr)
+static int check_header(Elf_Ehdr *hdr)
 {
   if (!IS_ELF(*hdr) ||
       hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
@@ -181,46 +186,16 @@ static int check_header(const Elf_Ehdr *hdr)
   return OK;
 }
 
-int elf_phdr(const char *exec_hdr, int hdr_len, vir_bytes *ret_phdr)
-{
-  const Elf_Ehdr *hdr = NULL;
-  const Elf_Phdr *phdr = NULL;
-  int e, i, have_computed_phdr = 1;
-
-  if((e=elf_unpack(exec_hdr, hdr_len, &hdr, &phdr)) != OK) return e;
-
-  for (i = 0; i < hdr->e_phnum; i++) {
-      switch (phdr[i].p_type) {
-      case PT_LOAD:
-               /* compute phdr based on this heuristic, to be used
-                * if there is no PT_PHDR
-                */
-               if(phdr[i].p_offset == 0) {
-                       *ret_phdr = phdr[i].p_vaddr + hdr->e_phoff;
-                       have_computed_phdr = 1;
-               }
-               break;
-      case PT_PHDR:
-         *ret_phdr = phdr[i].p_vaddr;
-         return OK;
-      default:
-         break;;
-      }
-  }
-  if(have_computed_phdr) return OK;
-  return ENOENT;
-}
-
 /* Return >0 if there is an ELF interpreter (i.e. it is a dynamically linked
  * executable) and we could extract it successfully.
  * Return 0 if there isn't one.
  * Return <0 on error.
  */
-int elf_has_interpreter(const char *exec_hdr,          /* executable header */
+int elf_has_interpreter(char *exec_hdr,                /* executable header */
                int hdr_len, char *interp, int maxsz)
 {
-  const Elf_Ehdr *hdr = NULL;
-  const Elf_Phdr *phdr = NULL;
+  Elf_Ehdr *hdr = NULL;
+  Elf_Phdr *phdr = NULL;
   int e, i;
 
   if((e=elf_unpack(exec_hdr, hdr_len, &hdr, &phdr)) != OK) return e;
@@ -243,3 +218,95 @@ int elf_has_interpreter(const char *exec_hdr,              /* executable header */
   return 0;
 }
 
+int libexec_load_elf(struct exec_info *execi)
+{
+       int r;
+       Elf_Ehdr *hdr = NULL;
+       Elf_Phdr *phdr = NULL;
+       int e, i = 0;
+       int first = 1;
+       vir_bytes startv, stacklow;
+
+       assert(execi != NULL);
+       assert(execi->hdr != NULL);
+
+       if((e=elf_unpack(execi->hdr, execi->hdr_len, &hdr, &phdr)) != OK) {
+               printf("libexec_load_elf: elf_unpack failed\n");
+               return e;
+        }
+
+       /* this function can load the dynamic linker, but that
+        * shouldn't require an interpreter itself.
+        */
+       i = elf_has_interpreter(execi->hdr, execi->hdr_len, NULL, 0);
+       if(i > 0) {
+             printf("libexec: cannot load dynamically linked executable\n");
+             return ENOEXEC;
+       }
+
+       /* Make VM forget about all existing memory in process. */
+       vm_procctl(execi->proc_e, VMPPARAM_CLEAR);
+
+       execi->stack_size = roundup(execi->stack_size, PAGE_SIZE);
+       execi->stack_high = VM_STACKTOP;
+       assert(!(VM_STACKTOP % PAGE_SIZE));
+       stacklow = execi->stack_high - execi->stack_size;
+
+       for (i = 0; i < hdr->e_phnum; i++) {
+               vir_bytes seg_membytes, page_offset, vaddr;
+               Elf_Phdr *ph = &phdr[i];
+               if (ph->p_type != PT_LOAD || ph->p_memsz == 0) continue;
+#if 0
+               printf("index %d memsz 0x%lx vaddr 0x%lx\n", i, ph->p_memsz, ph->p_vaddr);
+#endif
+               vaddr =  ph->p_vaddr;
+               seg_membytes = ph->p_memsz;
+               page_offset = vaddr % PAGE_SIZE;
+               vaddr -= page_offset;
+               seg_membytes += page_offset;
+               seg_membytes = roundup(seg_membytes, PAGE_SIZE);
+               if(first || startv > vaddr) startv = vaddr;
+               first = 0;
+
+#if 0
+               printf("libexec_load_elf: mmap 0x%lx bytes at 0x%lx\n",
+                       seg_membytes, vaddr);
+#endif
+
+               /* Tell VM to make us some memory */
+               if(minix_mmap_for(execi->proc_e, (void *) vaddr, seg_membytes,
+                       PROT_READ|PROT_WRITE|PROT_EXEC,
+                       MAP_ANON|MAP_PREALLOC|MAP_FIXED, -1, 0) == MAP_FAILED) {
+                       printf("libexec_load_elf: mmap of 0x%lx bytes failed\n", seg_membytes);
+                       vm_procctl(execi->proc_e, VMPPARAM_CLEAR);
+                       return ENOMEM;
+               }
+
+               /* Copy executable section into it */
+               if(execi->load(execi, ph->p_offset, ph->p_vaddr, ph->p_filesz) != OK) {
+                       printf("libexec_load_elf: load callback failed\n");
+                       vm_procctl(execi->proc_e, VMPPARAM_CLEAR);
+                       return ENOMEM;
+               }
+       }
+
+       /* Make it a stack */
+       if(minix_mmap_for(execi->proc_e, (void *) stacklow, execi->stack_size,
+               PROT_READ|PROT_WRITE|PROT_EXEC,
+               MAP_ANON|MAP_FIXED, -1, 0) == MAP_FAILED) {
+               printf("libexec_load_elf: mmap for stack failed\n");
+               vm_procctl(execi->proc_e, VMPPARAM_CLEAR);
+               return ENOMEM;
+       }
+
+       /* record entry point and lowest load vaddr for caller */
+       execi->pc = hdr->e_entry;
+       execi->load_base = startv;
+
+       if((r = libexec_pm_newexec(execi->proc_e, execi)) != OK) {
+             printf("libexec_load_elf: pm_newexec failed: %d\n", r);
+       }
+
+       return(r);
+}
+
diff --git a/lib/libexec/exec_general.c b/lib/libexec/exec_general.c
new file mode 100644 (file)
index 0000000..4e55015
--- /dev/null
@@ -0,0 +1,57 @@
+#define _SYSTEM 1
+
+#include <minix/type.h>
+#include <minix/const.h>
+#include <sys/param.h>
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <libexec.h>
+#include <string.h>
+#include <assert.h>
+#include <minix/ipc.h>
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <machine/elf.h>
+
+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;
+  message m;
+
+  m.m_type = PM_NEWEXEC;
+  m.EXC_NM_PROC = proc_e;
+  m.EXC_NM_PTR = (char *)e;
+  if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r);
+
+  e->allow_setuid = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID);
+
+  return(m.m_type);
+}
index decd9447b79524bad8fce53649c3982b73d85557..282dc4e4c6c4c88be0848f65c512b3c9e37a1323 100644 (file)
@@ -3,15 +3,49 @@
 
 #include <sys/exec_elf.h>
 
-/* ELF routines */
-int read_header_elf(const char *exec_hdr, int hdr_len,
+struct exec_info;
+
+typedef int (*libexec_loadfunc_t)(struct exec_info *execi,
+       off_t offset, off_t vaddr, size_t len);
+
+typedef int (*libexec_clearfunc_t)(struct exec_info *execi,
+       off_t vaddr, size_t len);
+
+struct exec_info {
+    /* Filled in by libexec caller */
+    endpoint_t  proc_e;                 /* Process endpoint */
+    char *hdr;                          /* Header or full image */
+    size_t hdr_len;                     /* Size of hdr */
+    vir_bytes frame_len;                /* Stack size */
+    char progname[PROC_NAME_LEN];       /* Program name */
+    uid_t new_uid;                      /* Process UID after exec */
+    gid_t new_gid;                      /* Process GID after exec */
+    int allow_setuid;                   /* Allow set{u,g}id execution? */
+    libexec_loadfunc_t load;           /* Load callback */
+    libexec_clearfunc_t clear;         /* Clear callback */
+    void *opaque;                      /* Callback data */
+    vir_bytes stack_size;              /* Desired stack size */
+
+    /* Filled in by libexec load function */
+    vir_bytes load_base;               /* Where executable is loaded */
+    vir_bytes pc;                       /* Entry point of exec file */
+    vir_bytes stack_high;              /* High stack addr */
+};
+
+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);
+int read_header_elf(char *exec_hdr, int hdr_len,
    vir_bytes *text_vaddr, phys_bytes *text_paddr,
    vir_bytes *text_filebytes, vir_bytes *text_membytes,
    vir_bytes *data_vaddr, phys_bytes *data_paddr,
    vir_bytes *data_filebytes, vir_bytes *data_membytes,
    vir_bytes *pc, off_t *text_offset, off_t *data_offset);
 
-int elf_has_interpreter(const char *exec_hdr, int hdr_len, char *interp, int maxsz);
-int elf_phdr(const 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);
+
+int libexec_load_elf(struct exec_info *execi);
 
 #endif /* !_LIBEXEC_H_ */
index 2f2cf43fe1475bfbecbffd0959117375d23eb42c..0c2fd331663bf640c93663e1480b7c5cfb2a3ce0 100644 (file)
@@ -130,7 +130,7 @@ CPPFLAGS.${i}+= -I${LIBCSRCDIR}/include -I${LIBCSRCDIR}/locale
        link.c _mcontext.c mknod.c mmap.c nanosleep.c open.c \
        read.c sbrk.c select.c setuid.c sigprocmask.c stat.c \
        stime.c syscall.c _ucontext.c umask.c unlink.c waitpid.c \
-       brksize.S _ipc.S _senda.S ucontext.S
+       brksize.S _ipc.S _senda.S ucontext.S mmap.c
 .PATH.c: ${LIBCSRCDIR}/sys-minix
 .PATH.S: ${LIBCSRCDIR}/arch/${MACHINE}/sys-minix
 SRCS+= ${i}
index 19f1f11fd30258177b11d7803203eec46dbd27da..07e40425ba690d38c24b8e23fcd4bcd19afaf20e 100644 (file)
@@ -118,7 +118,6 @@ SRCS=  \
        vbox.c \
        vm_brk.c \
        vm_dmacalls.c \
-       vm_exec_newmem.c \
        vm_exit.c \
        vm_fork.c \
        vm_info.c \
diff --git a/lib/libsys/vm_exec_newmem.c b/lib/libsys/vm_exec_newmem.c
deleted file mode 100644 (file)
index 82d69e8..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#include "syslib.h"
-
-#include <minix/vm.h>
-
-/*===========================================================================*
- *                                vm_exec_newmem                            *
- *===========================================================================*/
-int vm_exec_newmem(endpoint_t ep, struct exec_newmem *args,
-       int argssize, char **ret_stack_top, int *ret_flags)
-{
-    message m;
-    int result;
-
-    m.VMEN_ENDPOINT = ep;
-    m.VMEN_ARGSPTR = (void *) args;
-    m.VMEN_ARGSSIZE = argssize;
-
-    result = _taskcall(VM_PROC_NR, VM_EXEC_NEWMEM, &m);
-
-    *ret_stack_top = m.VMEN_STACK_TOP;
-    *ret_flags = m.VMEN_FLAGS;
-
-    return result;
-}
-
index a3081683ce7d049ed21c855d7d3989426694ff11..dad82b9cefb639b1ffda24a7352b889c7d02b61a 100644 (file)
@@ -20,3 +20,4 @@ int vm_procctl(endpoint_t ep, int param)
     result = _taskcall(VM_PROC_NR, VM_PROCCTL, &m);
     return(result);
 }
+
index 785b544e5ce1ab88a6c9c51f98301fdf933d13f0..c29b5ec2642cc4dfc899b85958e2c58edc8da74f 100644 (file)
@@ -26,6 +26,7 @@
 #include <a.out.h>
 #include <signal.h>
 #include <string.h>
+#include <libexec.h>
 #include <sys/ptrace.h>
 #include "mproc.h"
 #include "param.h"
@@ -46,7 +47,7 @@ int do_exec()
        m.PM_PATH = m_in.exec_name;
        m.PM_PATH_LEN = m_in.exec_len;
        m.PM_FRAME = m_in.frame_ptr;
-       m.PM_FRAME_LEN = m_in.frame_len;
+       m.PM_FRAME_LEN = m_in.msg_frame_len;
        m.PM_EXECFLAGS = m_in.PMEXEC_FLAGS;
 
        tell_vfs(mp, &m);
@@ -57,16 +58,15 @@ int do_exec()
 
 
 /*===========================================================================*
- *                             do_exec_newmem                               *
+ *                             do_newexec                                   *
  *===========================================================================*/
-int do_exec_newmem()
+int do_newexec()
 {
        int proc_e, proc_n, allow_setuid;
        char *ptr;
        struct mproc *rmp;
-       struct exec_newmem args;
+       struct exec_info args;
        int r, flags;
-       char *stack_top;
 
        if (who_e != VFS_PROC_NR && who_e != RS_PROC_NR)
                return EPERM;
@@ -82,50 +82,46 @@ int do_exec_newmem()
        if (r != OK)
                panic("do_exec_newmem: sys_datacopy failed: %d", r);
 
-       if ((r = vm_exec_newmem(proc_e, &args, sizeof(args), &stack_top,
-                               &flags)) == OK) {
-               allow_setuid = 0;       /* Do not allow setuid execution */
-               rmp->mp_flags &= ~TAINTED;      /* By default not tainted */
+       allow_setuid = 0;       /* Do not allow setuid execution */
+       rmp->mp_flags &= ~TAINTED;      /* By default not tainted */
 
-               if (rmp->mp_tracer == NO_TRACER) {
-                       /* Okay, setuid execution is allowed */
-                       allow_setuid = 1;
-               }
+       if (rmp->mp_tracer == NO_TRACER) {
+               /* Okay, setuid execution is allowed */
+               allow_setuid = 1;
+       }
 
-               if (allow_setuid && args.setugid) {
-                       rmp->mp_effuid = args.new_uid;
-                       rmp->mp_effgid = args.new_gid;
-               }
+       if (allow_setuid && args.allow_setuid) {
+               rmp->mp_effuid = args.new_uid;
+               rmp->mp_effgid = args.new_gid;
+       }
 
-               /* A process is considered 'tainted' when it's executing with
-                * setuid or setgid bit set, or when the real{u,g}id doesn't
-                * match the eff{u,g}id, respectively. */
-               if (allow_setuid && args.setugid) {
-                       /* Program has setuid and/or setgid bits set */
-                       rmp->mp_flags |= TAINTED;
-               } else if (rmp->mp_effuid != rmp->mp_realuid ||
-                          rmp->mp_effgid != rmp->mp_realgid) {
-                       rmp->mp_flags |= TAINTED;
-               }
+       /* A process is considered 'tainted' when it's executing with
+        * setuid or setgid bit set, or when the real{u,g}id doesn't
+        * match the eff{u,g}id, respectively. */
+       if (allow_setuid && args.allow_setuid) {
+               /* Program has setuid and/or setgid bits set */
+               rmp->mp_flags |= TAINTED;
+       } else if (rmp->mp_effuid != rmp->mp_realuid ||
+                  rmp->mp_effgid != rmp->mp_realgid) {
+               rmp->mp_flags |= TAINTED;
+       }
 
-               /* System will save command line for debugging, ps(1) output, etc. */
-               strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1);
-               rmp->mp_name[PROC_NAME_LEN-1] = '\0';
+       /* System will save command line for debugging, ps(1) output, etc. */
+       strncpy(rmp->mp_name, args.progname, PROC_NAME_LEN-1);
+       rmp->mp_name[PROC_NAME_LEN-1] = '\0';
 
-               /* Save offset to initial argc (for procfs) */
-               rmp->mp_frame_addr = (vir_bytes) stack_top - args.args_bytes;
-               rmp->mp_frame_len = args.args_bytes;
+       /* Save offset to initial argc (for procfs) */
+       rmp->mp_frame_addr = (vir_bytes) args.stack_high - args.frame_len;
+       rmp->mp_frame_len = args.frame_len;
 
-               /* Kill process if something goes wrong after this point. */
-               rmp->mp_flags |= PARTIAL_EXEC;
+       /* Kill process if something goes wrong after this point. */
+       rmp->mp_flags |= PARTIAL_EXEC;
+
+       mp->mp_reply.reply_res2= (vir_bytes) rmp->mp_frame_addr;
+       mp->mp_reply.reply_res3= flags;
+       if (allow_setuid && args.allow_setuid)
+               mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID;
 
-               mp->mp_reply.reply_res2= (vir_bytes) stack_top;
-               mp->mp_reply.reply_res3= flags;
-               if (allow_setuid && args.setugid)
-                       mp->mp_reply.reply_res3 |= EXC_NM_RF_ALLOW_SETUID;
-       } else {
-               printf("PM: newmem failed for %s\n", args.progname);
-       }
        return r;
 }
 
index 4c2863306b61e136c7809cbc5b724157fa264852..a4a2d97423b2a247be77840ab065c0af058e568e 100644 (file)
@@ -12,7 +12,7 @@
 #define new_val                m1_p1
 #define old_val                m1_p2
 #define sig            m6_i1
-#define frame_len      m1_i2
+#define msg_frame_len  m1_i2
 #define frame_ptr      m1_p2
 #define status         m1_i1
 #define usr_id         m1_i1
index 76148ae971393d53cfa08a4e58b01c441d2333a8..00646d3ed201a937b3259bee363e80882630ff42 100644 (file)
@@ -18,7 +18,7 @@ int do_brk(void);
 
 /* exec.c */
 int do_exec(void);
-int do_exec_newmem(void);
+int do_newexec(void);
 int do_execrestart(void);
 void exec_restart(struct mproc *rmp, int result, vir_bytes pc, vir_bytes sp);
 
index 203b02f799eb856571815b19d406e5d7fa237a67..5051cec7d5038eea06c438d8fc478c0ad0c6732c 100644 (file)
@@ -111,7 +111,7 @@ int (*call_vec[])(void) = {
        no_sys,         /* 97 = unused */
        do_sprofile,    /* 98 = sprofile */
        do_cprofile,    /* 99 = cprofile */
-       do_exec_newmem, /* 100 = exec_newmem */
+       do_newexec,     /* 100 = newexec */
        do_srv_fork,    /* 101 = srv_fork */
        do_execrestart, /* 102 = exec_restart */
        no_sys,         /* 103 = unused */
index e0faa0b3edeec921c73dde50a2fb910e039d60e1..3eaad4ec77030e550da572a688dafb35cd1efd3e 100644 (file)
@@ -2,30 +2,19 @@
 #include <a.out.h>
 #include <assert.h>
 #include <libexec.h>
-#include "exec.h"
-
-#define BLOCK_SIZE     1024
+#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_newmem(int proc_e, vir_bytes text_addr,
-       vir_bytes text_bytes, vir_bytes data_addr,
-       vir_bytes data_bytes, vir_bytes tot_bytes,
-       vir_bytes frame_len, int sep_id, int is_elf,
-       dev_t st_dev, ino_t st_ino, time_t ctime, char *progname,
-       int new_uid, int new_gid, vir_bytes *stack_topp,
-       int *load_textp, int *allow_setuidp);
-static void patch_ptr(char stack[ARG_MAX], vir_bytes base);
 static int exec_restart(int proc_e, int result, vir_bytes pc);
 static int read_seg(struct exec_info *execi, off_t off,
-        int proc_e, int seg, vir_bytes seg_addr, phys_bytes seg_bytes);
-static int load_elf(struct exec_info *execi);
+        off_t seg_addr, size_t seg_bytes);
 
 /* Array of loaders for different object formats */
 static struct exec_loaders {
-       int (*load_object)(struct exec_info *);
+       libexec_exec_loadfunc_t load_object;
 } const exec_loaders[] = {
-       { load_elf },
+       { libexec_load_elf },
        { NULL }
 };
 
@@ -128,12 +117,16 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
        struct exec_info execi;
        int i;
 
+       memset(&execi, 0, sizeof(execi));
+
+       execi.stack_size = DEFAULT_STACK_LIMIT;
        execi.proc_e = proc_e;
-       execi.image = exec;
-       execi.image_len = exec_len;
+       execi.hdr = exec;
+       execi.hdr_len = exec_len;
        strncpy(execi.progname, progname, PROC_NAME_LEN-1);
        execi.progname[PROC_NAME_LEN-1] = '\0';
        execi.frame_len = frame_len;
+       execi.load = read_seg;
 
        for(i = 0; exec_loaders[i].load_object != NULL; i++) {
            r = (*exec_loaders[i].load_object)(&execi);
@@ -148,14 +141,12 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
        }
 
        /* Patch up stack and copy it from RS to new core image. */
-       vsp = execi.stack_top;
+       vsp = execi.stack_high;
        vsp -= frame_len;
-       patch_ptr(frame, vsp);
+       libexec_patch_ptr(frame, vsp);
        r = sys_datacopy(SELF, (vir_bytes) frame,
                proc_e, (vir_bytes) vsp, (phys_bytes)frame_len);
        if (r != OK) {
-               printf("RS: stack_top is 0x%lx; tried to copy to 0x%lx in %d\n",
-                       execi.stack_top, vsp, proc_e);
                printf("do_exec: copying out new stack failed: %d\n", r);
                exec_restart(proc_e, r, execi.pc);
                return r;
@@ -164,149 +155,6 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
        return exec_restart(proc_e, OK, execi.pc);
 }
 
-static int load_elf(struct exec_info *execi)
-{
-  int r;
-  int proc_e;
-  phys_bytes tot_bytes;                /* total space for program, including gap */
-  vir_bytes text_vaddr, text_paddr, text_filebytes, text_membytes;
-  vir_bytes data_vaddr, data_paddr, data_filebytes, data_membytes;
-  off_t text_offset, data_offset;
-  int sep_id, is_elf, load_text, allow_setuid;
-  uid_t new_uid;
-  gid_t new_gid;
-
-  assert(execi != NULL);
-  assert(execi->image != NULL);
-
-  proc_e = execi->proc_e;
-
-  /* Read the file header and extract the segment sizes. */
-  r = read_header_elf(execi->image, execi->image_len, &text_vaddr, &text_paddr,
-                     &text_filebytes, &text_membytes,
-                     &data_vaddr, &data_paddr,
-                     &data_filebytes, &data_membytes,
-                     &execi->pc, &text_offset, &data_offset);
-  if (r != OK) {
-      return(r);
-  }
-
-  if(elf_has_interpreter(execi->image, execi->image_len, NULL, 0)) {
-       printf("RS: can't execute dynamically linked executables\n");
-       return ENOEXEC;
-  }
-
-  new_uid= getuid();
-  new_gid= getgid();
-  allow_setuid = 0;
-
-  sep_id = 0;
-  is_elf = 1;
-  tot_bytes = 0; /* Use default stack size */
-
-  r = exec_newmem(proc_e,
-                 trunc_page(text_vaddr), text_membytes,
-                 trunc_page(data_vaddr), data_membytes,
-                 tot_bytes, execi->frame_len, sep_id, is_elf,
-                 0 /*dev*/, proc_e /*inum*/, 0 /*ctime*/,
-                 execi->progname, new_uid, new_gid,
-                 &execi->stack_top, &load_text, &allow_setuid);
-  if (r != OK)
-  {
-      printf("RS: load_elf: exec_newmem failed: %d\n", r);
-      exec_restart(proc_e, r, execi->pc);
-      return r;
-  }
-
-  /* Read in text and data segments. */
-  if (load_text) {
-      r = read_seg(execi, text_offset, proc_e, T, text_vaddr, text_filebytes);
-      if (r != OK)
-      {
-         printf("RS: load_elf: read_seg failed: %d\n", r);
-         exec_restart(proc_e, r, execi->pc);
-         return r;
-      }
-  }
-  else
-      printf("RS: load_elf: not loading text segment\n");
-
-  r = read_seg(execi, data_offset, proc_e, D, data_vaddr, data_filebytes);
-  if (r != OK)
-  {
-      printf("RS: load_elf: read_seg failed: %d\n", r);
-      exec_restart(proc_e, r, execi->pc);
-      return r;
-  }
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                             exec_newmem                                  *
- *===========================================================================*/
-static int exec_newmem(
-  int proc_e,
-  vir_bytes text_addr,
-  vir_bytes text_bytes,
-  vir_bytes data_addr,
-  vir_bytes data_bytes,
-  vir_bytes tot_bytes,
-  vir_bytes frame_len,
-  int sep_id,
-  int is_elf,
-  dev_t st_dev,
-  ino_t st_ino,
-  time_t ctime,
-  char *progname,
-  int new_uid,
-  int new_gid,
-  vir_bytes *stack_topp,
-  int *load_textp,
-  int *allow_setuidp
-)
-{
-       int r;
-       struct exec_newmem e;
-       message m;
-
-       e.text_addr = text_addr;
-       e.text_bytes= text_bytes;
-       e.data_addr = data_addr;
-       e.data_bytes= data_bytes;
-       e.tot_bytes= tot_bytes;
-       e.args_bytes= frame_len;
-       e.sep_id= sep_id;
-       e.is_elf= is_elf;
-       e.st_dev= st_dev;
-       e.st_ino= st_ino;
-       e.enst_ctime= ctime;
-       e.new_uid= new_uid;
-       e.new_gid= new_gid;
-       e.setugid= *allow_setuidp;
-       strncpy(e.progname, progname, sizeof(e.progname)-1);
-       e.progname[sizeof(e.progname)-1]= '\0';
-
-       m.m_type= EXEC_NEWMEM;
-       m.EXC_NM_PROC= proc_e;
-       m.EXC_NM_PTR= (char *)&e;
-       r= sendrec(PM_PROC_NR, &m);
-       if (r != OK)
-               return r;
-#if 0
-       printf("exec_newmem: r = %d, m_type = %d\n", r, m.m_type);
-#endif
-       *stack_topp= m.m1_i1;
-       *load_textp= !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT);
-       *allow_setuidp= !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID);
-#if 0
-       printf("RS: exec_newmem: stack_top = 0x%x\n", *stack_topp);
-       printf("RS: exec_newmem: load_text = %d\n", *load_textp);
-#endif
-       return m.m_type;
-}
-
-
 /*===========================================================================*
  *                             exec_restart                                 *
  *===========================================================================*/
@@ -326,48 +174,13 @@ static int exec_restart(int proc_e, int result, vir_bytes pc)
 }
 
 /*===========================================================================*
- *                             patch_ptr                                    *
- *===========================================================================*/
-static void patch_ptr(
-char stack[ARG_MAX],           /* pointer to stack image within PM */
-vir_bytes base                 /* virtual address of stack base inside user */
-)
-{
-/* 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++;
-  }
-}
-
-/*===========================================================================*
- *                             read_seg                                     *
+ *                             read_seg                                     *
  *===========================================================================*/
 static int read_seg(
-struct exec_info *execi,       /* various data needed for exec */
-off_t off,                     /* offset in file */
-int proc_e,                    /* process number (endpoint) */
-int seg,                       /* T, D, or S */
-vir_bytes seg_addr,            /* address to load segment */
-phys_bytes seg_bytes           /* how much is to be transferred? */
+struct exec_info *execi,       /* various data needed for exec */
+off_t off,                     /* offset in file */
+off_t seg_addr,            /* address to load segment */
+size_t seg_bytes           /* how much is to be transferred? */
 )
 {
 /*
@@ -378,9 +191,11 @@ phys_bytes seg_bytes               /* how much is to be transferred? */
 
   int r;
 
-  assert((seg == T)||(seg == D));
-
-  if (off+seg_bytes > execi->image_len) return ENOEXEC;
-  r= sys_vircopy(SELF, D, ((vir_bytes)execi->image)+off, proc_e, seg, seg_addr, seg_bytes);
+  if (off+seg_bytes > execi->hdr_len) return ENOEXEC;
+  if((r= sys_vircopy(SELF, D, ((vir_bytes)execi->hdr)+off,
+       execi->proc_e, D, seg_addr, seg_bytes)) != OK) {
+       printf("RS: exec read_seg: copy 0x%lx bytes into %d at 0x%lx failed: %d\n",
+               seg_bytes, execi->proc_e, seg_addr, r);
+  }
   return r;
 }
diff --git a/servers/rs/exec.h b/servers/rs/exec.h
deleted file mode 100644 (file)
index a395a55..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _RS_EXEC_H_
-#define _RS_EXEC_H_ 1
-
-struct exec_info {
-    int  proc_e;                       /* Process endpoint */
-    char *image;                       /* Executable image */
-    size_t image_len;                  /* Size of executable image */
-    vir_bytes pc;                      /* Entry point of exec file */
-    vir_bytes stack_top;               /* Top of the stack */
-    vir_bytes frame_len;               /* Stack size */
-    char progname[PROC_NAME_LEN];      /* Program name */
-};
-
-#endif /* !_RS_EXEC_H_ */
index 6d2a01df63c830d8db086fa205d01d271d989660..9a363e22448a1f96ca44ad5f5a46bebaf58ad32c 100644 (file)
 #include <machine/vmparam.h>
 #include <assert.h>
 #include <fcntl.h>
-#include "exec.h"
 
 #define _KERNEL        /* for ELF_AUX_ENTRIES */
 #include <libexec.h>
 
+/* fields only used by elf and in VFS */
+struct vfs_exec_info {
+    struct exec_info args;             /* libexec exec args */
+    struct vnode *vp;                  /* Exec file's vnode */
+    struct vmnt *vmp;                  /* Exec file's vmnt */
+    struct stat sb;                    /* Exec file's stat structure */
+    int userflags;                     /* exec() flags from userland */
+    int is_dyn;                                /* Dynamically linked executable */
+    int elf_main_fd;                   /* Dyn: FD of main program execuatble */
+    char execname[PATH_MAX];           /* Full executable invocation */
+};
+
 static void lock_exec(void);
 static void unlock_exec(void);
-static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes,
-       vir_bytes data_addr, vir_bytes data_bytes, vir_bytes tot_bytes,
-       vir_bytes frame_len, int sep_id, int is_elf, dev_t st_dev,
-       ino_t st_ino, time_t ctime, char *progname, int new_uid, int new_gid,
-       vir_bytes *stack_topp, int *load_textp, int *setugidp);
 static int patch_stack(struct vnode *vp, char stack[ARG_MAX],
        size_t *stk_bytes, char path[PATH_MAX]);
-static int is_script(struct exec_info *execi);
+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);
-static void patch_ptr(char stack[ARG_MAX], vir_bytes base);
 static void clo_exec(struct fproc *rfp);
-static int read_seg(struct vnode *vp, off_t off, int proc_e, int seg,
-       vir_bytes seg_addr, phys_bytes seg_bytes);
-static int load_elf(struct exec_info *execi);
-static int stack_prepare_elf(struct exec_info *execi,
+static int stack_prepare_elf(struct vfs_exec_info *execi,
        char *curstack, size_t *frame_len, vir_bytes *vsp, int *extrabase);
-static int map_header(struct exec_info *execi);
+static int map_header(struct vfs_exec_info *execi);
+static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t seg_bytes);
 
 #define PTRSIZE        sizeof(char *) /* Size of pointers in argv[] and envp[]. */
 
 /* Array of loaders for different object file formats */
-typedef int (*exechook_t)(struct exec_info *execpackage);
-typedef int (*stackhook_t)(struct exec_info *execi, char *curstack,
+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);
 struct exec_loaders {
-       exechook_t load_object;  /* load executable into memory */
+       libexec_exec_loadfunc_t load_object;     /* load executable into memory */
        stackhook_t setup_stack; /* prepare stack before argc and argv push */
 };
 
 static const struct exec_loaders exec_loaders[] = {
-       { load_elf,  stack_prepare_elf },
+       { libexec_load_elf,  stack_prepare_elf },
        { NULL, NULL }
 };
 
@@ -110,8 +113,8 @@ static void unlock_exec(void)
 /*===========================================================================*
  *                             get_read_vp                                  *
  *===========================================================================*/
-static int get_read_vp(struct exec_info *execi, char *fullpath,
-       int copyprogname, int sugid, struct lookup *resolve, struct fproc *fp)
+static int get_read_vp(struct vfs_exec_info *execi,
+  char *fullpath, int copyprogname, int sugid, struct lookup *resolve, struct fproc *fp)
 {
 /* Make the executable that we want to exec() into the binary pointed
  * to by 'fullpath.' This function fills in necessary details in the execi
@@ -137,8 +140,8 @@ static int get_read_vp(struct exec_info *execi, char *fullpath,
                char *cp = strrchr(fullpath, '/');
                if(cp) cp++;
                else cp = fullpath;
-               strncpy(execi->progname, cp, sizeof(execi->progname)-1);
-               execi->progname[sizeof(execi->progname)-1] = '\0';
+               strncpy(execi->args.progname, cp, sizeof(execi->args.progname)-1);
+               execi->args.progname[sizeof(execi->args.progname)-1] = '\0';
        }
 
        /* Open executable */
@@ -161,12 +164,12 @@ static int get_read_vp(struct exec_info *execi, char *fullpath,
         if (sugid) {
                /* Deal with setuid/setgid executables */
                if (execi->vp->v_mode & I_SET_UID_BIT) {
-                       execi->new_uid = execi->vp->v_uid;
-                       execi->setugid = 1;
+                       execi->args.new_uid = execi->vp->v_uid;
+                       execi->args.allow_setuid = 1;
                }
                if (execi->vp->v_mode & I_SET_GID_BIT) {
-                       execi->new_gid = execi->vp->v_gid;
-                       execi->setugid = 1;
+                       execi->args.new_gid = execi->vp->v_gid;
+                       execi->args.allow_setuid = 1;
                }
         }
 
@@ -198,7 +201,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
   struct fproc *rfp;
   int extrabase = 0;
   static char mbuf[ARG_MAX];   /* buffer for stack and zeroes */
-  struct exec_info execi;
+  struct vfs_exec_info execi;
   int i;
   static char fullpath[PATH_MAX],
        elf_interpreter[PATH_MAX],
@@ -213,6 +216,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
 
   /* passed from exec() libc code */
   execi.userflags = user_exec_flags;
+  execi.args.stack_size = DEFAULT_STACK_LIMIT;
 
   okendpt(proc_e, &slot);
   rfp = fp = &fproc[slot];
@@ -233,8 +237,8 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
   }
 
   /* The default is to keep the original user and group IDs */
-  execi.new_uid = rfp->fp_effuid;
-  execi.new_gid = rfp->fp_effgid;
+  execi.args.new_uid = rfp->fp_effuid;
+  execi.args.new_gid = rfp->fp_effgid;
 
   /* Get the exec file name. */
   FAILCHECK(fetch_name(path, path_len, fullpath));
@@ -267,7 +271,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
    * executable instead. But open the current executable in an
    * fd for the current process.
    */
-  if(elf_has_interpreter(execi.hdr, execi.hdr_len,
+  if(elf_has_interpreter(execi.args.hdr, execi.args.hdr_len,
        elf_interpreter, sizeof(elf_interpreter))) {
        /* Switch the executable vnode to the interpreter */
        execi.is_dyn = 1;
@@ -292,11 +296,14 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
        Get_read_vp(execi, fullpath, 0, 0, &resolve, fp);
   }
 
-  execi.proc_e = proc_e;
-  execi.frame_len = frame_len;
+  execi.args.opaque = &execi;
+  execi.args.load = &read_seg;
+  execi.args.clear = NULL;
+  execi.args.proc_e = proc_e;
+  execi.args.frame_len = frame_len;
 
   for (i = 0; exec_loaders[i].load_object != NULL; i++) {
-      r = (*exec_loaders[i].load_object)(&execi);
+      r = (*exec_loaders[i].load_object)(&execi.args);
       /* Loaded successfully, so no need to try other loaders */
       if (r == OK) { makestack = exec_loaders[i].setup_stack; break; }
   }
@@ -304,31 +311,31 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
   FAILCHECK(r);
 
   /* Save off PC */
-  *pc = execi.pc;
+  *pc = execi.args.pc;
 
   /* call a stack-setup function if this executable type wants it */
-  vsp = execi.stack_top - frame_len;
+  vsp = execi.args.stack_high - frame_len;
   if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp, &extrabase));
 
   /* Patch up stack and copy it from VFS to new core image. */
-  patch_ptr(mbuf, vsp + extrabase);
+  libexec_patch_ptr(mbuf, vsp + extrabase);
   FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
                   (phys_bytes)frame_len));
-  
+
   /* Return new stack pointer to caller */
   *newsp = vsp;
 
   clo_exec(rfp);
 
-  if (execi.setugid) {
+  if (execi.args.allow_setuid) {
        /* If after loading the image we're still allowed to run with
         * setuid or setgid, change credentials now */
-       rfp->fp_effuid = execi.new_uid;
-       rfp->fp_effgid = execi.new_gid;
+       rfp->fp_effuid = execi.args.new_uid;
+       rfp->fp_effgid = execi.args.new_gid;
   }
 
   /* Remember the new name of the process */
-  strcpy(rfp->fp_name, execi.progname);
+  strcpy(rfp->fp_name, execi.args.progname);
 
 pm_execfinal:
   if (execi.vp != NULL) {
@@ -339,7 +346,7 @@ pm_execfinal:
   return(r);
 }
 
-static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *framelen,
+static int stack_prepare_elf(struct vfs_exec_info *execi, char *frame, size_t *framelen,
        vir_bytes *newsp, int *extrabase)
 {
        AuxInfo *a, *term;
@@ -351,8 +358,8 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame
        if(!execi->is_dyn)
                return OK;
 
-       assert(execi->hdr_len >= sizeof(*elf_header));
-       elf_header = (Elf_Ehdr *) execi->hdr;
+       assert(execi->args.hdr_len >= sizeof(*elf_header));
+       elf_header = (Elf_Ehdr *) execi->args.hdr;
 
        /* exec() promises stack space. Now find it. */
        mysp++; /* skip argc */
@@ -399,12 +406,11 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame
 #define AUXINFO(type, value) \
        { assert((char *) a < (char *) mysp_end); a->a_type = type; a->a_v = value; a++; }
 #if 0
-       AUXINFO(AT_PHDR, execi->elf_phdr);
        AUXINFO(AT_PHENT, elf_header->e_phentsize);
        AUXINFO(AT_PHNUM, elf_header->e_phnum);
 #endif
-       AUXINFO(AT_BASE, execi->elf_base);
-       AUXINFO(AT_ENTRY, execi->pc);
+       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);
 
@@ -439,150 +445,16 @@ static int stack_prepare_elf(struct exec_info *execi, char *frame, size_t *frame
        return OK;
 }
 
-/*===========================================================================*
- *                             load_elf                                     *
- *===========================================================================*/
-static int load_elf(struct exec_info *execi)
-{
-  int r;
-  struct vnode *vp;
-  int proc_e;
-  phys_bytes tot_bytes;                /* total space for program, including gap */
-  vir_bytes text_vaddr, text_paddr, text_filebytes, text_membytes;
-  vir_bytes data_vaddr, data_paddr, data_filebytes, data_membytes;
-  off_t text_offset, data_offset;
-  int sep_id, is_elf, i;
-  vir_bytes text_base, data_base;
-
-  assert(execi != NULL);
-  assert(execi->hdr != NULL);
-  assert(execi->vp != NULL);
-
-  proc_e = execi->proc_e;
-  vp = execi->vp;
-
-  /* this function can load the dynamic linker, but that 
-   * shouldn't require an interpreter itself.
-   */
-  i = elf_has_interpreter(execi->hdr, execi->hdr_len, NULL, 0);
-  if(i > 0) {
-       printf("VFS: cannot load dynamically linked executable\n");
-       return ENOEXEC;
-  }
-
-  /* Read the file header and extract the segment sizes. */
-  r = read_header_elf(execi->hdr, execi->hdr_len, &text_vaddr, &text_paddr,
-                     &text_filebytes, &text_membytes,
-                     &data_vaddr, &data_paddr,
-                     &data_filebytes, &data_membytes,
-                     &execi->pc, &text_offset, &data_offset);
-
-  if (r != OK) {
-       return(r);
-  }
-
-  if(elf_phdr(execi->hdr, execi->hdr_len, &execi->elf_phdr) == OK)
-       if(execi->elf_phdr == 0)        /* 0 should indicate: not known */
-               printf("VFS: warning: unexpected zero elf_phdr\n");
-
-  sep_id = 0;
-  is_elf = 1;
-  tot_bytes = 0; /* Use default stack size */
-  text_base = trunc_page(text_vaddr);
-  data_base = trunc_page(data_vaddr);
-  execi->elf_base = MIN(text_base, data_base);
-  r = exec_newmem(proc_e,
-                  text_base, text_membytes,
-                  data_base, data_membytes,
-                 tot_bytes, execi->frame_len, sep_id, is_elf,
-                 vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime,
-                 execi->progname, execi->new_uid, execi->new_gid,
-                 &execi->stack_top, &execi->load_text, &execi->setugid);
-
-  if (r != OK) {
-        printf("VFS: load_elf: exec_newmem failed: %d\n", r);
-        return(r);
-  }
-
-  /* Read in text and data segments. */
-  if (execi->load_text)
-      r = read_seg(vp, text_offset, proc_e, T, text_vaddr, text_filebytes);
-
-  if (r == OK)
-      r = read_seg(vp, data_offset, proc_e, D, data_vaddr, data_filebytes);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             exec_newmem                                  *
- *===========================================================================*/
-static int exec_newmem(
-  int proc_e,
-  vir_bytes text_addr,
-  vir_bytes text_bytes,
-  vir_bytes data_addr,
-  vir_bytes data_bytes,
-  vir_bytes tot_bytes,
-  vir_bytes frame_len,
-  int sep_id,
-  int is_elf,
-  dev_t st_dev,
-  ino_t st_ino,
-  time_t ctime,
-  char *progname,
-  int new_uid,
-  int new_gid,
-  vir_bytes *stack_topp,
-  int *load_textp,
-  int *setugidp
-)
-{
-/* Allocate a new memory map for a process that tries to exec */
-  int r;
-  struct exec_newmem e;
-  message m;
-
-  assert(setugidp != NULL);
-
-  e.text_addr = text_addr;
-  e.text_bytes = text_bytes;
-  e.data_addr = data_addr;
-  e.data_bytes = data_bytes;
-  e.tot_bytes  = tot_bytes;
-  e.args_bytes = frame_len;
-  e.sep_id     = sep_id;
-  e.is_elf     = is_elf;
-  e.st_dev     = st_dev;
-  e.st_ino     = st_ino;
-  e.enst_ctime = ctime;
-  e.new_uid    = new_uid;
-  e.new_gid    = new_gid;
-  e.setugid    = *setugidp;
-  strncpy(e.progname, progname, sizeof(e.progname)-1);
-  e.progname[sizeof(e.progname)-1] = '\0';
-
-  m.m_type = EXEC_NEWMEM;
-  m.EXC_NM_PROC = proc_e;
-  m.EXC_NM_PTR = (char *)&e;
-  if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r);
-
-  *stack_topp = m.m1_i1;
-  *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT);
-  *setugidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID);
-
-  return(m.m_type);
-}
-
 /*===========================================================================*
  *                             is_script                                    *
  *===========================================================================*/
-static int is_script(struct exec_info *execi)
+static int is_script(struct vfs_exec_info *execi)
 {
 /* Is Interpreted script? */
-  assert(execi->hdr != NULL);
+  assert(execi->args.hdr != NULL);
 
-  return(execi->hdr[0] == '#' && execi->hdr[1] == '!' && execi->hdr_len >= 2);
+  return(execi->args.hdr[0] == '#' && execi->args.hdr[1] == '!'
+       && execi->args.hdr_len >= 2);
 }
 
 /*===========================================================================*
@@ -713,56 +585,15 @@ int replace
        ((char **) stack)[0]++; /* nargs++; */
   }
   /* Now patch up argv[] and envp[] by offset. */
-  patch_ptr(stack, (vir_bytes) offset);
+  libexec_patch_ptr(stack, (vir_bytes) offset);
   ((char **) stack)[1] = (char *) a0;  /* set argv[0] correctly */
   return(TRUE);
 }
 
-
-/*===========================================================================*
- *                             patch_ptr                                    *
- *===========================================================================*/
-static void patch_ptr(
-char stack[ARG_MAX],           /* pointer to stack image within PM */
-vir_bytes base                 /* virtual address of stack base inside user */
-)
-{
-/* 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++;
-  }
-}
-
 /*===========================================================================*
  *                             read_seg                                     *
  *===========================================================================*/
-static int read_seg(
-struct vnode *vp,              /* inode descriptor to read from */
-off_t off,                     /* offset in file */
-int proc_e,                    /* process number (endpoint) */
-int seg,                       /* T, D, or S */
-vir_bytes seg_addr,            /* address to load segment */
-phys_bytes seg_bytes           /* how much is to be transferred? */
-)
+static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t seg_bytes)
 {
 /*
  * The byte count on read is usually smaller than the segment count, because
@@ -770,51 +601,16 @@ phys_bytes seg_bytes              /* how much is to be transferred? */
  * partially initialized.
  */
   int r;
-  unsigned n, o;
   u64_t new_pos;
   unsigned int cum_io;
-  static char buf[128 * 1024];
-
-  assert((seg == T)||(seg == D));
+  struct vnode *vp = ((struct vfs_exec_info *) execi->opaque)->vp;
 
   /* Make sure that the file is big enough */
   if (off + seg_bytes > LONG_MAX) return(EIO);
   if ((unsigned long) vp->v_size < off+seg_bytes) return(EIO);
 
-  if (seg == T) {
-       /* We have to use a copy loop until safecopies support segments */
-       o = 0;
-       while (o < seg_bytes) {
-               n = seg_bytes - o;
-               if (n > sizeof(buf))
-                       n = sizeof(buf);
-
-               if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o),
-                                      READING, VFS_PROC_NR, buf,
-                                      n, &new_pos, &cum_io)) != OK) {
-                       printf("VFS: read_seg: req_readwrite failed (text)\n");
-                       return(r);
-               }
-
-               if (cum_io != n) {
-                       printf(
-               "VFSread_seg segment has not been read properly by exec() \n");
-                       return(EIO);
-               }
-
-               if ((r = sys_vircopy(VFS_PROC_NR, D, (vir_bytes)buf, proc_e,
-                                    seg, seg_addr + o, n)) != OK) {
-                       printf("VFS: read_seg: copy failed (text)\n");
-                       return(r);
-               }
-
-               o += n;
-       }
-       return(OK);
-  } else if (seg == D) {
-
        if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING,
-                        proc_e, (char*)seg_addr, seg_bytes,
+                        execi->proc_e, (char*)seg_addr, seg_bytes,
                         &new_pos, &cum_io)) != OK) {
            printf("VFS: read_seg: req_readwrite failed (data)\n");
            return(r);
@@ -824,9 +620,6 @@ phys_bytes seg_bytes                /* how much is to be transferred? */
                printf("VFS: read_seg segment has not been read properly\n");
 
        return(r);
-  }
-
-  return(OK);
 }
 
 
@@ -848,7 +641,7 @@ static void clo_exec(struct fproc *rfp)
 /*===========================================================================*
  *                             map_header                                   *
  *===========================================================================*/
-static int map_header(struct exec_info *execi)
+static int map_header(struct vfs_exec_info *execi)
 {
   int r;
   u64_t new_pos;
@@ -859,12 +652,12 @@ static int map_header(struct exec_info *execi)
   pos = 0;     /* Read from the start of the file */
 
   /* How much is sensible to read */
-  execi->hdr_len = MIN(execi->vp->v_size, sizeof(hdr));
-  execi->hdr = hdr;
+  execi->args.hdr_len = MIN(execi->vp->v_size, sizeof(hdr));
+  execi->args.hdr = hdr;
 
   r = req_readwrite(execi->vp->v_fs_e, execi->vp->v_inode_nr,
        cvul64(pos), READING, VFS_PROC_NR, hdr,
-       execi->hdr_len, &new_pos, &cum_io);
+       execi->args.hdr_len, &new_pos, &cum_io);
   if (r != OK) {
        printf("VFS: exec: map_header: req_readwrite failed\n");
        return(r);
diff --git a/servers/vfs/exec.h b/servers/vfs/exec.h
deleted file mode 100644 (file)
index 11dc859..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _VFS_EXEC_H_
-#define _VFS_EXEC_H_ 1
-
-struct exec_info {
-    int  proc_e;                       /* Process endpoint */
-    char *hdr;                         /* Exec file's header */
-    int hdr_len;                       /* How many bytes are in hdr */
-    vir_bytes pc;                      /* Entry point of exec file */
-    vir_bytes stack_top;               /* Top of the stack */
-    vir_bytes frame_len;               /* Stack size */
-    uid_t new_uid;                     /* Process UID after exec */
-    gid_t new_gid;                     /* Process GID after exec */
-    int load_text;                     /* Load text section? */
-    int setugid;                       /* Allow set{u,g}id execution? */
-    struct vnode *vp;                  /* Exec file's vnode */
-    struct vmnt *vmp;                  /* Exec file's vmnt */
-    struct stat sb;                    /* Exec file's stat structure */
-    char progname[PROC_NAME_LEN];      /* Program name */
-    int userflags;                     /* exec() flags from userland */
-
-    /* fields only used by elf and in VFS */
-    int is_dyn;                                /* Dynamically linked executable */
-    vir_bytes elf_phdr;                        /* Program header location */
-    vir_bytes elf_base;                        /* Userland addr load address */
-    int elf_main_fd;                   /* Dyn: FD of main program execuatble */
-    char execname[PATH_MAX];           /* Full executable invocation */
-};
-
-#endif /* !_VFS_EXEC_H_ */
index ee129b9abe05d66afce39ce2d87f27be4d4519fa..6d84440cfb623646f1851200ba2647b7851f1a5f 100644 (file)
@@ -1,10 +1,5 @@
 #include <machine/vm.h>
 
-/* As visible from the user space process, where is the top of the
- * stack (first non-stack byte), when in paged mode?
- */
-#define VM_STACKTOP     0x80000000
-
 /* And what is the highest addressable piece of memory, when in paged
  * mode? Some data for kernel and stack are subtracted from this, the
  * final results stored in bytes in arch.vm_data_top.
index 69b53f83926a8fad2ce2abca62d4f72f3b339b04..9a05008803d2b83a60a33c9790724f5c4285e5e3 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <errno.h>
 #include <assert.h>
+#include <string.h>
 #include <env.h>
 #include <pagetable.h>
 #include <sys/param.h>
 
 #include "memory.h"
 
-static int new_mem(struct vmproc *vmp, vir_bytes text_addr, vir_bytes
-       text_bytes, vir_bytes data_addr, vir_bytes data_bytes, vir_bytes
-       stk_bytes, phys_bytes tot_bytes, vir_bytes *stack_top, int is_elf);
-
-/*===========================================================================*
- *                             exec_newmem                                  *
- *===========================================================================*/
-int do_exec_newmem(message *msg)
-{
-       int r, proc_e, proc_n;
-       vir_bytes stack_top;
-       vir_clicks tc, dc, sc, totc, dvir, s_vir;
-       struct vmproc *vmp;
-       char *ptr;
-       struct exec_newmem args;
-
-       SANITYCHECK(SCL_FUNCTIONS);
-
-       proc_e= msg->VMEN_ENDPOINT;
-       if (vm_isokendpt(proc_e, &proc_n) != OK)
-       {
-               printf("VM: exec_newmem: bad endpoint %d from %d\n",
-                       proc_e, msg->m_source);
-               return ESRCH;
-       }
-       vmp= &vmproc[proc_n];
-       ptr= msg->VMEN_ARGSPTR;
-
-       if(msg->VMEN_ARGSSIZE != sizeof(args)) {
-               printf("VM: exec_newmem: args size %d != %u\n",
-                       msg->VMEN_ARGSSIZE, sizeof(args));
-               return EINVAL;
-       }
-SANITYCHECK(SCL_DETAIL);
-
-       r= sys_datacopy(msg->m_source, (vir_bytes)ptr,
-               SELF, (vir_bytes)&args, sizeof(args));
-       if (r != OK)
-               panic("exec_newmem: sys_datacopy failed: %d", r);
-
-       /* Minimum stack region (not preallocated)
-        * Stopgap for better rlimit-based stack size system
-        */
-       if(args.tot_bytes < MINSTACKREGION) {
-               args.tot_bytes = MINSTACKREGION;
-       }
-
-       /* Check to see if segment sizes are feasible. */
-       tc = (vir_clicks) (CLICK_CEIL(args.text_bytes) >> CLICK_SHIFT);
-       dc = (vir_clicks) (CLICK_CEIL(args.data_bytes) >> CLICK_SHIFT);
-       totc = (vir_clicks) (CLICK_CEIL(args.tot_bytes) >> CLICK_SHIFT);
-       sc = (vir_clicks) (CLICK_CEIL(args.args_bytes) >> CLICK_SHIFT);
-       if (dc >= totc) {
-               printf("VM: newmem: no stack?\n");
-               return(ENOEXEC); /* stack must be at least 1 click */
-       }
-
-       dvir = (args.sep_id ? 0 : tc);
-       s_vir = dvir + (totc - sc);
-       r = (dvir + dc > s_vir) ? ENOMEM : OK;
-       if (r != OK) {
-               printf("VM: newmem: no virtual space?\n");
-               return r;
-       }
-
-       /* Allocate new memory and release old memory.  Fix map and tell
-        * kernel.
-        */
-       r = new_mem(vmp, args.text_addr, args.text_bytes,
-               args.data_addr, args.data_bytes,
-               args.args_bytes, args.tot_bytes, &stack_top,
-               args.is_elf);
-       if (r != OK) {
-               printf("VM: newmem: new_mem failed\n");
-               return(r);
-       }
-
-       /* Save file identification to allow it to be shared. */
-       vmp->vm_ino = args.st_ino;
-       vmp->vm_dev = args.st_dev;
-       vmp->vm_ctime = args.enst_ctime;
-
-       /* set/clear separate I&D flag */
-       if (args.sep_id)
-               vmp->vm_flags |= VMF_SEPARATE;  
-       else
-               vmp->vm_flags &= ~VMF_SEPARATE;
-
-       msg->VMEN_STACK_TOP = (void *) stack_top;
-       msg->VMEN_FLAGS = 0;
-       msg->VMEN_FLAGS |= EXC_NM_RF_LOAD_TEXT;
-
-       return OK;
-}
-
-/*===========================================================================*
- *                             new_mem                                      *
- *===========================================================================*/
-static int new_mem(
-  struct vmproc *rmp,           /* process to get a new memory map */
-  vir_bytes text_addr,          /* text segement load address */
-  vir_bytes text_bytes,         /* text segment size in bytes */
-  vir_bytes data_addr,          /* data segment load address */
-  vir_bytes data_bytes,         /* size of data (incl bss) in bytes */
-  vir_bytes stk_bytes,          /* size of initial stack segment in bytes */
-  phys_bytes tot_bytes,         /* total memory to allocate, including gap */
-  vir_bytes *stack_top,         /* top of process stack */
-  int is_elf
-)
-{
-/* Allocate new memory and release the old memory.  Change the map and report
- * the new map to the kernel.  Zero the new core image's bss, gap and stack.
- */
-
-  vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
-  int r, hadpt = 0;
-  struct vmproc *vmpold = &vmproc[VMP_EXECTMP];
-  int ptok = 1;
-
-  SANITYCHECK(SCL_FUNCTIONS);
-
-  assert(rmp->vm_flags & VMF_HASPT);
-
-  /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,
-   * and stack occupies an integral number of clicks, starting at click
-   * boundary.  The data and bss parts are run together with no space.
-   */
-  text_clicks = (vir_clicks) (CLICK_CEIL(text_bytes) >> CLICK_SHIFT);
-  data_clicks = (vir_clicks) (CLICK_CEIL(data_bytes) >> CLICK_SHIFT);
-  stack_clicks = (vir_clicks) (CLICK_CEIL(stk_bytes) >> CLICK_SHIFT);
-  tot_clicks = (vir_clicks) (CLICK_CEIL(tot_bytes) >> CLICK_SHIFT);
-  gap_clicks = tot_clicks - data_clicks - stack_clicks;
-  if ( (int) gap_clicks < 0) {
-       printf("VM: new_mem: no gap?\n");
-       return(ENOMEM);
-  }
-
-
-  /* Keep previous process state for recovery; the sanity check functions
-   * know about the 'vmpold' slot, so the memory that the exec()ing
-   * process is still holding is referenced there.
-   *
-   * Throw away the old page table to avoid having two process slots
-   * using the same vm_pt.
-   * Just recreate it in the case that we have to revert.
-   */
-SANITYCHECK(SCL_DETAIL);
-  rmp->vm_flags &= ~VMF_HASPT;
-  pt_free(&rmp->vm_pt);
-
-  assert(!(vmpold->vm_flags & VMF_INUSE));
-  *vmpold = *rmp;      /* copy current state. */
-#if SANITYCHECKS
-  map_setparent(vmpold);
-#endif
-
-  region_init(&rmp->vm_regions_avl); /* exec()ing process regions thrown out. */
-  rmp->vm_region_top = 0;
-SANITYCHECK(SCL_DETAIL);
-
-  /* Build new process in current slot, without freeing old
-   * one. If it fails, revert.
-   */
-  SANITYCHECK(SCL_DETAIL);
-  if((r=pt_new(&rmp->vm_pt)) != OK) {
-    ptok = 0;
-    printf("exec_newmem: no new pagetable\n");
-  }
-
-  SANITYCHECK(SCL_DETAIL);
-  if(r != OK || (r=proc_new(rmp,
-        VM_PROCSTART,  /* where to start the process in the page table */
-        text_addr, /* text load address */
-        CLICK2ABS(text_clicks),/* how big is the text in bytes, page-aligned */
-        data_addr, /* data load address */
-        CLICK2ABS(data_clicks),/* how big is data+bss, page-aligned */
-        CLICK2ABS(stack_clicks),/* how big is stack, page-aligned */
-        CLICK2ABS(gap_clicks), /* how big is gap, page-aligned */
-        0,0,                   /* not preallocated */
-        VM_STACKTOP,           /* regular stack top */
-        0, is_elf, 1)) != OK) {
-    SANITYCHECK(SCL_DETAIL);
-    printf("VM: new_mem: failed\n");
-    if(ptok) {
-      rmp->vm_flags &= ~VMF_HASPT;
-      pt_free(&rmp->vm_pt);
-    }
-    *rmp = *vmpold;    /* undo. */
-    map_setparent(rmp);
-    clear_proc(vmpold);        /* disappear. */
-    SANITYCHECK(SCL_DETAIL);
-    if(hadpt) {
-      if(pt_new(&rmp->vm_pt) != OK) {
-       /* We secretly know that making a new pagetable
-        * in the same slot if one was there will never fail.
-        */
-       panic("new_mem: pt_new failed: %d", ENOMEM);
-      }
-      rmp->vm_flags |= VMF_HASPT;
-      SANITYCHECK(SCL_DETAIL);
-      if(map_writept(rmp) != OK) {
-       printf("VM: warning: exec undo failed\n");
-      }
-      SANITYCHECK(SCL_DETAIL);
-    }
-    return r;
-  }
-  SANITYCHECK(SCL_DETAIL);
-  /* new process is made; free and unreference
-   * page table and memory still held by exec()ing process.
-   */
-  SANITYCHECK(SCL_DETAIL);
-  free_proc(vmpold);
-  clear_proc(vmpold);  /* disappear. */
-  SANITYCHECK(SCL_DETAIL);
-  *stack_top = VM_STACKTOP;
-
-  SANITYCHECK(SCL_FUNCTIONS);
-
-  return(OK);
-}
-
 /*===========================================================================*
  *                             find_kernel_top                              *
  *===========================================================================*/
@@ -273,6 +52,21 @@ phys_bytes find_kernel_top(void)
        return CLICK2ABS(kernel_top);
 }
 
+void regular_segs(struct vmproc *vmp)
+{
+        int s;
+        memset(vmp->vm_arch.vm_seg, 0, sizeof(vmp->vm_arch.vm_seg));
+        vmp->vm_arch.vm_seg[T].mem_phys =
+               vmp->vm_arch.vm_seg[D].mem_phys = ABS2CLICK(VM_PROCSTART);
+        vmp->vm_arch.vm_seg[T].mem_len =
+               vmp->vm_arch.vm_seg[D].mem_len =
+               vmp->vm_arch.vm_seg[S].mem_len = ABS2CLICK(VM_DATATOP-VM_PROCSTART);
+        if((s=sys_newmap(vmp->vm_endpoint, vmp->vm_arch.vm_seg)) != OK)
+                panic("regular_segs: sys_newmap failed: %d", s);
+        if((s=pt_bind(&vmp->vm_pt, vmp)) != OK)
+                panic("regular_segs: pt_bind failed: %d", s);
+}
+
 /*===========================================================================*
  *                             proc_new                                     *
  *===========================================================================*/
index 202dc0ba4c1a4a59f0eb6dbc47ab0b6c1c10157f..247172bb91ca5fa1bc054e63826ef28f71b91a09 100644 (file)
@@ -27,6 +27,7 @@
 void free_proc(struct vmproc *vmp)
 {
        map_free_proc(vmp);
+       vmp->vm_heap = NULL;
        if(vmp->vm_flags & VMF_HASPT) {
                vmp->vm_flags &= ~VMF_HASPT;
                pt_free(&vmp->vm_pt);
@@ -135,6 +136,7 @@ int do_procctl(message *msg)
                        pt_new(&vmp->vm_pt);
                        vmp->vm_flags |= VMF_HASPT;
                        pt_bind(&vmp->vm_pt, vmp);
+                       regular_segs(vmp);
                        return OK;
                default:
                        return EINVAL;
index 765852acb7a8ade2a51d03ab0c1122049a795c9d..487f1eb4e12dd70c72d9afe1ec630ff78d04b524 100644 (file)
@@ -344,7 +344,6 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info)
        CALLMAP(VM_EXIT, do_exit);
        CALLMAP(VM_FORK, do_fork);
        CALLMAP(VM_BRK, do_brk);
-       CALLMAP(VM_EXEC_NEWMEM, do_exec_newmem);
        CALLMAP(VM_PUSH_SIG, do_push_sig);
        CALLMAP(VM_WILLEXIT, do_willexit);
        CALLMAP(VM_ADDDMA, do_adddma);
index 8bf843754585263045dbfffbe357103416ff0fb1..4b1141f995d79d28b8c866b232b53be1c44b7688 100644 (file)
@@ -93,7 +93,7 @@ int do_mmap(message *m)
                        len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE);
 
                vr = NULL;
-               if (m->VMM_ADDR) {
+               if (m->VMM_ADDR || (m->VMM_FLAGS & MAP_FIXED)) {
                        /* An address is given, first try at that address. */
                        addr = arch_vir2map(vmp, m->VMM_ADDR);
                        vr = map_page_region(vmp, addr, 0, len, MAP_NONE,
index 3168ce9af2678a2b15607b2cff9e38ea61c880ba..8cc9a2e3739e03f22a7cc50d2fa322a60e95a656 100644 (file)
@@ -65,6 +65,7 @@ int proc_new(struct vmproc *vmp, phys_bytes start, phys_bytes text_addr,
        phys_bytes stack, phys_bytes gap, phys_bytes text_here, phys_bytes
        data_here, vir_bytes stacktop, int prealloc_stack, int is_elf, int full);
 phys_bytes find_kernel_top(void);
+void regular_segs(struct vmproc *);
 
 /* break.c */
 int do_brk(message *msg);
index 37c076869de3075912cef5b6490412e90943e0df..50063a5e06f5f282ab5266dc484608142daf5ec5 100644 (file)
@@ -55,11 +55,6 @@ int do_push_sig(message *msg)
         sp -= sizeof(struct sigcontext)
                                  + 3 * sizeof(char *) + 2 * sizeof(int);
 
-        if ((r=adjust(vmp, vmp->vm_arch.vm_seg[D].mem_len, sp)) != OK) {
-               printf("VM: do_push_sig: adjust() failed: %d\n", r);
-               return r;
-       }
-
        return OK;
 }