00001 #include "types.h"
00002 #include "param.h"
00003 #include "mmu.h"
00004 #include "proc.h"
00005 #include "defs.h"
00006 #include "x86.h"
00007 #include "elf.h"
00008
00009 int
00010 exec(char *path, char **argv)
00011 {
00012 char *mem, *s, *last;
00013 int i, argc, arglen, len, off;
00014 uint sz, sp, argp;
00015 struct elfhdr elf;
00016 struct inode *ip;
00017 struct proghdr ph;
00018
00019 mem = 0;
00020 sz = 0;
00021
00022 if((ip = namei(path)) == 0)
00023 return -1;
00024 ilock(ip);
00025
00026
00027 if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
00028 goto bad;
00029 if(elf.magic != ELF_MAGIC)
00030 goto bad;
00031
00032
00033
00034 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
00035 if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
00036 goto bad;
00037 if(ph.type != ELF_PROG_LOAD)
00038 continue;
00039 if(ph.memsz < ph.filesz)
00040 goto bad;
00041 sz += ph.memsz;
00042 }
00043
00044
00045 arglen = 0;
00046 for(argc=0; argv[argc]; argc++)
00047 arglen += strlen(argv[argc]) + 1;
00048 arglen = (arglen+3) & ~3;
00049 sz += arglen;
00050 sz += 4*(argc+1);
00051 sz += 4;
00052 sz += 4;
00053
00054
00055 sz += PAGE;
00056
00057
00058 sz = (sz+PAGE-1) & ~(PAGE-1);
00059 mem = kalloc(sz);
00060 if(mem == 0)
00061 goto bad;
00062 memset(mem, 0, sz);
00063
00064
00065 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
00066 if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
00067 goto bad;
00068 if(ph.type != ELF_PROG_LOAD)
00069 continue;
00070 if(ph.va + ph.memsz < ph.va || ph.va + ph.memsz > sz)
00071 goto bad;
00072 if(ph.memsz < ph.filesz)
00073 goto bad;
00074 if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
00075 goto bad;
00076 memset(mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
00077 }
00078 iunlockput(ip);
00079
00080
00081 sp = sz;
00082 argp = sz - arglen - 4*(argc+1);
00083
00084
00085 *(uint*)(mem+argp + 4*argc) = 0;
00086 for(i=argc-1; i>=0; i--){
00087 len = strlen(argv[i]) + 1;
00088 sp -= len;
00089 memmove(mem+sp, argv[i], len);
00090 *(uint*)(mem+argp + 4*i) = sp;
00091 }
00092
00093
00094 sp = argp;
00095 sp -= 4;
00096 *(uint*)(mem+sp) = argp;
00097 sp -= 4;
00098 *(uint*)(mem+sp) = argc;
00099 sp -= 4;
00100 *(uint*)(mem+sp) = 0xffffffff;
00101
00102
00103 for(last=s=path; *s; s++)
00104 if(*s == '/')
00105 last = s+1;
00106 safestrcpy(proc->name, last, sizeof(proc->name));
00107
00108
00109 kfree(proc->mem, proc->sz);
00110 proc->mem = mem;
00111 proc->sz = sz;
00112 proc->tf->eip = elf.entry;
00113 proc->tf->esp = sp;
00114 usegment();
00115 return 0;
00116
00117 bad:
00118 if(mem)
00119 kfree(mem, sz);
00120 iunlockput(ip);
00121 return -1;
00122 }