diff options
author | rsc <rsc> | 2007-08-21 19:22:08 +0000 |
---|---|---|
committer | rsc <rsc> | 2007-08-21 19:22:08 +0000 |
commit | f32f3638f4c34fbf2fc4398878e6304612bb3283 (patch) | |
tree | cabca9bf9ac8b1465b2c59e27e3dc8020c02e2be /exec.c | |
parent | 2d61a40b2059b9a198e7c4ff04c6ced88cb3ce65 (diff) | |
download | xv6-labs-f32f3638f4c34fbf2fc4398878e6304612bb3283.tar.gz xv6-labs-f32f3638f4c34fbf2fc4398878e6304612bb3283.tar.bz2 xv6-labs-f32f3638f4c34fbf2fc4398878e6304612bb3283.zip |
Various cleanup:
- Got rid of dummy proc[0]. Now proc[0] is init.
- Added initcode.S to exec /init, so that /init is
just a regular binary.
- Moved exec out of sysfile to exec.c
- Moved code dealing with fs guts (like struct inode)
from sysfile.c to fs.c. Code dealing with system call
arguments stays in sysfile.c
- Refactored directory routines in fs.c; should be simpler.
- Changed iget to return *unlocked* inode structure.
This solves the lookup-then-use race in namei
without introducing deadlocks.
It also enabled getting rid of the dummy proc[0].
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 136 |
1 files changed, 136 insertions, 0 deletions
@@ -0,0 +1,136 @@ +#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; + struct inode *ip; + struct elfhdr elf; + struct proghdr ph; + char *mem; + char *s, *last; + + sz = 0; + mem = 0; + + if((ip = namei(path)) == 0) + return -1; + + if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) + goto bad; + + if(elf.magic != ELF_MAGIC) + goto bad; + + for(i = 0; i < elf.phnum; i++){ + if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph), + sizeof(ph)) != sizeof(ph)) + goto bad; + if(ph.type != ELF_PROG_LOAD) + continue; + if(ph.memsz < ph.filesz) + goto bad; + sz += ph.memsz; + } + + sz += 4096 - (sz % 4096); + sz += 4096; + + mem = kalloc(sz); + if(mem == 0) + goto bad; + memset(mem, 0, sz); + + argbytes = 0; + for(i = 0; argv[i]; i++){ + len = strlen(argv[i]); + argbytes += len + 1; + } + nargs = i; + + // 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; + } + *(uint*)(mem + p1) = 0; + + // Save 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. + kfree(cp->mem, cp->sz); + cp->sz = sz; + cp->mem = mem; + mem = 0; + + for(i = 0; i < elf.phnum; i++){ + if(readi(ip, (char*)&ph, elf.phoff + i * sizeof(ph), + sizeof(ph)) != sizeof(ph)) + goto bad2; + if(ph.type != ELF_PROG_LOAD) + continue; + if(ph.va + ph.memsz > 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); + } + + iput(ip); + + cp->tf->eip = elf.entry; + cp->tf->esp = sp; + setupsegs(cp); + + return 0; + + bad: + if(mem) + kfree(mem, sz); + iput(ip); + return -1; + + bad2: + iput(ip); + proc_exit(); + return 0; +} |