/* * 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, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } //kprintf("\n in runprogram"); assignPid(); /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ 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_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /* Warp to user mode. */ md_usermode(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode 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, unsigned long argc) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; pid_t pidRetVal; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create filetable for process*/ curthread->ft = create_process_filetable(); if(curthread->ft == NULL) { vfs_close(v); return ENOMEM; } /* Initialize STDIN, STDOUT, STDERR */ struct ft_node* standardIn = create_ft_node(); struct ft_node* standardOut = create_ft_node(); struct ft_node* standardErr = create_ft_node(); char console1[] = "con:"; result = vfs_open(console1, O_RDONLY, &standardIn->v); if(result) { kprintf("Cannot open STDIN\n"); vfs_close(v); return result; } standardIn->mode = O_RDONLY; array_add(curthread->ft->file_descriptors, standardIn); char console2[] = "con:"; result = vfs_open(console2, O_WRONLY, &standardOut->v); if(result) { kprintf("Cannot open STDOUT\n"); vfs_close(v); return result; } standardOut->mode = O_WRONLY; array_add(curthread->ft->file_descriptors, standardOut); char console3[] = "con:"; result = vfs_open(console3, O_WRONLY, &standardErr->v); if(result) { kprintf("Cannot open STDERR\n"); vfs_close(v); return result; } standardErr->mode = O_WRONLY; array_add(curthread->ft->file_descriptors, standardErr); /* Allocate initial PID for this first program */ result = allocate_pid(&pidRetVal); if(result) { kprintf("Could not allocate PID\n"); vfs_close(v); return result; } curthread->PID = pidRetVal; ((struct p_node *)array_getguy(pid_table, curthread->PID))->is_interested = 0; /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } //kprintf("finished loadelf in runprog\n"); /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } vaddr_t stackptrv[argc+1]; int i; size_t actual; for(i = argc-1; i >= 0; i--) { int len = strlen(argv[i]); len++; int padding = len % 4; stackptr -= len + (4 - padding); result = copyoutstr(argv[i], (userptr_t)stackptr, len, &actual); if(result) { return result; } stackptrv[i] = stackptr; } stackptrv[argc] = 0; for(i = argc; i >= 0; i--) { stackptr -= sizeof(vaddr_t); result = copyout(&stackptrv[i], (userptr_t)stackptr, sizeof(vaddr_t)); if(result) { return result; } } //kprintf("Before usernmode\n"); /* Warp to user mode. */ md_usermode(argc /*argc*/, (userptr_t)stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(char* progname, char** args){ struct vnode *v; vaddr_t stackptr, entrypoint; int result; int string_size = 0; //s_size int kargc = 0; //kargc int err; char ** kernel_args; //kargs size_t check; //tt //CHECKS BEFORE WE BEGIN!! if(args == NULL) return EFAULT; if(progname == NULL) return ENOEXEC; struct addrspace* temp =(struct addrspace*)kmalloc(sizeof(struct addrspace)); if(temp == NULL) return ENOMEM; while(args[kargc] != NULL){ kargc++; } //Copy the address space to the one on the kernel heap. err = as_copy(curthread->t_vmspace, &(temp)); //If there is an error on copy. if(err){ kfree(temp); return ENOMEM; } //make a copy of the kernel args on the heap. kernel_args = (char **)kmalloc((kargc)*sizeof(char*)); if(kernel_args == NULL){ kfree(kernel_args); return ENOMEM; } int i,j; //Transfer the items passed in to the kernel heap array. for(i = 0; i<kargc; i++){ string_size = strlen(args[i]); kernel_args[i] =(char *)kmalloc(string_size * sizeof(char)); //If there is not enough memory... if(kernel_args[i]== NULL){ kfree(temp); for(j =0; j<i; j++){ kfree(kernel_args[j]); } kfree(kernel_args); return ENOMEM; } //If we get here, we have successfully copied the arguments. Copy in now. err = copyinstr(args[i], kernel_args[i], string_size+1, &check); //Check if copyinstr Success/Fail if(err){ for(i = 0; i<kargc; i++){ kfree(kernel_args[i]); } kfree(temp); kfree(kernel_args); return err; } } kernel_args[kargc]= NULL; //NOW, WE FOLLOW THE SAME PROCEDURE AS RUNPROGRAM!! /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { kfree(temp); for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); return result; } //Destroy the old address space, and setup the new one! as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; //Setup new vmspace. curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); vfs_close(v); return ENOMEM; } /* Activate vmspace */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); //We now prepare the user stack by placing the arguments on it, like we did in runprogram. result = as_define_stack(curthread->t_vmspace, &stackptr); //If error: if (result) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = temp; for(i = 0; i<kargc; i++) kfree(kernel_args[i]); kfree(kernel_args); return result; } // new addr space user stack vaddr_t new_args[kargc]; int padding; /*place all the strings on the stack*/ for(i = (kargc-1); i>=0 ; i--){ string_size = strlen(kernel_args[i]); padding = ((string_size / 4 ) + 1)*4; stackptr = stackptr - padding; //Do a copyout and check if success/fail err = copyoutstr(kernel_args[i], stackptr, string_size+1, &check); if(err){ return err; } //Success! new_args[i] = stackptr; } new_args[kargc] = NULL; for(i = kargc-1; i>=0 ; i--){ stackptr= stackptr- 4; err = copyout(&(new_args[i]), stackptr, 4); if(err){ return err; } } for(i =0; i<kargc; i++){ kfree(kernel_args[i]); } kfree(temp); kfree(kernel_args); /* Warp to user mode. */ md_usermode(kargc, stackptr, stackptr, entrypoint); }
int sys_execv(const char* program, char** args, int* errno) { int ret; // simple error check // ************* if (program == NULL) { *errno = EFAULT; return -1; } // ************ // copies progname into kernel buffer // *************** char* fname = (char*)kmalloc(PATH_MAX); ret = copyinstr((userptr_t)program, fname, PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } // opens executable // *************** struct vnode* v; ret = vfs_open(fname, O_RDONLY, &v); if (ret != 0) { *errno = ret; return -1; } // ************** // gets argc // ************** int i = 0; while (args[i] != NULL) { i++; } int argc = i; // ************* // copies all arguments into kernel buffer // ***************** char** argv; argv= (char**)kmalloc(PATH_MAX); ret = copyin(args, argv, sizeof(userptr_t)); if (ret != 0) { *errno = EFAULT; return -1; } for(i = 0; i < argc; i++) { argv[i]=(char*)kmalloc(PATH_MAX); ret = copyinstr((userptr_t)args[i],argv[i], PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } } argv[argc] = NULL; // ******************* // error check // ************ if (curthread->t_vmspace != NULL) { as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; } // ************** // creates new address space and loads elf into it // ************** curthread->t_vmspace = as_create(); if (curthread->t_vmspace == NULL) { vfs_close(v); *errno = ENOMEM; return -1; } vaddr_t entrypoint,stackptr; as_activate(curthread->t_vmspace); ret = load_elf(v,&entrypoint); if (ret != 0){ vfs_close(v); *errno = ret; return -1; } vfs_close(v); ret = as_define_stack(curthread->t_vmspace,&stackptr); if (ret != 0) { *errno = ret; return -1; } // ******************** // copies arguments into userstack and increments stack ptr // ************** unsigned int pstack[argc]; for (i = argc-1; i >= 0; i--) { int len = strlen(argv[i]) + 1; stackptr -= len; stackptr -= stackptr%4; ret = copyoutstr(argv[i], (userptr_t)stackptr, PATH_MAX, NULL); if (ret != 0) { *errno = EFAULT; return -1; } pstack[i] = stackptr; } pstack[argc] = (int)NULL; for (i = argc-1; i >= 0; i--) { stackptr -= 4; ret = copyout(&pstack[i], (userptr_t)stackptr, sizeof(pstack[i])); if (ret != 0) { *errno = EFAULT; return -1; } } // free unused memory for (i = 0; i < argc; i++) { kfree(argv[i]); } kfree(argv); kfree(fname); // ******************* // enters usermode, should not return // ******************* md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); // ****************** // if usermode returns, that is an error // ********** *errno = EINVAL; return -1; // ************ }
int runprogram(char *progname, unsigned int argc, char**args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ #if OPT_A3 curthread->t_vmspace->elf_file = kstrdup(progname); #endif result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ 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_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /*********************** stuff for A2 *******************/ char **args_u; /* user space arguments.(array of ptrs to string arguments.*/ /* string length of the arguments */ size_t argstrlen = getlen(argc, args); /* address space for the string arguments value. */ char *arg_str = (char *)stackptr - argstrlen; /* address space for the pointers to string arguments. */ args_u = (char **)arg_str - (argc+1)*sizeof(char**); /* adjust the address so that its divisable by 4 */ args_u = (int)args_u - (int)args_u%4; /* copy the arguments to the user address space */ int len; int i; for (i=0; i<argc; i++){ /* copy a single argument to the user address space */ copyoutstr(args[i], (userptr_t)arg_str, strlen(args[i])+1, &len); /* set the user argument to the current argument string pointer */ args_u[i] = arg_str; /* increment the argument pointer to the next argument */ arg_str += (strlen(args[i])+1)*sizeof(char); } /* set the n+1th argument to be NULL */ args_u[argc] = NULL; /* set the stackptr to the starting point of args_u and adjust the stack pointer */ stackptr = args_u - sizeof(char**) - ((int)args_u%8); /* Warp to user mode. */ md_usermode(argc, (userptr_t) args_u, stackptr, entrypoint); /*********************** end of A2 stuff *****************/ /* md_usermode does not return */ panic("md_usermode 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 nargs) { struct vnode *v; vaddr_t entrypoint, stackptr, arguments[nargs+1], exactnewstackptr; int result, i; size_t len, offset = 0; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ struct addrspace * old_vmspace = curthread->t_vmspace; curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ curthread->t_vmspace = old_vmspace; 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_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ curthread->t_vmspace = old_vmspace; return result; } if(old_vmspace){ as_destroy(old_vmspace); } for (i = 0; i < nargs; i++) { len = strlen(args[i]) + 1; offset += len; arguments[i] = stackptr - offset; copyout((void *)args[i], (userptr_t) arguments[i], (size_t) len); } arguments[nargs] = 0; offset += sizeof(vaddr_t) * (nargs+1); exactnewstackptr = stackptr - offset; stackptr = exactnewstackptr - exactnewstackptr%4; copyout((void *) arguments, (userptr_t) stackptr, (size_t) sizeof(vaddr_t) * (nargs+1)); md_usermode(nargs, (userptr_t) stackptr, stackptr, entrypoint); panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(userptr_t progname, userptr_t args){ /*This function implements the execv functionality*/ size_t get, offset; struct vnode *v; vaddr_t entrypoint, stackptr; userptr_t userdest; int i=0, append_zero, argc=0, result, part=0; char *buf_mem; int n=0; struct addrspace *old_addr = curthread->t_vmspace; char **usr_args = (char**)args; buf_mem = (void *) kmalloc(sizeof(void *)); result = copyin((const_userptr_t)args,buf_mem,4); if (result){ kfree(buf_mem); return result; } lock_acquire(execv_lock); kfree(buf_mem); while(usr_args[argc] != NULL){ argc++; } size_t len_string[argc]; userptr_t user_argv[argc]; char *args_buf = kmalloc(PAGE_SIZE*sizeof(char)); // Check user pointer buf_mem = (char *)kmalloc(1024*sizeof(char)); if (buf_mem == NULL){ result = ENOMEM; kfree(args_buf); } result = copyinstr((const_userptr_t)progname,buf_mem,1024,&get); if (result){ kfree(buf_mem); } //Implementation from runprogram from here /* Open the file. */ result = vfs_open((char *)progname, O_RDONLY, &v); if (result) { kfree(buf_mem); } // Keep old addrspace in case of failure struct addrspace *new_addr = as_create(); if (new_addr == NULL){ result = ENOMEM; vfs_close(v); } while (usr_args[i] != NULL){ result = copyinstr((const_userptr_t)usr_args[i], &args_buf[part], PAGE_SIZE, &len_string[i]); if (result){ as_destroy(new_addr); } part += len_string[i]; i++; } /* Swap addrspace and Activate it*/ curthread->t_vmspace = new_addr; as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } // Copy args to new addrspace offset = 0; for (i=argc-1; i>-1; i--){ part -= len_string[i]; // readjust inherited part index append_zero = (4 - (len_string[i]%4) ) % 4; // Word align offset += append_zero; offset += len_string[i]; user_argv[i] = (userptr_t)(stackptr - offset); result = copyoutstr((const char*)&args_buf[part], user_argv[i], len_string[i], &get); if (result){ curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); } } // 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) curthread->t_vmspace = old_addr; as_activate(curthread->t_vmspace); userdest += 4; } // Wrap up kfree(args_buf); vfs_close(v); /* Warp to user mode. */ md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); lock_release(execv_lock); return EINVAL; }
int sys_execv(const char *program, char *args[]) { char **args_copy; struct vnode *v; int argc, result, index; vaddr_t stackptr, entrypoint; // get number of arguments for (argc=0; args[argc] != NULL; argc++); // save out copy of args before current address space is scrapped char *strtemp; args_copy = kmalloc(argc * sizeof(char *) + 1); for (index=0; index<argc; index++) { strtemp = kmalloc(sizeof(char)); strcpy(strtemp, args[index]); args_copy[index] = strtemp; } // do parameter checks if (program != args[0]) { //kprintf("Mismatch: program name %s does not match first argument %s.\n", program, args[0]); } assert(args[argc] == NULL); // open the program file result = vfs_open((char *)program, O_RDONLY, &v); if (result) { kprintf("open program file: %s\n", strerror(result)); return result; } // configure the user address space curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } as_activate(curthread->t_vmspace); // load the elf result = load_elf(v, &entrypoint); if (result) { kprintf("load elf: %s\n", strerror(result)); vfs_close(v); return result; } // close the program file since we're done with it vfs_close(v); // define the user stack result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { kprintf("define user stack: %s\n", strerror(result)); return result; } // put arguments onto user stack store_program_arguments(argc, args_copy, &stackptr); kfree(args_copy); // Warp to user mode md_usermode(argc, (userptr_t)stackptr, stackptr, entrypoint); // md_usermode should not return (otherwise its an error) panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(const char *progname, char**args) { kprintf("hello world"); struct vnode *v; vaddr_t entrypoint, stackptr; int result; int argc = getargc(args); /* Copy the arguments into the kernel buffer */ char** kbuffer = kmalloc(argc*sizeof(char*)); int i; for (i=0; i<argc; i++) { kbuffer[i] = kmalloc(strlen(args[i])*sizeof(char*)+1); copyinstr(args[i], kbuffer[i], strlen(args[i])*sizeof(char*)+1, NULL); } args = kbuffer; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* This is not the first process, we have to make sure the previous process address space is not NULL. */ assert(curthread->t_vmspace != NULL); /* Destroy the old process address space */ as_destroy(curthread->t_vmspace); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace == NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } /* Done with the file now. */ vfs_close(v); /* Free the current process user stack */ kfree(curthread->t_stack); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /* copy arguments to user space */ char **args_u; /* user space arguments.(array of ptrs to string arguments.*/ /* string length of the arguments */ size_t argstrlen = getlen(argc, args); /* address space for the string arguments value. */ char* arg_str = (char *) stackptr - argstrlen; /* address space for the pointers to string arguments. */ args_u = (char **) arg_str - (argc + 1) * sizeof (char**); /* adjust the address so that its divisable by 4 */ args_u = (int) args_u - (int) args_u % 4; /* copy the arguments to the user address space */ int len; for (i = 0; i < argc; i++) { /* copy a single argument to the user address space */ copyoutstr(args[i], (userptr_t) arg_str, strlen(args[i]) + 1, &len); /* set the user argument to the current argument string pointer */ args_u[i] = arg_str; /* increment the argument pointer to the next argument */ arg_str += (strlen(args[i]) + 1) * sizeof (char); } /* set the n+1th argument to be NULL */ args_u[argc] = NULL; /* set the stackptr to the starting point of args_u and adjust the stack pointer */ stackptr = args_u - sizeof (char**) - ((int)args_u%8); /* Warp to user mode. */ md_usermode(argc, (userptr_t) args_u, stackptr, entrypoint); /*********************** end of A2 stuff *****************/ /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(const char *prog_path, char **args) { int spl = splhigh(); // the prog_path is in user space, we need to copy it into kernel space if(prog_path == NULL) { return EINVAL; } // frist the program path char* program = (char *) kmalloc(MAX_PATH_LEN * sizeof(char)); int size; int result = copyinstr((const_userptr_t) prog_path, program, MAX_PATH_LEN, &size); if(result) { kfree(program); return EFAULT; } // arguments char** argv = (char**) kmalloc(sizeof(char**)); // char** argv; result = copyin((const_userptr_t)args, argv, sizeof(char **)); if(result) { kfree(program); kfree(argv); return EFAULT; } // count the number of arguments int i = 0; while(args[i] != NULL){ argv[i] = (char*) kmalloc(sizeof(char) * MAX_ARG_LEN); if(copyinstr((const_userptr_t) args[i], argv[i], MAX_ARG_LEN, &size) != 0) { return EFAULT; } i++; } argv[i] = NULL; // runprogram_exev_syscall(program, argv, i); /*********************** runprogram starts*****************/ struct vnode *v; vaddr_t entrypoint, stackptr; result = vfs_open(program, O_RDONLY, &v); if (result) { return result; } // destroy the old addrspace if(curthread->t_vmspace != NULL){ as_destroy(curthread->t_vmspace); curthread->t_vmspace = NULL; } assert(curthread->t_vmspace == NULL); // Create a new address space. curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } // Activate it. as_activate(curthread->t_vmspace); // Load the executable. result = load_elf(v, &entrypoint); // Load an ELF executable user program into the current address space and // returns the entry point (initial PC) for the program in ENTRYPOINT. if (result) { vfs_close(v); return result; } vfs_close(v); result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { // thread_exit destroys curthread->t_vmspace return result; } int narg = i - 1; int j; for(j = 0; j < narg; ++j){ int len = 1 + strlen(argv[j]); len = ROUNDUP(len, 8); stackptr -= len; result = copyoutstr(argv[j],(userptr_t)stackptr, len, &len); if(result){ return result; } argv[j] = (char*)stackptr; } argv[i] = NULL; size_t arg_size = (narg + 1) * sizeof(char*); arg_size = ROUNDUP(arg_size, 8); // align the stackptr to 8 byte aligned stackptr -= arg_size; // stackptr -= stackptr % 8; copyout(argv, stackptr, (narg + 1) * 4); md_usermode(i, stackptr, stackptr, entrypoint); panic("md_usermode returned\n"); return EINVAL; }
int runprogram(char *progname, char** args, int num) { struct vnode *v; vaddr_t entrypoint, stackptr; int result; int s_size = 0; int kargc = num; int i=0, err; size_t tt; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ 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_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } if(args!=NULL) { vaddr_t new_args[kargc]; vaddr_t new_argv; int w_size; /*word alligned size of string*/ /*place all the strings on the stack*/ /*carefully ignore the first element because contains the program name*/ for(i = (kargc-1); i>=0 ; i--) { s_size = strlen(args[i]); w_size = ((s_size / 4 ) + 1)*4; stackptr -= w_size; err = copyoutstr(args[i], stackptr, s_size+1, &tt); if(err!=0){ kprintf("2: err %d, the official length is %d, the given length is %d \n ", err, tt, s_size+1); return err; } new_args[i] = stackptr; } kprintf("finished all my strlens \n"); /*place all the pointers to the strings on the stack*/ new_args[kargc] = NULL; for(i = kargc; i>=0 ; i--){ stackptr-= 4; err = copyout(&(new_args[i]), stackptr, 4); if(err!=0){ kprintf("3: err %d \n ", err); return err; } } /* Warp to user mode. */ md_usermode(kargc, stackptr, stackptr, entrypoint); } else md_usermode(0, NULL, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode 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; int err; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ 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_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /* Warp to user mode. */ // --- fk --- // attaching the filedescriptors 1 (stdout) and 2 (stderr) to console err = vfs_open("con:", O_WRONLY, &filetable[1]); filetable[2] = filetable[1]; // --- /fk --- md_usermode(0 /*argc*/, NULL /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
/* * runprogram is run from menu, and its arguments * are passed by thread_fork (a ptr & a int) * so we need to construct a struct to store progname and args */ int runprogram(struct runprogram_info *prog_info) { char *progname = prog_info->progname; struct vnode *v; vaddr_t entrypoint, stackptr; int result; /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* * if runprogram is called by sys_execv, it is for sure that * curthread has its own user addr_space already. * we need to destroy it. * if runprogram is called by menu, there is no addrspace created. */ // =========================================== struct addrspace *old_as = curthread->t_vmspace; if (old_as != NULL) { as_destroy(old_as); curthread->t_vmspace = NULL; } // =========================================== /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ // entrypoint is set by load_elf result = load_elf(v, &entrypoint); // =========================================== /* * in dumbvm, we only need to set up the addrspace for stack * now, we need to load stack (set up page table, without dealing with the content) */ // =========================================== if (result) { /* thread_exit destroys curthread->t_vmspace */ // which means runprogram is called by some other function, // and when it returns, thread_exit will be called outside runprogram // that's why runprom should not return 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_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } // ============================================ size_t len; void *ks_start = setup_args_mem(prog_info, &stackptr, &len); int err = copyout(ks_start, stackptr, len); if (err != 0) { panic("runprogram: copyout err!\n"); } /* int i; for (i = 0; i < len/4; i++) { //i in terms of word //kfree will free 4 bytes at a time? kfree((int *)((int *)ks_start+i)); } */ kfree(ks_start); //kprintf("copyout result: %d\n", err); // ============================================ /* Warp to user mode. */ int nargc = prog_info->argc; kfree(prog_info); //cmd_coremapstats(1, NULL); md_usermode(nargc /*argc*/, stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int runprogram_args(char *progname, int argc, char **args) { struct vnode *v; vaddr_t entrypoint, stackptr; int result, i; size_t buflen = 0; char **argv = kmalloc(sizeof(char*) * argc); size_t *offsets = kmalloc(sizeof(size_t) * argc); //kprintf("We have %d args in runprogram_args.\n", argc); for (i = 0; i < argc; ++i) { size_t len = strlen(args[i]) + 1; argv[i] = kstrdup(args[i]); offsets[i] = buflen; buflen += len; } /* Open the file. */ result = vfs_open(progname, O_RDONLY, &v); if (result) { return result; } /* We should be a new thread. */ assert(curthread->t_vmspace == NULL); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ 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_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } /* Copy arguments to stack */ userptr_t argbase, userargv, arg, argv_base; vaddr_t stack = stackptr - buflen; stack -= (stack & (sizeof(void *) - 1)); argbase = (userptr_t)stack; for (i = 0; i < argc; ++i) { result = copyout(argv[i], argbase + offsets[i], strlen(argv[i]) + 1); if (result) return result; } stack -= (argc + 1) * sizeof(userptr_t); userargv = (userptr_t)stack; argv_base = (userptr_t)stack; for (i = 0; i < argc; i++) { arg = argbase + offsets[i]; result = copyout(&arg, userargv, sizeof(userptr_t)); if (result) return result; userargv += sizeof(userptr_t); } arg = NULL; result = copyout(&arg, userargv, sizeof(userptr_t)); if (result) return result; stackptr = stack + sizeof(userptr_t); /* Warp to user mode. */ md_usermode(argc, argv_base, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }
int sys_execv(const char *prog, char *const *args){ char *tempdest,**dest; const char *userdata; int i,j=0,count=0,padding_start=0,next=0,real_counter=0,retval,len; struct vnode *v; //dest=kmalloc(sizeof(char*)*strlen(args)); len=sizeof(args)/sizeof(char*); //no of elements in args dest=kmalloc(len*sizeof(char*)); vaddr_t entrypoint, stackptr; int result; //=kmalloc(len); //int len=sizeof(prog)+sizeof(args); userdata=prog; kprintf("\n in execv1"); //copyin pointers in kernel buffer and align by 4 kprintf("\n in execv2"); do{ kprintf("\n in execv2"); size_t len=strlen(userdata);// tempdest=kmalloc(sizeof(char)*len); retval=copyin((const_userptr_t)userdata,tempdest,len); if(retval){ kprintf("\nreturning"); return retval; } kprintf("\n %s %d %d",userdata,retval,len); for(count=0;tempdest[count]!='\0';count++); padding_start=count; //count-1 should be a multiple of 4 else find the next multiple count=((count-1)%4==0)?count-1:count+(count-1)%4; for(i=padding_start;i<count;i++){ tempdest[i]='\0'; } kprintf("\ncrossed"); dest[j]=kmalloc(sizeof(char)*strlen(tempdest)); dest[j]=tempdest; kprintf("\ncrossed"); userdata=NULL; userdata=args[next]; next++;j++;real_counter=j; }while(userdata!=NULL); kprintf("\ncrossed"); //open the executable, create new addr space and load elf into it kprintf("\n in execv3"); /* Open the file. */; result = vfs_open(prog, O_RDONLY, &v); kprintf("\n vfs_open result::%d",result); if (result) { return result; } kprintf("\ncrossed"); /* Create a new address space. */ curthread->t_vmspace = as_create(); if (curthread->t_vmspace==NULL) { vfs_close(v); return ENOMEM; } kprintf("\ncrossed"); /* Activate it. */ as_activate(curthread->t_vmspace); /* Load the executable. */ result = load_elf(v, &entrypoint); if (result) { /* thread_exit destroys curthread->t_vmspace */ vfs_close(v); return result; } kprintf("\ncrossed"); /* Done with the file now. */ vfs_close(v); /* Define the user stack in the address space */ result = as_define_stack(curthread->t_vmspace, &stackptr); if (result) { /* thread_exit destroys curthread->t_vmspace */ return result; } kprintf("\ncrossed"); //copy args into user stack kprintf("\n in execv4"); /*for(i=0;i<len;i++){ int len_each_str=strlen(dest[i]); char *temp=dest[i]; for(j=0;j<len_each_str;j++){ //stackptr[i]=*dest; stackptr[i]=temp[j]; } }*/ copyout(dest,stackptr,real_counter); //return to user mode using enter_new_process kprintf("\n in execv5,%d",len); /* Warp to user mode. */ md_usermode(len /*argc*/, stackptr /*userspace addr of argv*/, stackptr, entrypoint); /* md_usermode does not return */ panic("md_usermode returned\n"); return EINVAL; }