summaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2019-06-11 09:57:14 -0400
committerRobert Morris <[email protected]>2019-06-11 09:57:14 -0400
commit5753553213df8f9de851adb68377db43faecb91f (patch)
tree3b629ff54897fca414146677532cb459a2ed11ba /exec.c
parent91ba81110acd3163f7de3580b677eece0c57f5e7 (diff)
downloadxv6-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.c149
1 files changed, 0 insertions, 149 deletions
diff --git a/exec.c b/exec.c
deleted file mode 100644
index c9af395..0000000
--- a/exec.c
+++ /dev/null
@@ -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;
-}