diff options
author | Frans Kaashoek <[email protected]> | 2011-07-27 20:49:45 -0400 |
---|---|---|
committer | Frans Kaashoek <[email protected]> | 2011-07-27 20:49:45 -0400 |
commit | dccb915282854476ce47752df6631dcce3b8f661 (patch) | |
tree | a84aa8ed35618f99c3d7e8cdd466d22ae7bad597 /exec.c | |
parent | 9acdfe0d04f3fcf95c6e392e08afb45bdfe16c20 (diff) | |
parent | 13a96baefc0ff5d8262c4bc8c797bee4b157443c (diff) | |
download | xv6-labs-dccb915282854476ce47752df6631dcce3b8f661.tar.gz xv6-labs-dccb915282854476ce47752df6631dcce3b8f661.tar.bz2 xv6-labs-dccb915282854476ce47752df6631dcce3b8f661.zip |
Merge commit 'origin/master' into page
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 77 |
1 files changed, 33 insertions, 44 deletions
@@ -9,20 +9,18 @@ int exec(char *path, char **argv) { - char *mem, *s, *last; - int i, argc, arglen, len, off; - uint sz, sp, spoffset, argp; + char *s, *last; + int i, off; + uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; - pgdir = 0; - sz = 0; - if((ip = namei(path)) == 0) return -1; ilock(ip); + pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) @@ -30,10 +28,11 @@ exec(char *path, char **argv) if(elf.magic != ELF_MAGIC) goto bad; - if (!(pgdir = setupkvm())) + if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. + sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; @@ -41,49 +40,39 @@ exec(char *path, char **argv) continue; if(ph.memsz < ph.filesz) goto bad; - if (!allocuvm(pgdir, (char *)ph.va, ph.memsz)) + if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; - if(ph.va + ph.memsz > sz) - sz = ph.va + ph.memsz; - if (!loaduvm(pgdir, (char *)ph.va, ip, ph.offset, ph.filesz)) + if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); + ip = 0; - // Allocate and initialize stack at sz + // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); - sz += PGSIZE; // leave an invalid page - if (!allocuvm(pgdir, (char *)sz, PGSIZE)) + if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) goto bad; - mem = uva2ka(pgdir, (char *)sz); - spoffset = sz; - sz += PGSIZE; - - arglen = 0; - for(argc=0; argv[argc]; argc++) - arglen += strlen(argv[argc]) + 1; - arglen = (arglen+3) & ~3; + // Push argument strings, prepare rest of stack in ustack. sp = sz; - argp = sz - arglen - 4*(argc+1); - - // Copy argv strings and pointers to stack. - *(uint*)(mem+argp-spoffset + 4*argc) = 0; // argv[argc] - for(i=argc-1; i>=0; i--){ - len = strlen(argv[i]) + 1; - sp -= len; - memmove(mem+sp-spoffset, argv[i], len); - *(uint*)(mem+argp-spoffset + 4*i) = sp; // argv[i] + for(argc = 0; argv[argc]; argc++) { + if(argc >= MAXARG) + goto bad; + sp -= strlen(argv[argc]) + 1; + sp &= ~3; + if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) + goto bad; + ustack[3+argc] = sp; } + ustack[3+argc] = 0; - // Stack frame for main(argc, argv), below arguments. - sp = argp; - sp -= 4; - *(uint*)(mem+sp-spoffset) = argp; - sp -= 4; - *(uint*)(mem+sp-spoffset) = argc; - sp -= 4; - *(uint*)(mem+sp-spoffset) = 0xffffffff; // fake return pc + ustack[0] = 0xffffffff; // fake return PC + ustack[1] = argc; + ustack[2] = sp - (argc+1)*4; // argv pointer + + sp -= (3+argc+1) * 4; + if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) + goto bad; // Save program name for debugging. for(last=s=path; *s; s++) @@ -97,15 +86,15 @@ exec(char *path, char **argv) proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; - - switchuvm(proc); - + switchuvm(proc); freevm(oldpgdir); return 0; bad: - if (pgdir) freevm(pgdir); - iunlockput(ip); + if(pgdir) + freevm(pgdir); + if(ip) + iunlockput(ip); return -1; } |