From 8455980b27a57e9c51693a4acbe91b820f4ab319 Mon Sep 17 00:00:00 2001 From: rtm Date: Fri, 28 Jul 2006 22:33:07 +0000 Subject: [PATCH] exec arguments --- Makefile | 10 +++++--- Notes | 2 ++ echo.c | 14 +++++++++++ mkfs.c | 5 ---- syscall.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++------ userfs.c | 3 ++- usertests.c | 2 +- 7 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 echo.c diff --git a/Makefile b/Makefile index d45bc6f..d405284 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,10 @@ usertests : usertests.o $(ULIB) $(LD) -N -e main -Ttext 0 -o usertests usertests.o $(ULIB) $(OBJDUMP) -S usertests > usertests.asm +echo : echo.o $(ULIB) + $(LD) -N -e main -Ttext 0 -o echo echo.o $(ULIB) + $(OBJDUMP) -S echo > echo.asm + userfs : userfs.o $(ULIB) $(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB) $(OBJDUMP) -S userfs > userfs.asm @@ -73,12 +77,12 @@ userfs : userfs.o $(ULIB) mkfs : mkfs.c fs.h cc -o mkfs mkfs.c -fs.img : mkfs usertests - ./mkfs fs.img usertests +fs.img : mkfs usertests echo + ./mkfs fs.img usertests echo -include *.d clean : rm -f *.o *.d *.asm vectors.S parport.out \ bootblock kernel xv6.img user1 userfs usertests \ - fs.img mkfs + fs.img mkfs echo diff --git a/Notes b/Notes index f0955b8..22658fc 100644 --- a/Notes +++ b/Notes @@ -161,3 +161,5 @@ need to lock bufs in bio between bread and brelse test 14-character file names and file arguments longer than 14 and directories longer than one sector + +kalloc() can return 0; do callers handle this right? diff --git a/echo.c b/echo.c new file mode 100644 index 0000000..89e19a9 --- /dev/null +++ b/echo.c @@ -0,0 +1,14 @@ +#include "user.h" + +int +main(int argc, char *argv[]) +{ + int i; + + for(i = 0; i < argc; i++){ + puts(argv[i]); + puts(" "); + } + puts("\n"); + exit(); +} diff --git a/mkfs.c b/mkfs.c index ae66dfd..1022adf 100644 --- a/mkfs.c +++ b/mkfs.c @@ -144,11 +144,6 @@ winode(uint inum, struct dinode *ip) dip = ((struct dinode *) buf) + (inum % IPB); *dip = *ip; wsect(bn, buf); - printf("wi %d size %d addrs %d %d...\n", - inum, - xint(dip->size), - xint(dip->addrs[0]), - xint(dip->addrs[1])); } void diff --git a/syscall.c b/syscall.c index a855774..ab9dd17 100644 --- a/syscall.c +++ b/syscall.c @@ -58,17 +58,20 @@ fetcharg(int argno, void *ip) return fetchint(curproc[cpu()], esp + 4 + 4*argno, ip); } -// check that an entire string is valid in user space +// check that an entire string is valid in user space. +// returns the length, not including null, or -1. int checkstring(uint s) { char c; + int len = 0; while(1){ if(fetchbyte(curproc[cpu()], s, &c) < 0) return -1; if(c == '\0') - return 0; + return len; + len++; s++; } } @@ -244,14 +247,17 @@ int sys_exec(void) { struct proc *cp = curproc[cpu()]; - uint arg0, sz; - int i; + uint arg0, arg1, sz=0, ap, sp, p1, p2; + int i, nargs, argbytes, len; struct inode *ip; struct elfhdr elf; struct proghdr ph; + char *mem = 0; if(fetcharg(0, &arg0) < 0) return -1; + if(fetcharg(1, &arg1) < 0) + return -1; if(checkstring(arg0) < 0) return -1; ip = namei(cp->mem + arg0); @@ -278,14 +284,62 @@ sys_exec(void) sz += 4096 - (sz % 4096); sz += 4096; + mem = kalloc(sz); + if(mem == 0) + goto bad; + memset(mem, 0, sz); + + // arg1 is a pointer to an array of pointers to string. + nargs = 0; + argbytes = 0; + for(i = 0; ; i++){ + if(fetchint(cp, arg1 + 4*i, &ap) < 0) + goto bad; + if(ap == 0) + break; + len = checkstring(ap); + if(len < 0) + goto bad; + nargs++; + argbytes += len + 1; + } + + // argn\0 + // ... + // arg0\0 + // 0 + // ptr to argn + // ... + // 12: ptr to arg0 + // 8: argv (points to ptr to arg0) + // 4: argc + // 0: fake return pc + sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4; + *(uint*)(mem + sp) = 0xffffffff; + *(uint*)(mem + sp + 4) = nargs; + *(uint*)(mem + sp + 8) = (uint)(sp + 12); + + p1 = sp + 12; + p2 = sp + 12 + (nargs + 1) * 4; + for(i = 0; i < nargs; i++){ + fetchint(cp, arg1 + 4*i, &ap); + len = checkstring(ap); + memmove(mem + p2, cp->mem + ap, len + 1); + *(uint*)(mem + p1) = p2; + p1 += 4; + p2 += len + 1; + } + *(uint*)(mem + p1) = 0; + // commit to the new image. kfree(cp->mem, cp->sz); cp->sz = sz; - cp->mem = kalloc(cp->sz); + cp->mem = mem; + mem = 0; for(i = 0; i < elf.phnum; i++){ if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph)) - goto bad; + goto bad2; if(ph.type != ELF_PROG_LOAD) continue; if(ph.va + ph.memsz > sz) @@ -298,13 +352,15 @@ sys_exec(void) iput(ip); cp->tf->eip = elf.entry; - cp->tf->esp = cp->sz; + cp->tf->esp = sp; setupsegs(cp); return 0; bad: cprintf("exec failed early\n"); + if(mem) + kfree(mem, sz); iput(ip); return -1; diff --git a/userfs.c b/userfs.c index aad9326..d3a4923 100644 --- a/userfs.c +++ b/userfs.c @@ -3,12 +3,13 @@ // file system tests char buf[1024]; +char *args[] = { "echo", "hello", "goodbye", 0 }; int main(void) { puts("userfs running\n"); block(); - exec("usertests"); + exec("echo", args); return 0; } diff --git a/usertests.c b/usertests.c index 370054b..cba362f 100644 --- a/usertests.c +++ b/usertests.c @@ -115,7 +115,7 @@ exitwait(void) } int -main(void) +main(int argc, char *argv[]) { puts("usertests starting\n");