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
exec.c
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 }
 All Data Structures