1 #include "inc.h" 2 #include <assert.h> 3 #include <sys/exec.h> 4 #include <libexec.h> 5 #include <machine/vmparam.h> 6 7 static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, 8 char *frame, int frame_len, vir_bytes ps_str); 9 static int exec_restart(int proc_e, int result, vir_bytes pc, vir_bytes ps_str); 10 static int read_seg(struct exec_info *execi, off_t off, 11 vir_bytes seg_addr, size_t seg_bytes); 12 13 /* Array of loaders for different object formats */ 14 static struct exec_loaders { 15 libexec_exec_loadfunc_t load_object; 16 } const exec_loaders[] = { 17 { libexec_load_elf }, 18 { NULL } 19 }; 20 21 int srv_execve(int proc_e, char *exec, size_t exec_len, char *progname, 22 char **argv, char **envp) 23 { 24 size_t frame_size = 0; /* Size of the new initial stack. */ 25 int argc = 0; /* Argument count. */ 26 int envc = 0; /* Environment count */ 27 char overflow = 0; /* No overflow yet. */ 28 char *frame; 29 struct ps_strings *psp; 30 int vsp = 0; /* (virtual) Stack pointer in new address space. */ 31 32 int r; 33 34 minix_stack_params(argv[0], argv, envp, &frame_size, &overflow, 35 &argc, &envc); 36 37 /* The party is off if there is an overflow. */ 38 if (overflow) { 39 errno = E2BIG; 40 return -1; 41 } 42 43 /* Allocate space for the stack frame. */ 44 if ((frame = (char *) sbrk(frame_size)) == (char *) -1) { 45 errno = E2BIG; 46 return -1; 47 } 48 49 minix_stack_fill(argv[0], argc, argv, envc, envp, frame_size, frame, 50 &vsp, &psp); 51 52 r = do_exec(proc_e, exec, exec_len, progname, frame, frame_size, 53 vsp + ((char *)psp - frame)); 54 55 /* Failure, return the memory used for the frame and exit. */ 56 (void) sbrk(-frame_size); 57 58 return r; 59 } 60 61 62 static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname, 63 char *frame, int frame_len, vir_bytes ps_str) 64 { 65 int r; 66 vir_bytes vsp; 67 struct exec_info execi; 68 int i; 69 70 memset(&execi, 0, sizeof(execi)); 71 72 execi.stack_high = minix_get_user_sp(); 73 execi.stack_size = DEFAULT_STACK_LIMIT; 74 execi.proc_e = proc_e; 75 execi.hdr = exec; 76 execi.filesize = execi.hdr_len = exec_len; 77 strncpy(execi.progname, progname, PROC_NAME_LEN-1); 78 execi.progname[PROC_NAME_LEN-1] = '\0'; 79 execi.frame_len = frame_len; 80 81 /* callback functions and data */ 82 execi.copymem = read_seg; 83 execi.clearproc = libexec_clearproc_vm_procctl; 84 execi.clearmem = libexec_clear_sys_memset; 85 execi.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared; 86 execi.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk; 87 execi.allocmem_ondemand = libexec_alloc_mmap_ondemand; 88 89 for(i = 0; exec_loaders[i].load_object != NULL; i++) { 90 r = (*exec_loaders[i].load_object)(&execi); 91 /* Loaded successfully, so no need to try other loaders */ 92 if (r == OK) break; 93 } 94 95 /* No exec loader could load the object */ 96 if (r != OK) { 97 printf("RS: do_exec: loading error %d\n", r); 98 return r; 99 } 100 101 /* Inform PM */ 102 if((r = libexec_pm_newexec(execi.proc_e, &execi)) != OK) 103 return r; 104 105 /* Patch up stack and copy it from RS to new core image. */ 106 vsp = execi.stack_high - frame_len; 107 r = sys_datacopy(SELF, (vir_bytes) frame, 108 proc_e, (vir_bytes) vsp, (phys_bytes)frame_len); 109 if (r != OK) { 110 printf("do_exec: copying out new stack failed: %d\n", r); 111 exec_restart(proc_e, r, execi.pc, ps_str); 112 return r; 113 } 114 115 return exec_restart(proc_e, OK, execi.pc, ps_str); 116 } 117 118 /*===========================================================================* 119 * exec_restart * 120 *===========================================================================*/ 121 static int exec_restart(int proc_e, int result, vir_bytes pc, vir_bytes ps_str) 122 { 123 int r; 124 message m; 125 126 memset(&m, 0, sizeof(m)); 127 m.m_type = PM_EXEC_RESTART; 128 m.m_rs_pm_exec_restart.endpt = proc_e; 129 m.m_rs_pm_exec_restart.result = result; 130 m.m_rs_pm_exec_restart.pc = pc; 131 m.m_rs_pm_exec_restart.ps_str = ps_str; 132 133 r = ipc_sendrec(PM_PROC_NR, &m); 134 if (r != OK) 135 return r; 136 137 return m.m_type; 138 } 139 140 /*===========================================================================* 141 * read_seg * 142 *===========================================================================*/ 143 static int read_seg( 144 struct exec_info *execi, /* various data needed for exec */ 145 off_t off, /* offset in file */ 146 vir_bytes seg_addr, /* address to load segment */ 147 size_t seg_bytes /* how much is to be transferred? */ 148 ) 149 { 150 /* 151 * The byte count on read is usually smaller than the segment count, because 152 * a segment is padded out to a click multiple, and the data segment is only 153 * partially initialized. 154 */ 155 156 int r; 157 158 if (off+seg_bytes > execi->hdr_len) return ENOEXEC; 159 if((r= sys_datacopy(SELF, ((vir_bytes)execi->hdr)+off, 160 execi->proc_e, seg_addr, seg_bytes)) != OK) { 161 printf("RS: exec read_seg: copy 0x%x bytes into %i at 0x%08lx failed: %i\n", 162 (int) seg_bytes, execi->proc_e, seg_addr, r); 163 } 164 return r; 165 } 166