exec arguments

This commit is contained in:
rtm 2006-07-28 22:33:07 +00:00
parent c59361f143
commit 8455980b27
7 changed files with 89 additions and 17 deletions

View file

@ -66,6 +66,10 @@ usertests : usertests.o $(ULIB)
$(LD) -N -e main -Ttext 0 -o usertests usertests.o $(ULIB) $(LD) -N -e main -Ttext 0 -o usertests usertests.o $(ULIB)
$(OBJDUMP) -S usertests > usertests.asm $(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) userfs : userfs.o $(ULIB)
$(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB) $(LD) -N -e main -Ttext 0 -o userfs userfs.o $(ULIB)
$(OBJDUMP) -S userfs > userfs.asm $(OBJDUMP) -S userfs > userfs.asm
@ -73,12 +77,12 @@ userfs : userfs.o $(ULIB)
mkfs : mkfs.c fs.h mkfs : mkfs.c fs.h
cc -o mkfs mkfs.c cc -o mkfs mkfs.c
fs.img : mkfs usertests fs.img : mkfs usertests echo
./mkfs fs.img usertests ./mkfs fs.img usertests echo
-include *.d -include *.d
clean : clean :
rm -f *.o *.d *.asm vectors.S parport.out \ rm -f *.o *.d *.asm vectors.S parport.out \
bootblock kernel xv6.img user1 userfs usertests \ bootblock kernel xv6.img user1 userfs usertests \
fs.img mkfs fs.img mkfs echo

2
Notes
View file

@ -161,3 +161,5 @@ need to lock bufs in bio between bread and brelse
test 14-character file names test 14-character file names
and file arguments longer than 14 and file arguments longer than 14
and directories longer than one sector and directories longer than one sector
kalloc() can return 0; do callers handle this right?

14
echo.c Normal file
View file

@ -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();
}

5
mkfs.c
View file

@ -144,11 +144,6 @@ winode(uint inum, struct dinode *ip)
dip = ((struct dinode *) buf) + (inum % IPB); dip = ((struct dinode *) buf) + (inum % IPB);
*dip = *ip; *dip = *ip;
wsect(bn, buf); 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 void

View file

@ -58,17 +58,20 @@ fetcharg(int argno, void *ip)
return fetchint(curproc[cpu()], esp + 4 + 4*argno, 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 int
checkstring(uint s) checkstring(uint s)
{ {
char c; char c;
int len = 0;
while(1){ while(1){
if(fetchbyte(curproc[cpu()], s, &c) < 0) if(fetchbyte(curproc[cpu()], s, &c) < 0)
return -1; return -1;
if(c == '\0') if(c == '\0')
return 0; return len;
len++;
s++; s++;
} }
} }
@ -244,14 +247,17 @@ int
sys_exec(void) sys_exec(void)
{ {
struct proc *cp = curproc[cpu()]; struct proc *cp = curproc[cpu()];
uint arg0, sz; uint arg0, arg1, sz=0, ap, sp, p1, p2;
int i; int i, nargs, argbytes, len;
struct inode *ip; struct inode *ip;
struct elfhdr elf; struct elfhdr elf;
struct proghdr ph; struct proghdr ph;
char *mem = 0;
if(fetcharg(0, &arg0) < 0) if(fetcharg(0, &arg0) < 0)
return -1; return -1;
if(fetcharg(1, &arg1) < 0)
return -1;
if(checkstring(arg0) < 0) if(checkstring(arg0) < 0)
return -1; return -1;
ip = namei(cp->mem + arg0); ip = namei(cp->mem + arg0);
@ -278,14 +284,62 @@ sys_exec(void)
sz += 4096 - (sz % 4096); sz += 4096 - (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. // commit to the new image.
kfree(cp->mem, cp->sz); kfree(cp->mem, cp->sz);
cp->sz = sz; cp->sz = sz;
cp->mem = kalloc(cp->sz); cp->mem = mem;
mem = 0;
for(i = 0; i < elf.phnum; i++){ for(i = 0; i < elf.phnum; i++){
if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph)) if(readi(ip, &ph, elf.phoff + i * sizeof(ph), sizeof(ph)) != sizeof(ph))
goto bad; goto bad2;
if(ph.type != ELF_PROG_LOAD) if(ph.type != ELF_PROG_LOAD)
continue; continue;
if(ph.va + ph.memsz > sz) if(ph.va + ph.memsz > sz)
@ -298,13 +352,15 @@ sys_exec(void)
iput(ip); iput(ip);
cp->tf->eip = elf.entry; cp->tf->eip = elf.entry;
cp->tf->esp = cp->sz; cp->tf->esp = sp;
setupsegs(cp); setupsegs(cp);
return 0; return 0;
bad: bad:
cprintf("exec failed early\n"); cprintf("exec failed early\n");
if(mem)
kfree(mem, sz);
iput(ip); iput(ip);
return -1; return -1;

View file

@ -3,12 +3,13 @@
// file system tests // file system tests
char buf[1024]; char buf[1024];
char *args[] = { "echo", "hello", "goodbye", 0 };
int int
main(void) main(void)
{ {
puts("userfs running\n"); puts("userfs running\n");
block(); block();
exec("usertests"); exec("echo", args);
return 0; return 0;
} }

View file

@ -115,7 +115,7 @@ exitwait(void)
} }
int int
main(void) main(int argc, char *argv[])
{ {
puts("usertests starting\n"); puts("usertests starting\n");