int runprogram(char *progname) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ #if OPT_A3 as = as_create(progname); #else as = as_create(); #endif if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } curthread->t_filetable = filetable_create(); if(curthread->t_filetable == NULL){ return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int execv(const char *program, char **args) { // kprintf("\n\n execv testing \n\n") ; if (program == NULL ) { return EFAULT ; } //char * kernel_pgm = (char *)kmalloc(sizeof(char *)) ; char * kernel_pgm = (char *)kmalloc(__PATH_MAX) ; size_t bytes_copied ; int result = copyinstr((const userptr_t)program,kernel_pgm,__PATH_MAX,&bytes_copied) ; if (result ) { return result ; } if (strlen(kernel_pgm) == 0) { return EINVAL ; } if (strlen(kernel_pgm) >= __PATH_MAX) { return ENAMETOOLONG ; } int argc = 0 ; if (args == NULL) { return EFAULT ; } char *temp1 = (char *)kmalloc(ARG_MAX*sizeof(char)) ; result = copyinstr((const userptr_t)args,temp1,ARG_MAX*sizeof(char),&bytes_copied) ; if(result){ return result; } kfree(temp1); while(args[argc]!=NULL) //while (true) { char *temp = (char *)kmalloc(ARG_MAX*sizeof(char)) ; result = copyinstr((const userptr_t)args[argc],temp,ARG_MAX*sizeof(char),&bytes_copied) ; if (result) { kfree(temp); return EFAULT ;//break ; } argc++ ; kfree(temp) ; } char **temp = (char **)kmalloc(argc*sizeof(char *)) ; int i = 0 ; while(i<argc) { temp[i] = (char *)kmalloc(ARG_MAX*sizeof(char)) ; result = copyinstr((const userptr_t)args[i],temp[i],ARG_MAX*sizeof(char),&bytes_copied) ; if (result) { return result ; } i++ ; } struct vnode *v; vaddr_t entrypoint, stackptr; result = vfs_open(kernel_pgm, O_RDONLY, 0, &v); if (result) { return result; } struct addrspace *addrspace_copy=curthread->t_addrspace; if(curthread->t_addrspace != NULL){ as_destroy(curthread->t_addrspace); curthread->t_addrspace = NULL; } //struct addrspace *addrspace_copy=curthread->t_addrspace; curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); curthread->t_addrspace = addrspace_copy; return ENOMEM; } as_activate(curthread->t_addrspace); result = load_elf(v, &entrypoint); if (result) { vfs_close(v); return result; } vfs_close(v); result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { return result; } i = i -1 ; vaddr_t index[25] ; int k = 0 ; while(i>= 0) { int length = strlen(temp[i]) ; int num0 = (4 - (length % 4)) ; int j = 0 ; char *temp1 = (char *)kmalloc((length+num0)*sizeof(char)) ; strcpy(temp1,temp[i]) ; while(j<num0) { strcat(temp1,"\0") ; j++ ; } stackptr = stackptr - ((length+num0)*sizeof(char)) ; result = copyoutstr(temp1,(userptr_t) stackptr,(length+num0)*sizeof(char),&bytes_copied) ; if (result) { return result ; } index[k] = (vaddr_t )stackptr; k++ ; i-- ; kfree(temp1) ; } i = 0 ; stackptr = stackptr - sizeof(int) ; stackptr = stackptr - sizeof(int) ; k-- ; while(i<=k) { result = copyout(&index[i],(userptr_t) stackptr,sizeof(int)) ; if (result) { return result ; } i++ ; if (i<=k){ stackptr = stackptr - sizeof(int) ; } } kfree(temp) ; kfree(kernel_pgm) ; enter_new_process(argc,(userptr_t) stackptr , stackptr, entrypoint); panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, int argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; // Variables for argument passing int i, pad; size_t offset, get; userptr_t userdest; size_t got[argc]; userptr_t user_argv[argc]; // Count length of each arg i = 0; for (i=0; i<argc; i++){ got[i] = strlen(args[i]) + 1; // Need +1 to account for /0 } /* We enforce that the kernel is only allowed to start ONE user process * directly through runprogram with PID_MIN as its pid. Thereafter any * new user process needs to be forked from existing ones. */ KASSERT(process_table[PID_MIN] == NULL); curthread->pid = PID_MIN; stdio_init(); /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } // Copy args to new addrspace offset = 0; for (i=argc-1; i>-1; i--){ pad = (4 - (got[i]%4) ) % 4; // Word align offset += pad; offset += got[i]; user_argv[i] = (userptr_t)(stackptr - offset); result = copyoutstr((const char*)args[i], user_argv[i], got[i], &get); if (result){ return result; } } // Copy pointers to argv userdest = user_argv[0] - 4 * (argc+1); stackptr = (vaddr_t)userdest; // Set stack pointer for (i=0; i<argc; i++){ result = copyout((const void *)&user_argv[i], userdest, 4); if (result){ return result; } userdest += 4; } /* Warp to user mode. */ enter_new_process(argc, (userptr_t)stackptr, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(char* progname, char** args, int *retval, bool iskernel) { int result; int *args_len; size_t len; size_t total_len = 0; char *temp; char **kern_args; int nargs = 0; userptr_t *usr_argv = NULL; char *kern_progname = kmalloc(PATH_MAX); args_len = kmalloc(sizeof(int) * ARG_MAX); temp = kmalloc(sizeof(char) * ARG_MAX); if (kern_progname == NULL || args_len == NULL || temp == NULL){ *retval = -1; return ENOMEM; } if (args == NULL || progname == NULL) { *retval = -1; return EFAULT; } if (!iskernel) { result = copyinstr((userptr_t)args, temp, ARG_MAX, &len); if (result) { *retval = -1; return result; } } // Figure out nargs, and the length for each arg string while(args[nargs] != NULL) { if (iskernel) { len = strlen(args[nargs]) + 1; if (len == 1) { nargs--; break; } strcpy(temp, args[nargs]); } else { result = copyinstr((userptr_t)args[nargs], temp, ARG_MAX, &len); if (result) { *retval = -1; return result; } } args_len[nargs] = len; total_len += len; nargs += 1; } kfree(temp); if (total_len > ARG_MAX) { *retval = -1; return E2BIG; } kern_args = kmalloc(sizeof(char*) * nargs); // Go through args and copy everything over to kern_args using copyinstr for (int i = 0; i < nargs; i++) { kern_args[i] = kmalloc(sizeof(char) * args_len[i]); if (kern_args[i] == NULL) { *retval = -1; return ENOMEM; } if (iskernel) { strcpy(kern_args[i], args[i]); len = strlen(kern_args[i]); } else { copyinstr((userptr_t)args[i], kern_args[i], ARG_MAX, NULL); } } // This is from runprogram struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; if (iskernel) { strcpy(kern_progname, progname); len = strlen(kern_progname); } else { result = copyinstr((userptr_t)progname, kern_progname, PATH_MAX, NULL); } if (*kern_progname == 0) { *retval = -1; return EISDIR; } if (result) { kfree(kern_progname); *retval = -1; return result; } /* Open the file. */ result = vfs_open(kern_progname, O_RDONLY, 0, &v); if (result) { *retval = -1; return result; } // Blow up the current addrspace. TODO, this may be problematic if (!iskernel) { as_destroy(curproc->p_addrspace); curproc->p_addrspace = NULL; } /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { vfs_close(v); *retval = -1; return ENOMEM; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Intialize file table, not needed for execv */ if (iskernel) filetable_init(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); *retval = -1; return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ *retval = -1; return result; } // Clear space for arg pointers +1 for NULL terminator stackptr -= (sizeof(char*)) * (nargs + 1); // Convenience method for indexing usr_argv = (userptr_t*)stackptr; for(int i = 0; i < nargs; i++ ) { // Clear out space for an arg string stackptr -= sizeof(char) * (strlen(kern_args[i]) + 1); // Assign the string's pointer to usr_argv usr_argv[i] = (userptr_t)stackptr; // Copy over string copyout(kern_args[i], usr_argv[i], sizeof(char) * (strlen(kern_args[i]) + 1)); } // NULL terminate usr_argv usr_argv[nargs] = NULL; // Free memory for(int i = 0; i < nargs; i++) { kfree(kern_args[i]); } kfree(kern_args); /* Warp to user mode. */ enter_new_process(nargs /*argc*/, (userptr_t)usr_argv /*userspace addr of argv*/, NULL /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, int argc, char** args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } /* Initialize an array of pointers that stores the pointer to the * string arguments in the user stack */ char** argv = (char **)kmalloc((argc + 1) * sizeof(char*)); if (argv == NULL) { return ENOMEM; } argv[argc] = 0; int i; size_t actual; int total = 0; /* Copy string arguments from kernel memory onto the user stack, * and store the user pointer to the argument in argv */ for (i = argc - 1; i >= 0; i--) { int len = strlen(args[i]) + 1; total = total + len; stackptr = stackptr - len; copyoutstr(args[i], (userptr_t)stackptr, len, &actual); argv[i] = (char *)stackptr; } /* Add any necessary padding to the user stack */ int padding = 4 - (total % 4); if (padding) { stackptr = stackptr - padding; } /* Copy the array of user pointers argv onto the user stack */ for (i = argc; i >= 0; i--) { stackptr = stackptr - 4; copyout(&argv[i], (userptr_t)stackptr, 4); } kfree(argv); /* Warp to user mode. */ enter_new_process(argc, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, unsigned int nargs) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; int argc = nargs; char **argv = (char **)kmalloc((argc + 1) * sizeof(char *)); if(argv == NULL) { return ENOMEM; } for(int i = 0; i < argc; ++i) { argv[i] = args[i]; } argv[argc] = NULL; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } /*------copy args to user stack-----------*/ vaddr_t *argPtrs = (vaddr_t *)kmalloc((argc + 1) * sizeof(vaddr_t)); if(argPtrs == NULL) { for(int i = 0; i < argc; ++i) { kfree(argv[i]); } kfree(argv); as_deactivate(); as = curproc_setas(NULL); as_destroy(as); return ENOMEM; } for(int i = argc-1; i >= 0; --i) { //arg length with null size_t curArgLen = strlen(argv[i]) + 1; size_t argLen = ROUNDUP(curArgLen,4); stackptr -= (argLen * sizeof(char)); //kprintf("copying arg: %s to addr: %p\n", temp, (void *)stackptr); //copy to stack result = copyout((void *) argv[i], (userptr_t)stackptr, curArgLen); if(result) { kfree(argPtrs); for(int i = 0; i < argc; ++i) { kfree(argv[i]); } kfree(argv); as_deactivate(); as = curproc_setas(NULL); as_destroy(as); return result; } argPtrs[i] = stackptr; } argPtrs[argc] = (vaddr_t)NULL; //copy arg pointers for(int i = argc; i >= 0; --i) { stackptr -= sizeof(vaddr_t); result = copyout((void *) &argPtrs[i], ((userptr_t)stackptr),sizeof(vaddr_t)); if(result) { kfree(argPtrs); for(int i = 0; i < argc; ++i) { kfree(argv[i]); } kfree(argv); as_deactivate(); as = curproc_setas(NULL); as_destroy(as); return result; } } kfree(argPtrs); vaddr_t baseAddress = USERSTACK; vaddr_t argvPtr = stackptr; vaddr_t offset = ROUNDUP(USERSTACK - stackptr,8); stackptr = baseAddress - offset; /* for(vaddr_t i = baseAddress; i >= stackptr; --i) { char *temp; temp = (char *)i; //kprintf("%p: %c\n",(void *)i,*temp); kprintf("%p: %x\n", (void *)i, *temp & 0xff); } */ /*-done-copy args to user stack-----------*/ /* Warp to user mode. */ enter_new_process(argc /*argc*/, (userptr_t)argvPtr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv( userptr_t upname, userptr_t uargs ) { struct addrspace *as_new = NULL; struct addrspace *as_old = NULL; struct vnode *vn = NULL; vaddr_t entry_ptr; vaddr_t stack_ptr; int err; char kpname[MAX_PROG_NAME]; int nargs; int buflen; KASSERT( curthread != NULL ); KASSERT( curthread->td_proc != NULL ); (void)uargs; //lock the execv args lock_acquire( lk_exec ); //copy the old addrspace just in case. as_old = curthread->t_addrspace; //copyin the program name. err = copyinstr( upname, kpname, sizeof( kpname ), NULL ); if( err ) { lock_release( lk_exec ); return err; } //try to open the given executable. err = vfs_open( kpname, O_RDONLY, 0, &vn ); if( err ) { lock_release( lk_exec ); return err; } //copy the arguments into the kernel buffer. err = copy_args( uargs, &nargs, &buflen ); if( err ) { lock_release( lk_exec ); vfs_close( vn ); return err; } //create the new addrspace. as_new = as_create(); if( as_new == NULL ) { lock_release( lk_exec ); vfs_close( vn ); return ENOMEM; } //activate the new addrspace. as_activate( as_new ); //temporarily switch the addrspaces. curthread->t_addrspace = as_new; //load the elf executable. err = load_elf( vn, &entry_ptr ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //create a stack for the new addrspace. err = as_define_stack( as_new, &stack_ptr ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //adjust the stackptr to reflect the change stack_ptr -= buflen; err = adjust_kargbuf( nargs, stack_ptr ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //copy the arguments into the new user stack. err = copyout( kargbuf, (userptr_t)stack_ptr, buflen ); if( err ) { curthread->t_addrspace = as_old; as_activate( as_old ); as_destroy( as_new ); vfs_close( vn ); lock_release( lk_exec ); return err; } //reelase lk_exec lock_release( lk_exec ); //no need for it anymore. vfs_close( vn ); //we are good to go. as_destroy( as_old ); //off we go to userland. enter_new_process( nargs-1, (userptr_t)stack_ptr, stack_ptr, entry_ptr ); panic( "execv: we should not be here." ); return EINVAL; }
int sys_execv(char* program, char** args) { int result; char name[strlen(program) + 1]; result = copyin((userptr_t) program, name, (strlen(program) + 1) * sizeof(char)); //kprintf("%s", name); int len_arg = 0; while(args[len_arg] != NULL) { len_arg++; } int length_every_arg[len_arg]; for(int i = 0; i < len_arg; i++) { length_every_arg[i] = strlen(args[i]); } char* kern_args[len_arg]; for(int i = 0; i < len_arg; i++) { kern_args[i] = kmalloc(sizeof(char) * length_every_arg[i] + 1); copyin((const_userptr_t)args[i], kern_args[i], (length_every_arg[i] + 1) * sizeof(char)); } /* for(int i = 0; i < len_arg; i++) { kprintf("{ _%d__%p__%p_",strlen(kern_args[i]), kern_args[i],args[i]); kprintf("%s", kern_args[i]); kprintf("}\n"); } */ ///////////////////////////////////////////////////// // this is "copied" from runprogram struct addrspace* old_as; struct vnode* v; vaddr_t entrypoint, stackptr; result = vfs_open(program, O_RDONLY, 0, &v); if(result) { return result; } as_deactivate(); old_as = curproc_setas(NULL); as_destroy(old_as); struct addrspace* new_as = as_create(); if(new_as == NULL) { vfs_close(v); return ENOMEM; } curproc_setas(new_as); as_activate(); result = load_elf(v, &entrypoint); if(result) { vfs_close(v); return result; } vfs_close(v); result = as_define_stack(new_as, &stackptr); if(result) { return result; } ////////////////////////////////////////////////////////// // kern_args // the addr of stackptr is 0x8000 0000 vaddr_t argv = stackptr; for(int i = 0; i < len_arg + 1; i++) { argv = argv - 4; } vaddr_t start = argv; vaddr_t temp = argv; copyout(NULL, (userptr_t)(stackptr - 4), 4); //starts from 1, because argv[0] is reserved for the program name for(int i = 0; i < len_arg; i++) { //question? why do I have to add 2 int m = sizeof(char) * (strlen(kern_args[i]) + 1); // kprintf("the value of m -> %d\n", m); argv = argv - m; copyout(kern_args[i], (userptr_t)argv, m); // kprintf("***(%d)%s(%p)\n***", m, (char* )argv, (void *) argv); copyout(&argv, (userptr_t)temp, sizeof(char* )); temp = temp + 4; } for(int i = 0; i < len_arg; i++) { kfree(kern_args[i]); } while(argv % 8 != 0) {argv--;} enter_new_process(len_arg, (userptr_t)start, (vaddr_t) argv, entrypoint); // enter_new_process(0, NULL, stackptr, entrypoint); panic("enter_new_process returned"); return EINVAL; }
int sys_execv(char *progname, char **args, int *err) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Validations */ if (progname == NULL) { *err = EFAULT; return -1; } if (args == NULL || (int *)args == (int *)0x40000000 || (int *)args == (int *)0x80000000) { *err = EFAULT; return -1; } /* Count number of arguments and total size of input */ int args_count = 0; for (;args_count < ARG_MAX && args[args_count] != NULL; args_count++); if (args_count > ARG_MAX) { *err = E2BIG; return -1; } /* Copy File name */ char *progname_copy = (char *) kmalloc(sizeof(char) * NAME_MAX); size_t actual = 0; result = copyinstr((userptr_t)progname, progname_copy, NAME_MAX, &actual); if (result) { kfree(progname_copy); *err = result; return -1; } if (strlen(progname_copy) == 0) { kfree(progname_copy); *err = EINVAL; return -1; } /* Allocate Kernel Memory for arguments */ char **args_copy = (char **) kmalloc(sizeof(char *) * args_count); int c_args_count = 0, arg_size = 0, padded_size = 0; for (;c_args_count < args_count; c_args_count++) { if ((int *)args[c_args_count] == (int *)0x40000000 || (int *)args[c_args_count] == (int *)0x80000000) { kfree(progname_copy); *err = EFAULT; return -1; } } c_args_count = 0; /* Calculate total length accounting for padding */ for (;c_args_count < args_count; c_args_count++) { arg_size = strlen(args[c_args_count]) + 1; args_copy[c_args_count] = (char *) kmalloc(sizeof(char) * arg_size); copyinstr((userptr_t)args[c_args_count], args_copy[c_args_count], arg_size, &actual); padded_size += arg_size; if (padded_size % 4) { padded_size += (4 - (padded_size % 4)) % 4; } } /* Open the file. */ result = vfs_open(progname_copy, O_RDONLY, 0, &v); if (result) { kfree(progname_copy); *err = result; return -1; } /* Destroy the current process's address space to create a new one. */ as = curproc->p_addrspace; curproc->p_addrspace = NULL; as_destroy(as); /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { kfree(progname_copy); vfs_close(v); *err = ENOMEM; return -1; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ kfree(progname_copy); vfs_close(v); *err = result; return -1; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ kfree(progname_copy); *err = result; return -1; } stackptr -= padded_size; char **arg_address = (char **) kmalloc(sizeof(char *) * args_count + 1); /* Copy arguments into user stack */ for(int i = 0; i < args_count; i++) { arg_size = strlen(args_copy[i]) + 1; if (arg_size % 4) { arg_size += (4 - arg_size % 4) % 4; } /* Store address of arguments */ arg_address[i] = (char *)stackptr; copyoutstr(args_copy[i], (userptr_t)stackptr, arg_size, &actual); stackptr += arg_size; } /* Add Null Pointer at the end */ arg_address[args_count] = 0; stackptr -= padded_size; stackptr -= (args_count + 1) * sizeof(char *); /* Copy address locations into user stack*/ for (int i = 0; i < args_count + 1; i++) { copyout((arg_address + i), (userptr_t)stackptr, sizeof(char *)); stackptr += sizeof(char *); } /* Reset pointer to start of the stack */ stackptr -= ((args_count + 1) * sizeof(char *)); kfree(progname_copy); c_args_count = 0; for (;c_args_count < args_count; c_args_count++) { kfree(args_copy[c_args_count]); } kfree(args_copy); kfree(arg_address); /* Warp to user mode. */ enter_new_process(args_count /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/, (userptr_t) stackptr /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); *err = EINVAL; return -1; }
int sys_execv(userptr_t progname, userptr_t *arguments) { struct proc *proc = curproc; struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; //kprintf("****EXECV]***** process-%d trying to exec", proc->pid); //lock_acquire(execlock); //kprintf("****EXECV]***** process-%d acquired exec lock", proc->pid); if(progname == NULL || progname == (void *)0x80000000 || progname == (void *)0x40000000) { return EFAULT; } if(arguments == NULL || arguments == (void *)0x80000000 || arguments == (void *)0x40000000) { return EFAULT; } /* This process should have an address space copied during fork */ KASSERT(proc != NULL); char *_progname; size_t size; int i=0, count=0; _progname = (char *) kmalloc(sizeof(char)*PATH_MAX); result = copyinstr(progname, _progname, PATH_MAX, &size); if(result) { kfree(_progname); return EFAULT; } if(strlen(_progname) == 0) { kfree(_progname); return EINVAL; } if(swapping_started == true) { } kfree(_progname); char *args = (char *) kmalloc(sizeof(char)*ARG_MAX); result = copyinstr((const_userptr_t)arguments, args, ARG_MAX, &size); if(result) { kfree(args); return EFAULT; } /* Copy the user arguments on to the kernel */ int offset = 0; while((char *) arguments[count] != NULL) { result = copyinstr((const_userptr_t) arguments[count], args+offset, ARG_MAX, &size); if(result) { kfree(args); return EFAULT; } offset += size; count++; } /* Open the file */ result = vfs_open((char *)progname, O_RDONLY, 0, &v); if(result) { kfree(args); return result; } /* Destroy the current address space and Create a new address space */ as_destroy(proc->p_addrspace); proc->p_addrspace = NULL; KASSERT(proc_getas() == NULL); as = as_create(); if(as == NULL) { kfree(args); vfs_close(v); return ENOMEM; } /* Switch to it and activate it */ proc_setas(as); as_activate(); /* Load the executable. */ // kprintf("free pages available before load_elf : %d \n", coremap_free_bytes()/4096); result = load_elf(v, &entrypoint); if(result) { kfree(args); vfs_close(v); return result; } /* Done with the file now */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if(result) { kfree(args); return result; } i = 0; int prevlen = 0, cur = 0; char **stkargs=(char**) kmalloc(sizeof(char*)*(count+1)); while(i < offset) { int len=0, olen; for(len=0; args[i] != '\0'; len++, i++); olen = len; len = len + (4 - len%4); char *arg = kmalloc(len); //arg = kstrdup(args+prevlen); //kprintf("%s\n", arg); int j = prevlen; for(int k=0; k<len; k++) { if(k >= olen) arg[k] = '\0'; else arg[k] = args[j++]; } //kprintf("%s\n", arg); stackptr -= len; result = copyout((const void *)arg, (userptr_t)stackptr, (size_t)len); if(result) { kfree(args); kfree(stkargs); return result; } kfree(arg); stkargs[cur++] = (char *)stackptr; prevlen += olen + 1; i++; } stkargs[cur] = NULL; kfree(args); for(i=(cur) ; i>=0; i--) { stackptr = stackptr - sizeof(char *); //kprintf("copying arg %d at [%p]\n", i, *(stkargs+i)); result = copyout((const void *)(stkargs+i), (userptr_t) stackptr, (sizeof(char *))); if(result) { kfree(stkargs); return result; } prevlen += 4; } kfree(stkargs); //unsigned int free = coremap_free_bytes(); // unsigned int free_pages = free/4096; // kprintf("free pages available : %d \n", free_pages); //lock_release(execlock); //kprintf("****EXECV]***** process-%d released exec lock", proc->pid); enter_new_process(count, (userptr_t) stackptr, NULL, stackptr, entrypoint); panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **arguments, int argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; (void)arguments; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } char **argv; char *arg; int length, padding; //For each argument: Add padding, Decrement stackptr and copyout args for (int i=0; i<argc; i++) { length = strlen(arguments[i])+1; padding = 4-(length % 4); //Add padding arg = add_padding(arguments[i], padding); length = length+padding; //Decrement stackptr stackptr -= length; argv[i] = (char *)stackptr; //Copyout copyout(arg, (userptr_t) stackptr, length); } //Null terminate argv stackptr -= sizeof(char *)*(argc+1); argv[argc] = NULL; //Copyout argv copyout(argv, (userptr_t) stackptr, sizeof(char *)*(argc+1)); /* Warp to user mode. */ enter_new_process(argc, (userptr_t) stackptr, stackptr-1, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int runprogram(char *progname, unsigned long argc, char **argv) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ #if OPT_A3 as = as_create(progname); #else as = as_create(); #endif if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); // find the stack pointer if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } //add stuff stackptr = stackptr - (argc + 1)*sizeof(vaddr_t); //subtract number of arguments + 1 (space for pointers) unsigned long i; unsigned int len; unsigned int len2; char **buf = (char **)stackptr; // argv for(i=0; i<argc; i++){ len = (strlen(argv[i])+1)*(sizeof(char)); // first str length + null char stackptr = stackptr - len; // adjust stack pointer for length of str buf[i] = (char*)stackptr; // assign pointer to argv[i] copyoutstr((void *)argv[i],(userptr_t)buf[i],len,&len2); // copy to userstack } unsigned int remainder = stackptr % 8; if(remainder != 0){ stackptr = stackptr - remainder; } // pass arguments to user program /* Warp to user mode. */ enter_new_process(argc, (userptr_t)buf /*userspace addr of argv*/, stackptr, entrypoint); // stores into trap->a0 as argc // stores trap->a1 as argv // sets stack pointer /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int runprogram(char *progname) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { // p_addrspace will go away when curproc is destroyed return result; } struct vnode* v1; struct vnode* v2; struct vnode* v3; const char* name = "con:"; char *con_name = kstrdup(name); char *con_name2 = kstrdup(name); char *con_name3 = kstrdup(name); /*char con_name[5]; char con_name2[5]; char con_name3[5]; strcpy(con_name,name); strcpy(con_name2,name); strcpy(con_name3,name); */ result = vfs_open(con_name, O_RDONLY, 0664, &v1); if(result) { return result; } result = vfs_open(con_name2, O_WRONLY, 0664, &v2); if(result) { return result; } result = vfs_open(con_name3, O_WRONLY, 0664, &v3); if(result) { return result; } kfree(con_name); kfree(con_name2); kfree(con_name3); struct file_handle* fh1 = file_handle_create(); fh1->file = v1; fh1->openflags = O_RDONLY; fh1->ref_count = 1; strcpy(fh1->file_name,"con:"); curproc->t_file_table[0] = fh1; struct file_handle* fh2 = file_handle_create(); fh2->file = v2; fh2->openflags = O_WRONLY; fh2->ref_count = 1; strcpy(fh2->file_name, "con:"); curproc->t_file_table[1] = fh2; struct file_handle* fh3 = file_handle_create(); fh3->file = v3; fh3->openflags = O_WRONLY; fh3->ref_count = 1; strcpy(fh3->file_name, "con:"); curproc->t_file_table[2] = fh3; /* Warp to user mode. */ //kprintf("[run program] releasing semaphore \n"); enter_new_process(0 /*argc*/, 0 /*userspace addr of argv*/, NULL /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, unsigned long nargs, char **args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); // userptr_t addrOfArg = (userptr_t)stackptr; //mOVED if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } //Will store my pointers of arguments here, put in stack later. vaddr_t ptrToArgAddressInStack[nargs]; // Had issues with data being stored at start of the stack. // Moving down to avoid writing/reading issue. stackptr = stackptr - 4; // Insert strings (my arguments), and store the address (in stack) // which we get from stack pointer into my array I defined earlier. unsigned long i; for (i = 0; i < nargs; i++){ result = insertArgToStack(&stackptr, args[i]); if (result){ return result; } ptrToArgAddressInStack[i] = stackptr; } //Add a Null 4 byte buffer int fourBlank = (int)NULL; stackptr = stackptr - 4; result = copyout(&fourBlank, (userptr_t)stackptr, 4); if (result){ return result; } // Insert the address values into the stack for (i = nargs; i > 0 ; i--){ stackptr = stackptr - 4; copyout(&ptrToArgAddressInStack[(i - 1)], (userptr_t)stackptr, 4); } userptr_t addrOfArg = (userptr_t) (stackptr); /* Warp to user mode. */ enter_new_process(nargs /*argc*/, addrOfArg /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(userptr_t progname, userptr_t uargs_ptr){ // char* name int err; char* program = (char*)kmalloc(20); size_t prog_len; err = copyinstr((userptr_t)progname, program, 1024, &prog_len); if(err){ return err; } if(prog_len == 1) return EINVAL; char** uargs = (char**)kmalloc(100); // this could be causing problems maybe err = copyin((userptr_t)uargs_ptr, uargs, 100); if(err){ return err; } // Get number of arguments size_t nargs = 0; while(uargs[nargs] != NULL){ nargs++; if(nargs >= MAX_ARGS){ return E2BIG; } } int wordlen; int argLengths[nargs]; // Store the length of each argument, including the 1 null terminator // but NOT including the padding for alignment. for(size_t i = 0; i < nargs; i++){ char arg[100]; err = copyin((userptr_t)uargs[i],arg,100); if(err) return err; wordlen = strlen(uargs[i]) + 1; // Add 1 to account for Null terminator! // pad = 4 - (wordlen % 4); // Don't worry about padding yet // if(pad == 4){ pad = 0; } // // totalLength += wordlen; // Don't need this... argLengths[i] = wordlen; } char** args = kmalloc(sizeof(char*) * nargs); // Still need to populate args with each individual argument if(args == NULL){ panic("kmalloc failed :'("); } size_t arg_num = 0; while(arg_num < nargs){ args[arg_num] = kmalloc(argLengths[arg_num] * sizeof(char)); err = copyin((userptr_t)uargs[arg_num], args[arg_num], argLengths[arg_num]); if(err) return err; arg_num++; } int result; struct vnode *v; vaddr_t entrypoint, stackptr; /* Open the file. */ result = vfs_open(program, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ // KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } // This is where runprogram stuff starts! // vaddr_t entrypoint, stackptr; int individualArgSize[nargs]; size_t totalLength = 0; size_t pad; for(size_t i = 0; i < nargs; i++){ wordlen = strlen(args[i]) + 1; // Add 1 to account for Null terminator! pad = 4 - (wordlen % 4); if(pad == 4){ pad = 0; } totalLength += wordlen + pad; } char* words_contiguous = kmalloc(sizeof(char) * totalLength); int j; for(size_t i = 0; i < nargs; i++){ j = 0; while(args[i][j] != '\0'){ *words_contiguous = args[i][j]; words_contiguous++; j++; } // At this point, j is the length of the word without any null bytes. *words_contiguous = '\0'; words_contiguous++; // Now calculate the number of padding null bytes for alignment. pad = 4 - ((j + 1) % 4); if(pad == 4){ pad = 0; } // Add the null bytes for(size_t p = 0; p < pad; p++){ *words_contiguous = '\0'; words_contiguous++; } individualArgSize[i] = j + 1 + pad; //Just getting the pointer size... } // Reset pointer back to start of C-string. words_contiguous = words_contiguous - totalLength; size_t totalStackSize; totalStackSize = totalLength + ((nargs + 1) * sizeof(char*)); // Adjust to copyout the words (totalLength) stackptr = stackptr - totalLength; copyout(words_contiguous, (userptr_t)stackptr, totalLength); // Adjust to bottom of where we'll modify stack. // stackptr = stackptr - (totalStackSize - totalLength); // KASSERT((totalStackSize - totalLength) == sizeof(args)); args[0] = (char*)stackptr; stackptr = stackptr + individualArgSize[0]; for(size_t argNumber = 1; argNumber < nargs; argNumber++){ args[argNumber] = (char*)stackptr; stackptr = stackptr + individualArgSize[argNumber]; } // stackptr should be at 80000000 right now. // Set stackptr back to bottom of stack; stackptr = stackptr - totalStackSize; // Copy args (pointers to stack addresses) onto the stack, below the words. copyout(args, (userptr_t)stackptr, (totalStackSize - totalLength)); // Create Null pointer. args[0] = NULL; // Copy null pointer to stack copyout(args, (userptr_t)(stackptr+((totalStackSize - totalLength) - 4)), 4); // TODO: Free words contiguous at some point (memory leak) kfree(words_contiguous); kfree(args); kfree(program); //kfree(uargs); /* Warp to user mode. */ //TODO: Change enter_new_process(nargs /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); (void)nargs; /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(const char *prog, char **userArgs) { struct vnode *v; vaddr_t entrypoint, stackptr; int res = 0; int length = 0; int index = 0; lock_acquire(allProcLock); char *progname; size_t size; progname = (char *) kmalloc(sizeof(char) * PATH_MAX); res = copyinstr((const_userptr_t) prog, progname, PATH_MAX, &size); char **args = (char **) kmalloc(sizeof(char **)); res = copyin((const_userptr_t)userArgs, args, sizeof(char **)); while (userArgs[index] != NULL) { args[index] = (char *) kmalloc(sizeof(char) * PATH_MAX); res = copyinstr((const_userptr_t) userArgs[index], args[index], PATH_MAX, &size); index++; } args[index] = NULL; index = 0; res = vfs_open(progname, O_RDONLY, 0, &v); struct addrspace *temp; temp = curproc->p_addrspace; if(curproc->p_addrspace != NULL){ as_destroy(curproc->p_addrspace); curproc->p_addrspace = NULL; } KASSERT(curproc->p_addrspace == NULL); if((curproc->p_addrspace = as_create()) == NULL){ kfree(progname); kfree(args); vfs_close(v); return ENOMEM; } as_activate(); res = load_elf(v, &entrypoint); vfs_close(v); res = as_define_stack(curproc->p_addrspace, &stackptr); while(args[index] != NULL) { char * arg; length = strlen(args[index]) + 1; int orignalLength = length; if(length % 4 != 0) { length = length + (4 - length % 4); } arg = kmalloc(sizeof(length)); arg = kstrdup(args[index]); for(int i = 0; i < length; i++){ if(i >= orignalLength){ arg[i] = '\0'; } else{ arg[i] = args[index][i]; } } stackptr -= length; res = copyout((const void *) arg, (userptr_t) stackptr, (size_t) length); kfree(arg); args[index] = (char *) stackptr; index++; } if(args[index] == NULL){ stackptr -= 4 * sizeof(char); } for(int i = (index - 1); i >= 0; i--) { stackptr = stackptr - sizeof(char*); res = copyout((const void *) (args + i), (userptr_t) stackptr, sizeof(char*)); } kfree(progname); kfree(args); lock_release(allProcLock); enter_new_process(index, (userptr_t) stackptr, stackptr, entrypoint); return EINVAL; }
runprogram(char *progname) #endif { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; //kprintf("bla0\n"); /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } //kprintf("bla1\n"); /* We should be a new process. */ KASSERT(curproc_getas() == NULL); //kprintf("bla2\n"); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } //kprintf("bla3\n"); /* Switch to it and activate it. */ curproc_setas(as); as_activate(); //kprintf("bla4\n"); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } //kprintf("bla5\n"); /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 //kprintf("bla6\n"); if(args == NULL){ return EFAULT; } // copy args to user size_t len = sizeof(char *) * (num + 1); char **copyargs = kmalloc(len); for(unsigned long int i = 0; i < num; i++){ len = strlen(args[i]) + 1; stackptr = stackptr - ROUNDUP(len, 8);//? limit or valid stackptr //new result = copyoutstr(args[i], (userptr_t)stackptr, len, NULL);//new if(result){ kfree(copyargs); return result; } copyargs[i] = (char *)stackptr; } copyargs[num] = NULL; // copy arr len = sizeof(char *) * (num + 1); stackptr = stackptr - ROUNDUP(len, 8); result = copyout(copyargs, (userptr_t)stackptr, len); kfree(copyargs); if(result){ return result; } userptr_t stackk = (userptr_t)stackptr; enter_new_process(num /*argc*/, stackk /*userspace addr of argv*/, stackptr, entrypoint); #else /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); #endif /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int execv(const char *prog_name, char **argv) { if( prog_name == NULL || argv == NULL ) return EFAULT; int argc = 0; size_t actual; char progname[__NAME_MAX]; int err = copyinstr((const_userptr_t) prog_name, progname, __NAME_MAX, &actual); if(err != 0){ return EFAULT; } /*if ( progname == (const char *)0x40000000 || progname == (const char *)0x80000000 || argv == (char **)0x40000000 || argv == (char **)0x80000000) return EFAULT; if( strcmp(progname,"") ) return EFAULT; if( strcmp((const char*)*argv,"") ) return EINVAL; if( strcmp(progname,"\0") ) return EINVAL; if( strcmp((const char*)*argv,"\0") ) return EINVAL; if( strlen(progname) == 0 ) return EINVAL; if( strlen((const char*)*argv) == 0 ) return EINVAL;*/ int i; for(i=0 ; argv[i] != NULL ; i++){ if(argv == (char **)0x40000000 || argv == (char **)0x80000000) return EFAULT; } argc = i; struct vnode *v; vaddr_t entrypoint, stackptr; int result; //Copy arguments into Temporary Kernel buffer char *ktemp[argc]; int argvlen[argc]; for( int m=0; m <argc; m++) { int len = strlen(argv[m])+1; argvlen[m] = len; int len_padding = len + (4 - (len % 4)); ktemp[m] = kmalloc(len_padding); size_t *p; err = copyinstr((const_userptr_t)argv[m], ktemp[m], len, p); } /* Open the file. */ result = vfs_open((char*)progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ //KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } // Load the arguments in user stack vaddr_t kargv[argc]; size_t len_from_top = 0; int arglen = 0, arglen_pad=0; if(argc > 0) { //kargv[argc]=0; for(int i=0 ; i < argc ; i++){ arglen = argvlen[i]; arglen_pad =arglen + (4- ((arglen)%4)); len_from_top = len_from_top + arglen_pad ; kargv[i] = stackptr - len_from_top; copyout(ktemp[i], (userptr_t) kargv[i], arglen_pad); kfree((void*)ktemp[i]); } stackptr = stackptr - len_from_top -(argc)*sizeof(vaddr_t); for(int i=0 ; i <argc ; i++){ copyout( &kargv[i], (userptr_t) stackptr, sizeof(vaddr_t)); stackptr = stackptr + sizeof(vaddr_t); } stackptr = stackptr - (argc)*sizeof(vaddr_t); /* Warp to user mode. */ enter_new_process( argc /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); } /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
void run_process(void *ptr, unsigned long num) { (void)num; int result; vaddr_t entrypoint, stackptr; // extract and free passed-in context struct new_process_context *ctxt = (struct new_process_context *)ptr; struct process *proc = ctxt->proc; struct vnode *v = ctxt->executable; int nargs = ctxt->nargs; char **args = ctxt->args; kfree(ctxt); // attach process to thread curthread->t_proc = proc; proc->ps_thread = curthread; // Activate address space as_activate(proc->ps_addrspace); // Load the executable result = load_elf(v, &entrypoint); if (result) { vfs_close(v); kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Done with the file now vfs_close(v); // Define the user stack in the address space result = as_define_stack(proc->ps_addrspace, &stackptr); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Copy out arguments userptr_t uargv[nargs + 1]; for (int i = 0; i < nargs; i++) { int aligned_length = WORD_ALIGN(strlen(args[i]) + 1); stackptr -= aligned_length; uargv[i] = (userptr_t)stackptr; size_t arg_len; result = copyoutstr(args[i], uargv[i], strlen(args[i]) + 1, &arg_len); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } } uargv[nargs] =(userptr_t)NULL; // Copy out the argv array itself stackptr -= (nargs + 1) * sizeof(userptr_t); result = copyout(uargv, (userptr_t)stackptr, (nargs + 1) * sizeof(userptr_t)); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } enter_new_process(nargs, (userptr_t)stackptr, stackptr, entrypoint); // enter_new_process() does not return panic("enter_new_process returned\n"); }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /** Initialize the file descriptors for console**/ if (curthread->t_fdtable[0] == NULL) { result = init_file_descriptor(); if (result ) { // file descriptors not initialized kprintf_n("init_file_descriptor failed"); return result; } } /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(proc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as == NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ proc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, NULL /*userspace addr of environment*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(const_userptr_t path, const_userptr_t argv) { int err; struct process *proc = curthread->t_proc; char *kpath = kmalloc(PATH_MAX); if (kpath == NULL) return ENOMEM; // copy in path size_t path_len; if ((err = copyinstr(path, kpath, PATH_MAX, &path_len))) { kfree(kpath); return err; } // give the process a new name char *old_name = proc->ps_name; proc->ps_name = kstrdup(kpath); if (proc->ps_name == NULL) { proc->ps_name = old_name; kfree(kpath); return ENOMEM; } // copy in args size_t argc; size_t total_len; char **kargv = kmalloc((ARGNUM_MAX + 1) * sizeof(char *)); err = copyinargs(argv, kargv, &argc, &total_len); if (err) { kfree(proc->ps_name); proc->ps_name = old_name; kfree(kpath); return err; } // Open the file. struct vnode *v; err = vfs_open(kpath, O_RDONLY, 0, &v); kfree(kpath); if (err) { free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // set up new address space struct addrspace *old_as = curthread->t_proc->ps_addrspace; struct addrspace *as = as_create(); if (as == NULL) { vfs_close(v); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return ENOMEM; } proc->ps_addrspace = as; // Activate the new address space as_activate(as); vaddr_t entrypoint; err = load_elf(v, &entrypoint); if (err) { proc->ps_addrspace = old_as; as_activate(old_as); as_destroy(as); vfs_close(v); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // close the file now, since we will not be returning // here from user mode. vfs_close(v); // set up user stack vaddr_t stackptr; err = as_define_stack(as, &stackptr); if (err) { proc->ps_addrspace = old_as; as_activate(old_as); as_destroy(as); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // copy arguments at base of stack stackptr -= total_len; stackptr -= (argc + 1) * sizeof(userptr_t); err = copyoutargs((userptr_t)stackptr, kargv, argc, total_len); if (err) { proc->ps_addrspace = old_as; as_activate(old_as); as_destroy(as); free_kargv(kargv); kfree(proc->ps_name); proc->ps_name = old_name; return err; } // destroy old address space and free memory // that we will no longer need as_destroy(old_as); kfree(old_name); // Warp to user mode enter_new_process(argc, (userptr_t)stackptr, stackptr, entrypoint); // enter_new_process() does not return panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **argv, int argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } int i, bytes; vaddr_t argvaddr[argc+1]; for (i = 0; i < argc; i++) { bytes = strlen(argv[i]); bytes += 4 - bytes%4; //padding stackptr -= bytes; argvaddr[i] = stackptr; copyout(argv[i], (userptr_t)stackptr, bytes); kfree(argv[i]); } kfree(argv); argvaddr[argc] = 0; stackptr -= sizeof(vaddr_t)*(argc+1); copyout(argvaddr, (userptr_t) stackptr, 4*(argc+1)); /* Warp to user mode. */ enter_new_process(argc /*argc*/,(userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(userptr_t progname_ptr, userptr_t args_ptr){ char* prog_name = kmalloc(PATH_MAX); size_t prog_name_len; if((char*)progname_ptr == NULL || (char**)args_ptr == NULL){ return EFAULT; } int argc = 0; char** args_ptrs = kmalloc(ARG_MAX); while(1){ char* arg = NULL; copyin(args_ptr+argc*sizeof(char*), &arg, sizeof(char*)); args_ptrs[argc] = arg; if(arg != NULL){ argc++; }else{ break; } } if(argc> 64){ return E2BIG; } int result_prog_name = copyinstr(progname_ptr,prog_name,PATH_MAX, &prog_name_len); if(result_prog_name != 0){ return result_prog_name; } char* argv = kmalloc(ARG_MAX); size_t * arg_offsets = kmalloc(argc * sizeof(size_t)); int offset = 0; for(int i = 0; i < argc; i++){ //char* arg = kmalloc(ARG_MAX); size_t arg_len; int result = copyinstr((userptr_t)args_ptrs[i], argv+offset, ARG_MAX - offset, &arg_len ); if(result != 0){ return result; } arg_offsets[i] = offset; offset += ROUNDUP(arg_len+1,8); //argv[i] = arg; } // prog_name (char*) AND argv (char*) struct addrspace *curproc_as = curproc_getas(); struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; vaddr_t cur_ptr; int result; /* Open the file. */ result = vfs_open(prog_name, O_RDONLY, 0, &v); if (result) { return result; } /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); // Have both argc and prog_name ready for runprogram cur_ptr = stackptr; cur_ptr -= offset; result = copyout(argv, (userptr_t)cur_ptr, offset); if(result != 0){ return result; } userptr_t * arg_offsets_up = kmalloc(sizeof(userptr_t) * (argc+1)); for(int i = 0; i < argc; i++){ userptr_t ptr = (userptr_t)cur_ptr + arg_offsets[i]; arg_offsets_up[i] = ptr; } arg_offsets_up[argc] = NULL; cur_ptr -= sizeof(userptr_t) * (argc+1); result = copyout(arg_offsets_up, (userptr_t)cur_ptr, sizeof(userptr_t) * (argc+1) ); if(result != 0){ return result; } as_destroy(curproc_as); kfree(arg_offsets); kfree(arg_offsets_up); kfree(argv); kfree(args_ptrs); kfree(prog_name); enter_new_process(argc /*argc*/, (userptr_t)cur_ptr /*userspace addr of argv*/, cur_ptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; //return 0; }
int sys___execv(char * p_name,char **ar ) { struct vnode *p_vnode; vaddr_t stackptr; vaddr_t entrypoint; int result; size_t copied_length; char *kname; if(p_name==NULL) return EFAULT; if(ar==NULL) return EFAULT; if(p_name == '\0') return ENOEXEC; kname = (char *) kmalloc(sizeof(p_name)); result = copyinstr((const_userptr_t)p_name,kname,NAME_MAX,&copied_length); if(copied_length == 1) { kfree(kname); return EINVAL; } if(result) { kfree(kname); return result; } char **karguments1 = kmalloc(100*sizeof(char*)); result = copyin((const_userptr_t) ar,karguments1,(100*sizeof(char*))); if(result) { kfree(karguments1); kfree(kname); return result; } else kfree(karguments1); char **arguments_kernel =(char **) kmalloc(sizeof(char**)); result = copyin((const_userptr_t) ar,arguments_kernel,(sizeof(char**))); if(result) { kfree(kname); kfree(arguments_kernel); return result; } char **karguments = (char **) kmalloc(sizeof(char **)); int counter=0; size_t actual_lenght1; while(!(ar[counter]==NULL)) { int string_length = strlen(ar[counter])+1; karguments[counter] = (char *) kmalloc(sizeof(char) * string_length); result = copyinstr((const_userptr_t) ar[counter],karguments[counter],string_length,&actual_lenght1); if(result) { kfree(kname); kfree(arguments_kernel); return result; } counter++; } karguments[counter] = NULL; result = vfs_open(kname, O_RDONLY, 0, &p_vnode); if (result) { return result; } as_destroy(curthread->t_addrspace); //Create a new address space. curthread->t_addrspace = as_create(); if (curthread->t_addrspace==NULL) { vfs_close(p_vnode); return ENOMEM; } //Activate it. as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(p_vnode, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(p_vnode); return result; } /* Done with the file now. */ vfs_close(p_vnode); //Get the pointer to the stack starting result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } //Now copy the arguments int count =0; char **karray= kmalloc(sizeof(char**)); size_t final_stack=0; while(karguments[count] != NULL) { int string_length = strlen(karguments[count])+1; char *k_des= karguments[count]; int new_length = string_length; if((string_length) % 4 != 0) { while(new_length%4 !=0) { new_length++; } for(int i=string_length;i<=new_length;i++) { k_des[i]= '\0'; } } //Argument aligned by 4 size_t final_length= (size_t)new_length; if(count==0) { final_stack= stackptr- final_length; } else { final_stack= (size_t)karray[count-1]- final_length; } size_t actual_length1; result= copyoutstr(k_des, (userptr_t) (final_stack), final_length, &actual_length1); if(result) { return result; } karray[count]= (char*)(final_stack); count++; } //End of While karray[count]= (char*)NULL; int value= count+1; int arr_length = (value+1)*sizeof(char*); final_stack= (size_t)karray[count-1]- arr_length; result= copyout(karray, (userptr_t) (final_stack),arr_length); if(result) { return result; } /* Warp to user mode. */ enter_new_process(count /*argc*/, (userptr_t)(final_stack) /*userspace addr of argv*/, final_stack, entrypoint); return 0; }
runprogram(char *progname) #endif { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 // How much space do we need for args in stack? // We need space for each pointer (4argc) // We need space for each character, including NULL termination, plus // padding to make multiples of 4 int stringSpace = 0; for (unsigned long i = 0; i < argc; i++) { stringSpace += strlen(argv[i]) + 1; } // Align stack pointer to an 8-byte alignment while ((stackptr - (4*argc) - stringSpace) % 8 != 0) { stackptr--; } // Use a vaddr array to track the addresses the strings end up in // One bigger than argc to also have the pointer to the final NULL // value vaddr_t stringAddr[argc+1]; // Copy argument strings onto stack // Array must end with NULL pointer, so do that first stackptr -= 4; copyout((void *)NULL, (userptr_t)stackptr, (size_t)4); stringAddr[argc] = stackptr; for (int i = argc-1; i >= 0; i--) { stackptr -= strlen(argv[i]) + 1; while (stackptr % 4 != 0) stackptr--; copyoutstr(argv[i], (userptr_t)stackptr, (size_t)strlen(argv[i]), NULL); stringAddr[i] = stackptr; } // Now use the stored addresses of the string to add the appropriate // pointers to the stack for (int i = argc; i >= 0; i--) { stackptr -= sizeof(vaddr_t); copyout(&stringAddr[i], (userptr_t)stackptr, sizeof(vaddr_t)); } /* Warp to user mode. */ enter_new_process(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); #else /* Warp to user mode. */ enter_new_process(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); #endif /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char** args, size_t nargs) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; int argc = 0; while(args[argc] != NULL) { argc++; } /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new process. */ KASSERT(curproc_getas() == NULL); /* Create a new address space. */ as = as_create(); if (as ==NULL) { vfs_close(v); return ENOMEM; } /* Switch to it and activate it. */ curproc_setas(as); as_activate(); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(as, &stackptr); if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } #if OPT_A2 while(stackptr %8 != 0) stackptr--; vaddr_t argptr[argc + 1]; for (int i = argc - 1; i >= 0; i--) { stackptr -= strlen(args[i]) + 1; result = copyoutstr(args[i], (userptr_t) stackptr, strlen(args[i]) + 1, NULL); if(result) return result; argptr[i] = stackptr; } while(stackptr % 4 != 0) stackptr--; //int hack = (int) nargs; argptr[nargs] = 0; for (int i = argc; i >= 0; i--) { stackptr -= ROUNDUP(sizeof(vaddr_t), 4); result = copyout(&argptr[i], (userptr_t) stackptr, sizeof(vaddr_t)); if(result) return result; } #endif /* Warp to user mode. */ enter_new_process(nargs /*argc*/, (userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
/* * Load program "progname" and start running it in usermode. * Does not return except on error. * * Calls vfs_open on progname and thus may destroy it. */ int runprogram(char *progname, char **args, unsigned long nargs) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /*Initialize Console*/ char *consolein; char *consoleout; char *consoleerr; consolein = kstrdup("con:"); consoleout = kstrdup("con:"); consoleerr = kstrdup("con:"); curthread->t_fdtable[0] = (struct fdesc*) kmalloc(sizeof(struct fdesc)); if (vfs_open(consolein, O_RDONLY, 0664, &(curthread->t_fdtable[0]->vn))) { return EINVAL; } curthread->t_fdtable[0]->name = consolein; curthread->t_fdtable[0]->flag = O_RDONLY; curthread->t_fdtable[0]->ref_count = 1; curthread->t_fdtable[0]->filelock = lock_create("STDIN"); kfree(consolein); curthread->t_fdtable[1] = (struct fdesc*) kmalloc(sizeof(struct fdesc)); if (vfs_open(consoleout, O_WRONLY, 0664, &(curthread->t_fdtable[1]->vn))) { return EINVAL; } curthread->t_fdtable[1]->name = consoleout; curthread->t_fdtable[1]->flag = O_WRONLY; curthread->t_fdtable[1]->ref_count = 1; curthread->t_fdtable[1]->filelock = lock_create("STDOUT"); kfree(consoleout); curthread->t_fdtable[2] = (struct fdesc*) kmalloc(sizeof(struct fdesc)); if (vfs_open(consoleerr, O_WRONLY, 0664, &(curthread->t_fdtable[2]->vn))) { return EINVAL; } curthread->t_fdtable[2]->name = consoleerr; curthread->t_fdtable[2]->flag = O_WRONLY; curthread->t_fdtable[2]->ref_count = 1; curthread->t_fdtable[2]->filelock = lock_create("STDERR"); kfree(consoleerr); /*Console Initialized*/ /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } /* We should be a new thread. */ KASSERT(curthread->t_addrspace == NULL); /* Create a new address space. */ curthread->t_addrspace = as_create(); if (curthread->t_addrspace == NULL ) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_addrspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_addrspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_addrspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_addrspace */ return result; } int argc = (signed) nargs; int err; char** argv; //kmalloc argv with size of char* times nargs+1 argv = kmalloc((nargs + 1) * sizeof(userptr_t)); size_t len; for (int i = 0; i < argc; i++) { len = strlen(args[i]) + 1; len = (len + 4 - 1) & ~(size_t) (4 - 1); stackptr -= len; if ((err = copyout(args[i], (userptr_t) stackptr, len)) != 0) { kprintf("error copyout"); } argv[i] = (char*) stackptr; } argv[nargs] = NULL; stackptr -= (nargs + 1) * sizeof(userptr_t); if ((err = copyout(argv, (userptr_t) stackptr, (nargs + 1) * sizeof(char*)))) { kprintf("error copying"); } /* Warp to user mode. */ enter_new_process(argc, (userptr_t) stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* enter_new_process does not return. */ panic("enter_new_process returned\n"); return EINVAL; }
int sys_execv(userptr_t progname, userptr_t args) { struct addrspace *as; struct vnode *v; vaddr_t entrypoint, stackptr; int result; char * path = kmalloc(PATH_MAX); as = curproc_getas(); if (as != NULL && !valid_address_check(as, (vaddr_t)args)) { // out of vaddr boundary for this proc errno = EFAULT; return -1; } if (as != NULL && !valid_address_check(as, (vaddr_t)progname)) { // out of vaddr boundary for this proc errno = EFAULT; return -1; } result = copyinstr(progname, path, PATH_MAX, NULL); if(result) { return result; } if(*path == '\0') { errno = EISDIR; return -1; } // Open the executable, create a new address space and load the elf into it result = vfs_open((char *)path, O_RDONLY, 0, &v); if (result) { return result; } // KASSERT(curproc_getas() == NULL); as = as_create(); if (as == NULL) { vfs_close(v); return ENOMEM; } curproc_setas(as); as_activate(); result = load_elf(v, &entrypoint); if (result) { /* p_addrspace will go away when curproc is destroyed */ vfs_close(v); return result; } vfs_close(v); result = as_define_stack(as, &stackptr); // stackptr set if (result) { /* p_addrspace will go away when curproc is destroyed */ return result; } kfree(path); userptr_t karg, uargs, argbase; char * buffer, * bufend; buffer = kmalloc(sizeof(ARG_MAX)); if(buffer == NULL) { errno = ENOMEM; return -1; } bufend = buffer; size_t resid, bufsize; size_t alen; size_t *offsets = kmalloc(NARG_MAX * sizeof(size_t)); if(offsets == NULL) { errno = ENOMEM; return -1; } int size = 0; userptr_t arg; resid = bufsize = ARG_MAX; for(int i = 0 ; i < NARG_MAX ; i++) { // copyin from user. copyin(args, &karg, sizeof(userptr_t)); // copy the pointer. if(karg == NULL) break; // if NULL, break. copyinstr(karg, bufend, resid, &alen); offsets[i] = bufsize - resid; bufend += alen; resid -= alen; args += sizeof(userptr_t); size++; } size_t buflen = bufend - buffer; // length of buffer. vaddr_t stack = stackptr - buflen; // current stack position. stack -= (stack & (sizeof(void *) - 1)); // alignment argbase = (userptr_t)stack; // argbase. copyout(buffer, argbase, buflen); // copy the arguments into stack. stack -= (size + 1)*sizeof(userptr_t); // go to array pointer (bottom of stack). uargs = (userptr_t)stack; // got stack. for(int i = 0 ; i < size ; i++) { // copy the elements arg = argbase + offsets[i]; copyout(&arg, uargs, sizeof(userptr_t)); uargs += sizeof(userptr_t); // 4 } arg = NULL; copyout(&arg, uargs, sizeof(userptr_t)); // copy the NULL pointer. kfree(buffer); kfree(offsets); enter_new_process(size /*argc*/, (userptr_t)stack /*userspace addr of argv*/, stack, entrypoint); return 0; }