exec compiles but argstr() doesn't work yet
This commit is contained in:
parent
5d34fa2a48
commit
7fd1f1eb0a
8 changed files with 207 additions and 69 deletions
74
exec.c
74
exec.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue