diff options
author | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-06-11 09:57:14 -0400 |
commit | 5753553213df8f9de851adb68377db43faecb91f (patch) | |
tree | 3b629ff54897fca414146677532cb459a2ed11ba /exec.c | |
parent | 91ba81110acd3163f7de3580b677eece0c57f5e7 (diff) | |
download | xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.gz xv6-labs-5753553213df8f9de851adb68377db43faecb91f.tar.bz2 xv6-labs-5753553213df8f9de851adb68377db43faecb91f.zip |
separate source into kernel/ user/ mkfs/
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 149 |
1 files changed, 0 insertions, 149 deletions
@@ -1,149 +0,0 @@ -#include "types.h" -#include "param.h" -#include "memlayout.h" -#include "riscv.h" -#include "proc.h" -#include "defs.h" -#include "elf.h" - -static int loadseg(pde_t *pgdir, uint64 addr, struct inode *ip, uint offset, uint sz); - -int -exec(char *path, char **argv) -{ - char *s, *last; - int i, off; - uint64 argc, sz, sp, ustack[MAXARG+1], stackbase; - struct elfhdr elf; - struct inode *ip; - struct proghdr ph; - pagetable_t pagetable = 0, oldpagetable; - struct proc *p = myproc(); - uint64 oldsz = p->sz; - - begin_op(); - - if((ip = namei(path)) == 0){ - end_op(); - return -1; - } - ilock(ip); - - // Check ELF header - if(readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf)) - goto bad; - if(elf.magic != ELF_MAGIC) - goto bad; - - if((pagetable = proc_pagetable(p)) == 0) - goto bad; - - // Load program into memory. - sz = 0; - for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ - if(readi(ip, 0, (uint64)&ph, off, sizeof(ph)) != sizeof(ph)) - goto bad; - if(ph.type != ELF_PROG_LOAD) - continue; - if(ph.memsz < ph.filesz) - goto bad; - if(ph.vaddr + ph.memsz < ph.vaddr) - goto bad; - if((sz = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz)) == 0) - goto bad; - if(ph.vaddr % PGSIZE != 0) - goto bad; - if(loadseg(pagetable, ph.vaddr, ip, ph.off, ph.filesz) < 0) - goto bad; - } - iunlockput(ip); - end_op(); - ip = 0; - - // Allocate two pages at the next page boundary. - // Use the second as the user stack. - sz = PGROUNDUP(sz); - if((sz = uvmalloc(pagetable, sz, sz + 2*PGSIZE)) == 0) - goto bad; - sp = sz; - stackbase = sp - PGSIZE; - - // Push argument strings, prepare rest of stack in ustack. - for(argc = 0; argv[argc]; argc++) { - if(argc >= MAXARG) - goto bad; - sp -= strlen(argv[argc]) + 1; - sp -= sp % 16; // riscv sp must be 16-byte aligned - if(sp < stackbase) - goto bad; - if(copyout(pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0) - goto bad; - ustack[argc] = sp; - } - ustack[argc] = 0; - - // push the array of argv[] pointers. - sp -= (argc+1) * sizeof(uint64); - sp -= sp % 16; - if(sp < stackbase) - goto bad; - if(copyout(pagetable, sp, (char *)ustack, (argc+1)*sizeof(uint64)) < 0) - goto bad; - - // arguments to user main(argc, argv) - // argc is returned via the system call return - // value, which goes in a0. - p->tf->a1 = sp; - - // Save program name for debugging. - for(last=s=path; *s; s++) - if(*s == '/') - last = s+1; - safestrcpy(p->name, last, sizeof(p->name)); - - // Commit to the user image. - oldpagetable = p->pagetable; - p->pagetable = pagetable; - p->sz = sz; - p->tf->epc = elf.entry; // initial program counter = main - p->tf->sp = sp; // initial stack pointer - proc_freepagetable(oldpagetable, oldsz); - return argc; // this ends up in a0, the first argument to main(argc, argv) - - bad: - if(pagetable) - proc_freepagetable(pagetable, sz); - if(ip){ - iunlockput(ip); - end_op(); - } - return -1; -} - -// Load a program segment into pagetable at virtual address va. -// va must be page-aligned -// and the pages from va to va+sz must already be mapped. -// Returns 0 on success, -1 on failure. -static int -loadseg(pagetable_t pagetable, uint64 va, struct inode *ip, uint offset, uint sz) -{ - uint i, n; - uint64 pa; - - if((va % PGSIZE) != 0) - panic("loadseg: va must be page aligned"); - - for(i = 0; i < sz; i += PGSIZE){ - pa = walkaddr(pagetable, va + i); - if(pa == 0) - panic("loadseg: address should exist"); - if(sz - i < PGSIZE) - n = sz - i; - else - n = PGSIZE; - if(readi(ip, 0, (uint64)pa, offset+i, n) != n) - return -1; - } - - return 0; -} |