Xv6 with picoc & Linkage editor
v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
|
00001 #include "types.h" 00002 #include "param.h" 00003 #include "memlayout.h" 00004 #include "mmu.h" 00005 #include "proc.h" 00006 #include "defs.h" 00007 #include "x86.h" 00008 #include "elf.h" 00009 00010 int 00011 exec(char *path, char **argv) 00012 { 00013 char *s, *last; 00014 int i, off; 00015 uint argc, sz, sp, ustack[3+MAXARG+1]; 00016 struct elfhdr elf; 00017 struct inode *ip; 00018 struct proghdr ph; 00019 pde_t *pgdir, *oldpgdir; 00020 00021 if((ip = namei(path)) == 0) 00022 return -1; 00023 ilock(ip); 00024 pgdir = 0; 00025 00026 // Check ELF header 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 if((pgdir = setupkvm(kalloc)) == 0) 00033 goto bad; 00034 00035 // Load program into memory. 00036 sz = 0; 00037 for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ 00038 if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) 00039 goto bad; 00040 if(ph.type != ELF_PROG_LOAD) 00041 continue; 00042 if(ph.memsz < ph.filesz) 00043 goto bad; 00044 if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) 00045 goto bad; 00046 if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) 00047 goto bad; 00048 } 00049 iunlockput(ip); 00050 ip = 0; 00051 00052 // Allocate two pages at the next page boundary. 00053 // Make the first inaccessible. Use the second as the user stack. 00054 sz = PGROUNDUP(sz); 00055 if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) 00056 goto bad; 00057 clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); 00058 sp = sz; 00059 00060 // Push argument strings, prepare rest of stack in ustack. 00061 for(argc = 0; argv[argc]; argc++) { 00062 if(argc >= MAXARG) 00063 goto bad; 00064 sp = (sp - (strlen(argv[argc]) + 1)) & ~3; 00065 if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) 00066 goto bad; 00067 ustack[3+argc] = sp; 00068 } 00069 ustack[3+argc] = 0; 00070 00071 ustack[0] = 0xffffffff; // fake return PC 00072 ustack[1] = argc; 00073 ustack[2] = sp - (argc+1)*4; // argv pointer 00074 00075 sp -= (3+argc+1) * 4; 00076 if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) 00077 goto bad; 00078 00079 // Save program name for debugging. 00080 for(last=s=path; *s; s++) 00081 if(*s == '/') 00082 last = s+1; 00083 safestrcpy(proc->name, last, sizeof(proc->name)); 00084 00085 // Commit to the user image. 00086 oldpgdir = proc->pgdir; 00087 proc->pgdir = pgdir; 00088 proc->sz = sz; 00089 proc->tf->eip = elf.entry; // main 00090 proc->tf->esp = sp; 00091 switchuvm(proc); 00092 freevm(oldpgdir); 00093 return 0; 00094 00095 bad: 00096 if(pgdir) 00097 freevm(pgdir); 00098 if(ip) 00099 iunlockput(ip); 00100 return -1; 00101 }