// Look up and return the inode for a path name. // If parent != 0, return the inode for the parent and copy the final // path element into name, which must have room for DIRSIZ bytes. static struct inode* namex(char *path, int nameiparent, char *name) { struct inode *ip, *next; if(*path == '/') ip = iget(ROOTDEV, ROOTINO); else ip = idup(proc->cwd); while((path = skipelem(path, name)) != 0){ ilock(ip); if(ip->type != T_DIR){ iunlockput(ip); return 0; } if(nameiparent && *path == '\0'){ // Stop one level early. iunlock(ip); return ip; } if((next = dirlookup(ip, name, 0)) == 0){ iunlockput(ip); return 0; } iunlockput(ip); ip = next; } if(nameiparent){ iput(ip); return 0; } return ip; }
int kernel_unlink(char* path) { struct inode *ip, *dp; struct dirent de; char name[DIRSIZ]; uint off; // if(argstr(0, &path) < 0) // return -1; if((dp = nameiparent(path, name)) == 0) return -1; begin_trans(); ilock(dp); // Cannot unlink "." or "..". if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0) goto bad; if((ip = dirlookup(dp, name, &off)) == 0) goto bad; ilock(ip); if(ip->nlink < 1) panic("unlink: nlink < 1"); /* if(ip->type == T_DIR && !isdirempty(ip)){ iunlockput(ip); goto bad; } */ memset(&de, 0, sizeof(de)); if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) panic("unlink: writei"); if(ip->type == T_DIR){ dp->nlink--; iupdate(dp); } iunlockput(dp); ip->nlink--; iupdate(ip); iunlockput(ip); commit_trans(); return 0; bad: iunlockput(dp); commit_trans(); return -1; }
// Look up and return the inode for a path name. // If parent != 0, return the inode for the parent and copy the final // path element into name, which must have room for DIRSIZ bytes. static struct inode* namex(char *path, int nameiparent, char *name, int mode) // mode - 0-reference 1-dereference { struct inode *ip, *next; char buf[64]; if(*path == '/') ip = iget(ROOTDEV, ROOTINO); else ip = idup(proc->cwd); while((path = skipelem(path, name)) != 0){ ilock(ip); if(ip->type != T_DIR){ iunlockput(ip); return 0; } if(nameiparent && *path == '\0'){ // Stop one level early. iunlock(ip); return ip; } if((next = dirlookup(ip, name, 0)) == 0){ iunlockput(ip); return 0; } iunlockput(ip); if(mode || *path!='\0') { next= recursive_readlink(buf,next, 16, 0); } ip = next; } if(nameiparent){ iput(ip); return 0; } return ip; }
struct inode* kernel_create(char *path, short type, short major, short minor) { uint off; struct inode *ip, *dp; char name[DIRSIZ]; //cprintf("nameiparent path: %s\n",path); if((dp = nameiparent(path, name)) == 0) return 0; ilock(dp); if((ip = dirlookup(dp, name, &off)) != 0){ iunlockput(dp); ilock(ip); if(type == T_FILE && ip->type == T_FILE) return ip; iunlockput(ip); return 0; } if((ip = ialloc(dp->dev, type)) == 0) panic("create: ialloc"); ilock(ip); ip->major = major; ip->minor = minor; ip->nlink = 1; iupdate(ip); if(type == T_DIR){ // Create . and .. entries. dp->nlink++; // for ".." iupdate(dp); // No ip->nlink++ for ".": avoid cyclic ref count. if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) panic("create dots"); } if(dirlink(dp, name, ip->inum) < 0) panic("create: dirlink"); iunlockput(dp); return ip; }
// Look up and return the inode for a path name. // If parent != 0, return the inode for the parent and copy the final // path element into name, which must have room for DIRSIZ bytes. static struct inode* _namei(char *path, int parent, char *name) { //cprintf("Path: %s\n", path); struct inode *ip, *next; if(*path == '/') ip = iget(ROOTDEV, 1); else ip = idup(cp->cwd); //cprintf("cp name: %s\n", cp->name); while((path = skipelem(path, name)) != 0){ ilock(ip); if(ip->type != T_DIR){ iunlockput(ip); //cprintf("HERE\n"); return 0; } if(parent && *path == '\0'){ // Stop one level early. iunlock(ip); //cprintf("HERE3\n"); return ip; } if((next = dirlookup(ip, name, 0)) == 0){ iunlockput(ip); //cprintf("HERE1\n"); return 0; } iunlockput(ip); ip = next; } if(parent){ iput(ip); //cprintf("HERE2\n"); return 0; } //cprintf("HERE4-2: %d\n", ip); return ip; }
static struct inode *_path2inode(char *path, int parent, char *name) { struct inode *ip, *next; ip = 0; if (*path == '/') { ip = iget(ROOT_DEV, ROOT_INO); } else { ip = idup(proc->cwd); } while ((path = skipelem(path, name)) != 0) { /* read from disk */ ilock(ip); if (!S_ISDIR(ip->mode)) { iunlockput(ip); return 0; } if (parent && *path == '\0') { iunlock(ip); return ip; } if ((next = dir_lookup(ip, name, 0)) == 0) { iunlockput(ip); return 0; } iunlockput(ip); ip = next; } if (parent) { iput(ip); return 0; } return ip; }
struct file* kernel_open(char* path, int omode){ int fd; struct file *f; struct inode *ip; if(omode & O_CREATE){ begin_trans(); ip = kernel_create(path, T_FILE, 0, 0); commit_trans(); if(ip == 0) return 0; } else { // cprintf("kernel_open - path is %s\n",path); if((ip = namei(path)) == 0) return 0; //cprintf("kernel_open - path is %s passed namei\n",path); ilock(ip); if(ip->type == T_DIR && omode != O_RDONLY){ iunlockput(ip); return 0; } } // cprintf("kernel_open - before filealloc path %s\n",path); if((f = filealloc()) == 0 || (fd = kernel_fdalloc(f)) < 0){ if(f) fileclose(f); iunlockput(ip); return 0; } iunlock(ip); f->type = FD_INODE; f->ip = ip; f->off = 0; f->readable = !(omode & O_WRONLY); f->writable = (omode & O_WRONLY) || (omode & O_RDWR); return f; //return fd; //return 0; }
static int load_proc(char *path, struct proc *p) { int i; struct proc np; //an inode describes a single unnamed file struct inode *ip; begin_op(); if ((ip = namei(path)) == 0) { end_op(); return -1; } ilock(ip); if((np.pgdir = setupkvm()) == 0) return -1; if((np.sz = allocuvm(np.pgdir, 0, p->sz)) == 0) return -1; for(i = 0; i < p->sz; i+=PGSIZE) { if(loaduvm(np.pgdir, (void *)i, ip, sizeof(struct proc) + i,PGSIZE) < 0) return -1; } iunlockput(ip); end_op(); ip = 0; np.tf->eax = proc->pid; np.tf->eip = p->tf->eip; np.tf->esp = p->tf->esp; np.tf->ebp = p->tf->ebp; proc->pgdir = np.pgdir; proc->sz = PGROUNDUP(np.sz); *proc->tf = *np.tf; switchuvm(proc); return 0; }
// Look up and return the inode for a path name. // If parent != 0, return the inode for the parent and copy the final // path element into name, which must have room for DIRSIZ bytes. // Must be called inside a transaction since it calls iput(). static struct inode* namex(char* path, int nameiparent, int ignoreMounts, char* name) { // cprintf("namex \n"); struct inode* ip, *next; // cprintf("path %s nameparent %d , name %s bootfrom %d\n", path, nameiparent, name, bootfrom); if (*path == '/') ip = iget(ROOTDEV, ROOTINO, bootfrom); else ip = idup(proc->cwd); while ((path = skipelem(path, name)) != 0) { //cprintf("namex path %s \n",path); ilock(ip); if (ip->type != T_DIR) { iunlockput(ip); return 0; } if (nameiparent && *path == '\0') { // Stop one level early. // cprintf("fileread \n"); iunlock(ip); return ip; } if ((next = dirlookup(ip, name, 0)) == 0) { // cprintf("next is zero \n"); iunlockput(ip); return 0; } iunlockput(ip); ilock(next); // cprintf("next %d , type %d major %d minor %d \n",next->inum,next->type,next->major,next->minor); if (!ignoreMounts && next->type == T_DIR && next->major != 0 && next->major != MOUNTING_POINT) { // cprintf("major used ,we are f****d \n"); } // handle mounting points if (!ignoreMounts && next->type == T_DIR && next->major == MOUNTING_POINT) { // cprintf("got into condition \n"); iunlock(next); // iunlockput(ip); uint partitionNumnber = next->minor; ip = iget(ROOTDEV, 1, partitionNumnber); } else{ iunlock(next); // testing ip = next; } } if (nameiparent) { iput(ip); return 0; } // cprintf("ip returned is %d \n", ip->inum); return ip; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz,s_sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack one page away from USERTOP (at bottom // grow upwards) s_sz = (USERTOP - PGSIZE); if((s_sz = allocuvm(pgdir, s_sz, s_sz + PGSIZE)) == 0) goto bad; // Push argument strings, prepare rest of stack in ustack. sp = s_sz; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); s_sz = USERTOP - PGSIZE; // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->s_sz =s_sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); // cprintf("finish exec%d\t%d\n",sz,s_sz); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
//part 1 - signature change, and de-referencing symbolic links to the correct inode struct inode* namex(char *path, int nameiparent, char *name, struct inode *prev, int loopCount,int noDeRef) { struct inode *ip, *next; char buf[512]; // part 1 - prevent loop in symbolic links if(loopCount > 16) return 0; if(*path == '/') { ip = iget(ROOTDEV, ROOTINO); } else if(prev) { ip = idup(prev); } else { ip = idup(proc->cwd); } while( (path = skipelem(path, name)) != 0 ) { ilock(ip); if(ip->type != T_DIR){ iunlockput(ip); return 0; } if(nameiparent && *path == '\0'){ // Stop one level early. iunlock(ip); return ip; } if((next = dirlookup(ip, name, 0)) == 0){ iunlockput(ip); return 0; } if(noDeRef) { iunlockput(ip); } else { iunlock(ip); //part 1 ilock(next); if(next->type == T_SYMLINK) { if(readi(next, buf, 0, sizeof(buf)) != next->size) { iunlockput(ip); return 0; } buf[next->size] = 0; iunlock(next); next = namex(buf, 0, name, ip, loopCount++,0); } else { iunlock(next); } // End part 1 iput(ip); } ip = next; } if(nameiparent) { iput(ip); return 0; } return ip; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; char tmp_path[MAX_LNK_NAME]; /* A&T */ /* A&T use readlink to de-reference symbolic links */ if (k_readlink(path, tmp_path, MAX_LNK_NAME) != -1) { if((ip = namei(tmp_path)) == 0) return -1; } else { if((ip = namei(path)) == 0) return -1; } ilock(ip); //A&T checks if symlink /* for (i=0;i < 16 ; i++) { //prevents loops ,up to 16 chain links */ /* if (ip->flags & I_SYMLNK) { */ /* if((sym_ip = namei((char*)ip->addrs)) == 0) { */ /* iunlock(ip); */ /* return -1; */ /* } */ /* iunlock(ip); */ /* ip = sym_ip; */ /* ilock(ip); */ /* } else */ /* break; */ /* } */ /* if (i == 16) { */ /* panic("symbolic link exceeds 16 links "); */ /* } */ //A&T - end pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm(kalloc)) == 0) goto bad; // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { cprintf("-(%d)exec...\n",proc->pid); char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // sx: passed Part 1 sz = PGSIZE;//PGSIZW = 4K for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; //no need to modify above///////////////////////// // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); /* if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) goto bad; sp = sz; */ // Push argument strings, prepare rest of stack in ustack. // sx:tst1///////////////// int sz_stack= 0; if((sz_stack = allocuvm(pgdir, USERTOP-PGSIZE, USERTOP))==0) panic("allocuvm sz_stack failed\n"); sp = sz_stack; ///////////////////////// cprintf("-exec: sp(%d)\n",sp); for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); cprintf("-exec:sz(%d)sp(%d)sz-sp(%d)elf.entry(%d)\n",sz,sp,USERTOP-sp,elf.entry); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz_stack;//current stack bottom proc->sz_stack = sz_stack-PGSIZE;//current stack top proc->sz_heap = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); cprintf("-exec end***\n"); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // Skip first page sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) goto bad; // Push argument strings, prepare rest of stack in ustack. sp = sz; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; // Set end of shared pages address to USERTOP proc->endSP = USERTOP; proc->sz = sz; // For each shared page set the shared page count to the memory count for (i = 0; i < SHMEM_PAGES; i++) { proc->shared_count[i] = mem_count[i]; } proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sz_stk, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; sz = PGROUNDUP(sz); // CHANGE: Allocates the first page of the stack at the end of the user programs address space if((allocuvm(pgdir, USERTOP - PGSIZE, USERTOP)) == 0) goto bad; /* CHANGE: sets the sz_stk field equal to the top address of the stack */ sz_stk = USERTOP - PGSIZE; // Push argument strings, prepare rest of stack in ustack. sp = USERTOP; /* CHANGE: sets the stack pointer to the botom of the user space. */ for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->sz_stk = sz_stk; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. sz = PGSIZE; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.va + ph.memsz)) == 0) goto bad; //cprintf("exec: size: %d, phva: %d phvamem:%d \n", sz, ph.va , ph.memsz); if(loaduvm(pgdir, (char*)ph.va, ip, ph.offset, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate a one-page stack at the next page boundary sz = PGROUNDUP(sz); //if((sz = allocuvm(pgdir, sz, sz + PGSIZE)) == 0) // goto bad; uint stkptr = allocuvm(pgdir, USERTOP - PGSIZE, USERTOP); if(stkptr == 0) panic("dont know wht to do"); //proc->stkptr = USERTOP-PGSIZE; //cprintf("stkptr is : %d\n", stkptr); // Push argument strings, prepare rest of stack in ustack. sp = stkptr; for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp -= strlen(argv[argc]) + 1; sp &= ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; //cprintf("sp value: %d\n",sp); } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // remzi video change //uint newstk = allocuvm(pgdir, USERTOP - PGSIZE, USERTOP); //if(newstk == 0) panic("dont know wht to do"); // Commit to the user image. proc->stkptr = USERTOP - PGSIZE; //proc->grdptr = USERTOP - PGSIZE - PGSIZE; oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm(kalloc)) == 0) goto bad; // Load program into memory. // leave first page inaccessible (to make NULL ref fail) sz = PGSIZE-1; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // hook up the old shared memory to the new addr space // (no need to change refcount, because the old ref goes away with // this exec, so it's +1 then -1 => 0 change if (proc->shared) { extern void mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm); mappages(pgdir, (char *)SHARED_V, PGSIZE, v2p(proc->shared->page), PTE_W|PTE_U); } // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; if((ip = namei(path)) == 0) return -1; ilock(ip); pgdir = 0; // Check ELF header if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; //// section check (either exist interp section) //// needed libsample.so.1 if (strcmp("share_main", path) == 0) { // share loader process (dummy of load ld-linux.so.2) //// mmap share library (libsample.so). sz = 0; /////// alloc physical memory cprintf("start %d \n", sz); ph.vaddr = 0x08048000; ph.memsz = 0x031a4 + 0x00130; sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz); cprintf("start4 %d \n", sz); /////// map pages to physical memory ph.off = 0x0; ph.filesz = 0x21a4 + 0x00124; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; cprintf("start3 %d \n", sz); iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = 0x80486d4; //.text proc->tf->esp = sp; cprintf("start2 %d \n", sz); switchuvm(proc); freevm(oldpgdir); return 0; //// rewrite bss valiable. //// stay loader program for delayed load. } // Load program into memory. sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; ustack[2] = sp - (argc+1)*4; // argv pointer sp -= (3+argc+1) * 4; if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip) iunlockput(ip); return -1; }
int exec(char *path, char **argv) { char *s, *last; int i, off; uint argc, sz, sp, ustack[3+MAXARG+1]; struct elfhdr elf; struct inode *ip; struct proghdr ph; pde_t *pgdir, *oldpgdir; // namei converts given path into inode begin_op(); if((ip = namei(path)) == 0){ end_op(); return -1; } ilock(ip); pgdir = 0; // Check ELF header // if the file is smaller than the size of an elf header, // then it doesn't hold an elf header. (ERROR) if(readi(ip, (char*)&elf, 0, sizeof(elf)) < sizeof(elf)) goto bad; if(elf.magic != ELF_MAGIC) goto bad; if((pgdir = setupkvm()) == 0) goto bad; // Load program into memory. // do this for each section of the elf file (chunk size dlineated // by sizeof program header) // allocate user virtual memory // load program into user virtual memory // in linux, run readelf -a /bin/ls and see the the offset and size // column program section header being loaded sz = 0; for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){ if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph)) goto bad; if(ph.type != ELF_PROG_LOAD) continue; if(ph.memsz < ph.filesz) goto bad; if((sz = allocuvm(pgdir, sz, ph.vaddr + ph.memsz)) == 0) goto bad; if(loaduvm(pgdir, (char*)ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } iunlockput(ip); end_op(); ip = 0; // Allocate two pages at the next page boundary. // Make the first inaccessible. Use the second as the user stack. sz = PGROUNDUP(sz); // This is macro function that jumps to the next page boundary if((sz = allocuvm(pgdir, sz, sz + 2*PGSIZE)) == 0) goto bad; // this makes the inaccessible page clearpteu(pgdir, (char*)(sz - 2*PGSIZE)); sp = sz; // Push argument strings, prepare rest of stack in ustack. // This code is building the stack frame of the application. // since argc is not passed into this function, to find the max // num of args, we need to step through the argv string until the // item returned is NULL or the end of the string. // This means that we have found all of the arguments. // Next, we need to copy each argument into the stack and keep // references to it in a local stack. Once this is done, we can // set the stack pointer to point to the first argument on the stack. // now, we can put the return value and the total number of args onto our // local stack. Then, we must prepare local stack for the copy into the // real stack. Next, we adjust the real stack pointer to make // room for our local stack and then we copy our stack that contains // pointers to each argument onto the stack. // We need this for quick lookup of each argument -- without the poitners // we can't efficiently get the args back. we also need the // the total number of arguments to make sure that we are growing the // stack properly. // think about this: int main(int argc, char **argv); // this code defends why we need a double pointer to a char. // we are giving an array of char *. for(argc = 0; argv[argc]; argc++) { if(argc >= MAXARG) goto bad; // explain of ~3 in following line: // to make memory align with 4 bits, we the two lower order bit // which are the oly two bits that aren't divisibile by 4. // this is to keep the compiler aligned with the system sp = (sp - (strlen(argv[argc]) + 1)) & ~3; if(copyout(pgdir, sp, argv[argc], strlen(argv[argc]) + 1) < 0) goto bad; ustack[3+argc] = sp; } ustack[3+argc] = 0; ustack[0] = 0xffffffff; // fake return PC ustack[1] = argc; // This is getting the real stack ready for the copy // of the local stack, ustack[] ustack[2] = sp - (argc+1)*4; // argv pointer // this is moving the stack pointer to the location of first argument. sp -= (3+argc+1) * 4; // This is copying the ustack[] into the real stack if(copyout(pgdir, sp, ustack, (3+argc+1)*4) < 0) goto bad; // done buildng the stack frame // Save program name for debugging. for(last=s=path; *s; s++) if(*s == '/') last = s+1; safestrcpy(proc->name, last, sizeof(proc->name)); // Commit to the user image. oldpgdir = proc->pgdir; proc->pgdir = pgdir; proc->sz = sz; proc->tf->eip = elf.entry; // main proc->tf->esp = sp; switchuvm(proc); freevm(oldpgdir); return 0; bad: if(pgdir) freevm(pgdir); if(ip){ iunlockput(ip); end_op(); } return -1; }
int exec(char *path, char **argv) { int i; char *s, *name; uint32_t sz, sp, off, argc, pa, ustack[3 + MAX_ARGC + 1]; pde_t *pgdir, *old_pgdir; struct inode *ip; struct elf32hdr eh; struct proghdr ph; pgdir = 0; i = off = 0; pgdir = (pde_t *)pmm_alloc(); kvm_init(pgdir); // exception handle pgdir // if ((ip = p2i(path)) == 0) { goto bad; } ilock(ip); // read elf header if (iread(ip, (char *)&eh, 0, sizeof(eh)) < (int)sizeof(eh)) { goto bad; } if (eh.magic != ELF_MAGIC) { goto bad; } // load program to memory sz = USER_BASE; for (i = 0, off = eh.phoff; i < eh.phnum; i++, off += sizeof(ph)) { if (iread(ip, (char *)&ph, off, sizeof(ph)) != sizeof(ph)) { goto bad; } if (ph.type != ELF_PROG_LOAD) { continue; } if (ph.memsz < ph.filesz) { goto bad; } if ((sz = uvm_alloc(pgdir, sz, ph.vaddr + ph.memsz)) == 0) { goto bad; } if (uvm_load(pgdir, ph.vaddr, ip, ph.off, ph.filesz) < 0) { goto bad; } } iunlockput(ip); ip = 0; /* build user stack */ sz = PAGE_ALIGN_UP(sz); if ((sz = uvm_alloc(pgdir, sz, sz + 2*PAGE_SIZE)) == 0) { goto bad; } /* leave a unaccessable page between kernel stack */ if (vmm_get_mapping(pgdir, sz - 2*PAGE_SIZE, &pa) == 0) { // sz is no mapped goto bad; } vmm_map(pgdir, sz - 2*PAGE_SIZE, pa, PTE_K | PTE_P | PTE_W); sp = sz; if (vmm_get_mapping(pgdir, sz - PAGE_SIZE, &pa) == 0) { // sz is no mapped goto bad; } pa += PAGE_SIZE; for (argc = 0; argv[argc]; argc++) { if (argc > MAX_ARGC) { goto bad; } // "+1" leava room for '\0' "&~3" align 4 sp = (sp - (strlen(argv[argc]) + 1)) & ~3; // sync with pa pa = (pa - (strlen(argv[argc]) + 1)) & ~3; strcpy((char *)pa, argv[argc]); ustack[3+argc] = sp; // argv[argc] } ustack[3+argc] = 0; ustack[0] = 0xffffffff; ustack[1] = argc; // count of arguments ustack[2] = sp - (argc+1)*4; // pointer of argv[0] sp -= (3 + argc + 1)*4; pa -= (3 + argc + 1)*4; memcpy((void *)pa, ustack, (3 + argc + 1)*4); // combine for (name = s = path; *s; s++) { if (*s == '/') { name = s + 1; } } cli(); strncpy(proc->name, name, sizeof(proc->name)); old_pgdir = proc->pgdir; proc->pgdir = pgdir; proc->size = sz - USER_BASE; proc->fm->eip = eh.entry; proc->fm->user_esp = sp; uvm_switch(proc); uvm_free(old_pgdir); old_pgdir = 0; old_pgdir ++; sti(); return 0; bad: if (pgdir) { uvm_free(pgdir); } if (ip) { iunlockput(ip); } return -1; }