Mercurial > hg > Members > anatofuz > CbC_xv6
view src/exec.c @ 94:d876c9a65239 default tip
impl mac os target
author | anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 23 Oct 2019 14:31:38 +0900 |
parents | 397e74cbf14e |
children |
line wrap: on
line source
#include "types.h" #include "param.h" #include "defs.h" #include "memlayout.h" #include "mmu.h" #include "proc.h" #include "elf.h" #include "arm.h" // load a user program for execution int exec (char *path, char **argv) { struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir = 0; pde_t *oldpgdir; char *s; char *last; int i; int off; uint argc; uint sz; uint sp; uint ustack[3 + MAXARG + 1]; if ((ip = namei(path)) == 0) { return -1; } ilock(ip); // Check ELF header if (readi(ip, (char*) &elf, 0, sizeof(elf)) < sizeof(elf)) { goto bad; } if (elf.magic != ELF_MAGIC) { goto bad; } if ((pgdir = kpt_alloc()) == 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, (char*) &ph, off, sizeof(ph)) != sizeof(ph)) { goto bad; } if (ph.type != ELF_PROG_LOAD) { continue; } if (ph.memsz < ph.filesz) { goto bad; } if ((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) { goto bad; } if (loaduvm(pgdir, (char*) ph.vaddr, ip, ph.off, ph.filesz) < 0) { goto bad; } } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = align_up (sz, PTE_SZ); if ((sz = allocuvm(pgdir, sz, sz + 2 * PTE_SZ)) == 0) { goto bad; } clearpteu(pgdir, (char*) (sz - 2 * PTE_SZ)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for (argc = 0; argv[argc]; argc++) { if (argc >= MAXARG) { goto bad; } sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if (copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) { goto bad; } ustack[argc] = sp; } ustack[argc] = 0; // in ARM, parameters are passed in r0 and r1 proc->tf->r0 = argc; proc->tf->r1 = sp - (argc + 1) * 4; sp -= (argc + 1) * 4; if (copyout(pgdir, sp, ustack, (argc + 1) * 4) < 0) { goto bad; } // Save program name for debugging. for (last = s = path; *s; s++) { if (*s == '/') { last = s + 1; } } safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->pc = elf.entry; proc->tf->sp_usr = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if (pgdir) { freevm(pgdir); } if (ip) { iunlockput(ip); } return -1; }