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