diff --git a/exec.c b/exec.c index 4da73b2..9f06605 100644 --- a/exec.c +++ b/exec.c @@ -1,44 +1,35 @@ #include "types.h" -#include "stat.h" #include "param.h" #include "mmu.h" #include "proc.h" #include "defs.h" #include "x86.h" -#include "traps.h" -#include "syscall.h" -#include "spinlock.h" -#include "buf.h" #include "fs.h" -#include "fsvar.h" #include "elf.h" -#include "file.h" -#include "fcntl.h" int exec(char *path, char **argv) { - uint sz, sp, p1, p2; - int i, nargs, argbytes, len, off; - struct inode *ip; + char *mem, *s, *last; + int i, argc, arglen, len, off; + uint sz, sp, argp; struct elfhdr elf; + struct inode *ip; struct proghdr ph; - char *mem; - char *s, *last; - - sz = 0; - mem = 0; if((ip = namei(path)) == 0) return -1; ilock(ip); + // Compute memory size of new process. + mem = 0; + sz = 0; + + // Program segments. if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; - if(elf.magic != ELF_MAGIC) goto bad; - for(i=0, off=elf.phoff; i sz) + goto bad; + if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz) + goto bad; + memset(mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz); } - nargs = i; + iunlockput(ip); + + // Initialize stack. + sp = sz; + argp = sz - arglen; - // argn\0 - // ... - // arg0\0 - // 0 - // ptr to argn - // ... - // 12: ptr to arg0 - // 8: argv (points to ptr to arg0) - // 4: argc - // 0: fake return pc - sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4; - *(uint*)(mem + sp) = 0xffffffff; - *(uint*)(mem + sp + 4) = nargs; - *(uint*)(mem + sp + 8) = (uint)(sp + 12); - - p1 = sp + 12; - p2 = sp + 12 + (nargs + 1) * 4; - for(i = 0; i < nargs; i++){ - len = strlen(argv[i]); - memmove(mem + p2, argv[i], len + 1); - *(uint*)(mem + p1) = p2; - p1 += 4; - p2 += len + 1; + // Copy argv strings and pointers to stack. + *(uint*)(mem+argp + 4*argc) = 0; // argv[argc] + for(i=argc-1; i>=0; i--){ + len = strlen(argv[i]) + 1; + sp -= len; + memmove(mem+sp, argv[i], len); + *(uint*)(mem+argp + 4*i) = sp; // argv[i] } - *(uint*)(mem + p1) = 0; - // Save name for debugging. + // Stack frame for main(argc, argv), below arguments. + sp = argp; + sp -= 4; + *(uint*)(mem+sp) = argp; + sp -= 4; + *(uint*)(mem+sp) = argc; + sp -= 4; + *(uint*)(mem+sp) = 0xffffffff; // fake return pc + + // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(cp->name, last, sizeof(cp->name)); - // commit to the new image. + // Commit to the new image. kfree(cp->mem, cp->sz); - cp->sz = sz; cp->mem = mem; - mem = 0; - - for(i=0, off=elf.phoff; i sz) - goto bad2; - if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz) - goto bad2; - memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz); - } - iunlockput(ip); - - cp->tf->eip = elf.entry; + cp->sz = sz; + cp->tf->eip = elf.entry; // main cp->tf->esp = sp; setupsegs(cp); - return 0; bad: @@ -126,9 +113,4 @@ exec(char *path, char **argv) kfree(mem, sz); iunlockput(ip); return -1; - - bad2: - iunlockput(ip); - proc_exit(); - return 0; }