提交 629c1fe7 创建 作者: rsc's avatar rsc

Edit exec.

Do not commit to new memory image until nothing can go wrong, avoiding bad2 case. Be sure to allocate enough stack space for argv. Load executable before initializing stack, to keep ELF loops together. Make argv loop clearer.
上级 e79b1659
#include "types.h" #include "types.h"
#include "stat.h"
#include "param.h" #include "param.h"
#include "mmu.h" #include "mmu.h"
#include "proc.h" #include "proc.h"
#include "defs.h" #include "defs.h"
#include "x86.h" #include "x86.h"
#include "traps.h"
#include "syscall.h"
#include "spinlock.h"
#include "buf.h"
#include "fs.h" #include "fs.h"
#include "fsvar.h"
#include "elf.h" #include "elf.h"
#include "file.h"
#include "fcntl.h"
int int
exec(char *path, char **argv) exec(char *path, char **argv)
{ {
uint sz, sp, p1, p2; char *mem, *s, *last;
int i, nargs, argbytes, len, off; int i, argc, arglen, len, off;
struct inode *ip; uint sz, sp, argp;
struct elfhdr elf; struct elfhdr elf;
struct inode *ip;
struct proghdr ph; struct proghdr ph;
char *mem;
char *s, *last;
sz = 0;
mem = 0;
if((ip = namei(path)) == 0) if((ip = namei(path)) == 0)
return -1; return -1;
ilock(ip); ilock(ip);
// Compute memory size of new process.
mem = 0;
sz = 0;
// Program segments.
if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf))
goto bad; goto bad;
if(elf.magic != ELF_MAGIC) if(elf.magic != ELF_MAGIC)
goto bad; goto bad;
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
goto bad; goto bad;
...@@ -48,77 +39,73 @@ exec(char *path, char **argv) ...@@ -48,77 +39,73 @@ exec(char *path, char **argv)
goto bad; goto bad;
sz += ph.memsz; sz += ph.memsz;
} }
sz += 4096 - (sz % 4096); // Arguments.
sz += 4096; arglen = 0;
for(argc=0; argv[argc]; argc++)
arglen += strlen(argv[i]) + 1;
arglen = (arglen+3) & ~3;
sz += arglen + 4*(argc+1);
// Stack.
sz += PAGE;
// Allocate program memory.
sz = (sz+PAGE-1) & ~(PAGE-1);
mem = kalloc(sz); mem = kalloc(sz);
if(mem == 0) if(mem == 0)
goto bad; goto bad;
memset(mem, 0, sz); memset(mem, 0, sz);
argbytes = 0; // Load program into memory.
for(i = 0; argv[i]; i++){ for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
len = strlen(argv[i]); if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
argbytes += len + 1; goto bad;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.va + ph.memsz > sz)
goto bad;
if(readi(ip, mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
goto bad;
memset(mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
} }
nargs = i; iunlockput(ip);
// argn\0 // Initialize stack.
// ... sp = sz;
// arg0\0 argp = sz - arglen;
// 0
// ptr to argn // Copy argv strings and pointers to stack.
// ... *(uint*)(mem+argp + 4*argc) = 0; // argv[argc]
// 12: ptr to arg0 for(i=argc-1; i>=0; i--){
// 8: argv (points to ptr to arg0) len = strlen(argv[i]) + 1;
// 4: argc sp -= len;
// 0: fake return pc memmove(mem+sp, argv[i], len);
sp = sz - argbytes - (nargs+1)*4 - 4 - 4 - 4; *(uint*)(mem+argp + 4*i) = sp; // argv[i]
*(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++){
len = strlen(argv[i]);
memmove(mem + p2, argv[i], len + 1);
*(uint*)(mem + p1) = p2;
p1 += 4;
p2 += len + 1;
} }
*(uint*)(mem + p1) = 0;
// Save name for debugging. // Stack frame for main(argc, argv), below arguments.
sp = argp;
sp -= 4;
*(uint*)(mem+sp) = argp;
sp -= 4;
*(uint*)(mem+sp) = argc;
sp -= 4;
*(uint*)(mem+sp) = 0xffffffff; // fake return pc
// Save program name for debugging.
for(last=s=path; *s; s++) for(last=s=path; *s; s++)
if(*s == '/') if(*s == '/')
last = s+1; last = s+1;
safestrcpy(cp->name, last, sizeof(cp->name)); safestrcpy(cp->name, last, sizeof(cp->name));
// commit to the new image. // Commit to the new image.
kfree(cp->mem, cp->sz); kfree(cp->mem, cp->sz);
cp->sz = sz;
cp->mem = mem; cp->mem = mem;
mem = 0; cp->sz = sz;
cp->tf->eip = elf.entry; // main
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
goto bad2;
if(ph.type != ELF_PROG_LOAD)
continue;
if(ph.va + ph.memsz > sz)
goto bad2;
if(readi(ip, cp->mem + ph.va, ph.offset, ph.filesz) != ph.filesz)
goto bad2;
memset(cp->mem + ph.va + ph.filesz, 0, ph.memsz - ph.filesz);
}
iunlockput(ip);
cp->tf->eip = elf.entry;
cp->tf->esp = sp; cp->tf->esp = sp;
setupsegs(cp); setupsegs(cp);
return 0; return 0;
bad: bad:
...@@ -126,9 +113,4 @@ exec(char *path, char **argv) ...@@ -126,9 +113,4 @@ exec(char *path, char **argv)
kfree(mem, sz); kfree(mem, sz);
iunlockput(ip); iunlockput(ip);
return -1; return -1;
bad2:
iunlockput(ip);
proc_exit();
return 0;
} }
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论