exec compiles but argstr() doesn't work yet

This commit is contained in:
Robert Morris 2019-05-31 12:43:20 -04:00
parent 5d34fa2a48
commit 7fd1f1eb0a
8 changed files with 207 additions and 69 deletions

74
exec.c
View file

@ -1,14 +1,13 @@
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "riscv.h"
#include "proc.h"
#include "defs.h"
#include "traps.h"
#include "msr.h"
#include "x86.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)
{
@ -18,9 +17,11 @@ exec(char *path, char **argv)
struct elfhdr elf;
struct inode *ip;
struct proghdr ph;
pde_t *pgdir, *oldpgdir;
pagetable_t pagetable = 0, oldpagetable;
struct proc *p = myproc();
uint64 oldsz = p->sz;
printf("EXEC\n");
begin_op();
@ -29,7 +30,6 @@ exec(char *path, char **argv)
return -1;
}
ilock(ip);
pgdir = 0;
// Check ELF header
if(readi(ip, (char*)&elf, 0, sizeof(elf)) != sizeof(elf))
@ -37,7 +37,7 @@ exec(char *path, char **argv)
if(elf.magic != ELF_MAGIC)
goto bad;
if((pgdir = setupkvm()) == 0)
if((pagetable = proc_pagetable(p)) == 0)
goto bad;
// Load program into memory.
@ -51,11 +51,11 @@ exec(char *path, char **argv)
goto bad;
if(ph.vaddr + ph.memsz < ph.vaddr)
goto bad;
if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0)
if((sz = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz)) == 0)
goto bad;
if(ph.vaddr % PGSIZE != 0)
goto bad;
if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0)
if(loadseg(pagetable, ph.vaddr, ip, ph.off, ph.filesz) < 0)
goto bad;
}
iunlockput(ip);
@ -63,11 +63,10 @@ exec(char *path, char **argv)
ip = 0;
// Allocate two pages at the next page boundary.
// Make the first inaccessible. Use the second as the user stack.
// Use the second as the user stack.
sz = PGROUNDUP(sz);
if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0)
if((sz = uvmalloc(pagetable, sz, sz + 2*PGSIZE)) == 0)
goto bad;
clearpteu(pgdir, (char*)(sz - 2*PGSIZE));
sp = sz;
// Push argument strings, prepare rest of stack in ustack.
@ -75,7 +74,7 @@ exec(char *path, char **argv)
if(argc >= MAXARG)
goto bad;
sp = (sp - (strlen(argv[argc]) + 1)) & ~(sizeof(uint64)-1);
if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
if(copyout(pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0)
goto bad;
ustack[3+argc] = sp;
}
@ -85,11 +84,12 @@ exec(char *path, char **argv)
ustack[1] = argc;
ustack[2] = sp - (argc+1)*sizeof(uint64); // argv pointer
p->sf->rdi = argc;
p->sf->rsi = sp - (argc+1)*sizeof(uint64);
// arguments to user main(argc, argv)
p->tf->a0 = argc;
p->tf->a1 = sp - (argc+1)*sizeof(uint64);
sp -= (3+argc+1) * sizeof(uint64);
if(copyout(pgdir, sp, ustack, (3+argc+1)*sizeof(uint64)) < 0)
if(copyout(pagetable, sp, (char *)ustack, (3+argc+1)*sizeof(uint64)) < 0)
goto bad;
// Save program name for debugging.
@ -99,21 +99,47 @@ exec(char *path, char **argv)
safestrcpy(p->name, last, sizeof(p->name));
// Commit to the user image.
oldpgdir = p->pgdir;
p->pgdir = pgdir;
oldpagetable = p->pagetable;
p->pagetable = pagetable;
p->sz = sz;
p->sf->rcx = elf.entry; // main
p->sf->rsp = sp;
switchuvm(p);
freevm(oldpgdir, oldsz);
p->tf->epc = elf.entry; // initial program counter = main
p->tf->sp = sp; // initial stack pointer
proc_freepagetable(oldpagetable, oldsz);
return 0;
bad:
if(pgdir)
freevm(pgdir, sz);
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;
pte_t *pte;
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, (char *)pa, offset+i, n) != n)
return -1;
}
return 0;
}