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 // XXX rtm: what about the BSS? shouldn't there be some 52 // bzero()ing here? 53 54 // Allocate and initialize stack at sz 55 sz = spbottom = PGROUNDUP(sz); 56 if(!(sz = allocuvm(pgdir, sz, sz + PGSIZE))) 57 goto bad; 58 mem = uva2ka(pgdir, (char *)spbottom); 59 60 arglen = 0; 61 for(argc=0; argv[argc]; argc++) 62 arglen += strlen(argv[argc]) + 1; 63 arglen = (arglen+3) & ~3; 64 65 sp = sz; 66 argp = sz - arglen - 4*(argc+1); 67 68 // XXX rtm: does the following code work if the 69 // arguments &c do not fit in one page? 70 71 // Copy argv strings and pointers to stack. 72 *(uint*)(mem+argp-spbottom + 4*argc) = 0; // argv[argc] 73 for(i=argc-1; i>=0; i--){ 74 len = strlen(argv[i]) + 1; 75 sp -= len; 76 memmove(mem+sp-spbottom, argv[i], len); 77 *(uint*)(mem+argp-spbottom + 4*i) = sp; // argv[i] 78 } 79 80 // Stack frame for main(argc, argv), below arguments. 81 sp = argp; 82 sp -= 4; 83 *(uint*)(mem+sp-spbottom) = argp; 84 sp -= 4; 85 *(uint*)(mem+sp-spbottom) = argc; 86 sp -= 4; 87 *(uint*)(mem+sp-spbottom) = 0xffffffff; // fake return pc 88 89 // Save program name for debugging. 90 for(last=s=path; *s; s++) 91 if(*s == '/') 92 last = s+1; 93 safestrcpy(proc->name, last, sizeof(proc->name)); 94 95 // Commit to the user image. 96 oldpgdir = proc->pgdir; 97 proc->pgdir = pgdir; 98 proc->sz = sz; 99 proc->tf->eip = elf.entry; // main 100 proc->tf->esp = sp; 101 102 switchuvm(proc); 103 104 freevm(oldpgdir); 105 106 return 0; 107 108 bad: 109 if(pgdir) freevm(pgdir); 110 iunlockput(ip); 111 return -1; 112 } 113