1 #include "types.h" 2 #include "param.h" 3 #include "mmu.h" 4 #include "proc.h" 5 #include "defs.h" 6 #include "x86.h" 7 #include "elf.h" 8 9 int 10 exec(char *path, char **argv) 11 { 12 char *mem, *s, *last; 13 int i, argc, arglen, len, off; 14 uint sz, sp, spbottom, argp; 15 struct elfhdr elf; 16 struct inode *ip; 17 struct proghdr ph; 18 pde_t *pgdir, *oldpgdir; 19 20 pgdir = 0; 21 sz = 0; 22 23 if((ip = namei(path)) == 0) 24 return -1; 25 ilock(ip); 26 27 // Check ELF header 28 if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) 29 goto bad; 30 if(elf.magic != ELF_MAGIC) 31 goto bad; 32 33 if(!(pgdir = setupkvm())) 34 goto bad; 35 36 // Load program into memory. 37 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ 38 if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) 39 goto bad; 40 if(ph.type != ELF_PROG_LOAD) 41 continue; 42 if(ph.memsz < ph.filesz) 43 goto bad; 44 if(!(sz = allocuvm(pgdir, sz, ph.va + ph.memsz))) 45 goto bad; 46 if(!loaduvm(pgdir, (char *)ph.va, ip, ph.offset, ph.filesz)) 47 goto bad; 48 } 49 iunlockput(ip); 50 51 // Allocate and initialize stack at sz 52 sz = spbottom = PGROUNDUP(sz); 53 if(!(sz = allocuvm(pgdir, sz, sz + PGSIZE))) 54 goto bad; 55 mem = uva2ka(pgdir, (char *)spbottom); 56 57 arglen = 0; 58 for(argc=0; argv[argc]; argc++) 59 arglen += strlen(argv[argc]) + 1; 60 arglen = (arglen+3) & ~3; 61 62 sp = sz; 63 argp = sz - arglen - 4*(argc+1); 64 65 // Copy argv strings and pointers to stack. 66 *(uint*)(mem+argp-spbottom + 4*argc) = 0; // argv[argc] 67 for(i=argc-1; i>=0; i--){ 68 len = strlen(argv[i]) + 1; 69 sp -= len; 70 memmove(mem+sp-spbottom, argv[i], len); 71 *(uint*)(mem+argp-spbottom + 4*i) = sp; // argv[i] 72 } 73 74 // Stack frame for main(argc, argv), below arguments. 75 sp = argp; 76 sp -= 4; 77 *(uint*)(mem+sp-spbottom) = argp; 78 sp -= 4; 79 *(uint*)(mem+sp-spbottom) = argc; 80 sp -= 4; 81 *(uint*)(mem+sp-spbottom) = 0xffffffff; // fake return pc 82 83 // Save program name for debugging. 84 for(last=s=path; *s; s++) 85 if(*s == '/') 86 last = s+1; 87 safestrcpy(proc->name, last, sizeof(proc->name)); 88 89 // Commit to the user image. 90 oldpgdir = proc->pgdir; 91 proc->pgdir = pgdir; 92 proc->sz = sz; 93 proc->tf->eip = elf.entry; // main 94 proc->tf->esp = sp; 95 96 switchuvm(proc); 97 98 freevm(oldpgdir); 99 100 return 0; 101 102 bad: 103 if(pgdir) freevm(pgdir); 104 iunlockput(ip); 105 return -1; 106 } 107