int mon_start_user (int argc, char **argv, struct Trapframe *tf) { if (CID != 0) { dprintf( "The process is already running. If you want to run the program again, please restart qemu.\n"); return 0; } uint8_t * exe = _binary___obj_proc_dummy_dummy_start; CID = alloc_mem_quota (0, 1024 * 1024); elf_load (exe, CID); dprintf("Program 0x%08x is loaded.\n", exe); set_pdir_base (CID); entry_t entry = (entry_t) elf_entry (exe); entry(); return 0; }
unsigned int proc_create(void *elf_addr, unsigned int quota) { unsigned int pid, id; id = get_curid(); pid = thread_spawn((void *) proc_start_user, id, quota); elf_load(elf_addr, pid); uctx_pool[pid].es = CPU_GDT_UDATA | 3; uctx_pool[pid].ds = CPU_GDT_UDATA | 3; uctx_pool[pid].cs = CPU_GDT_UCODE | 3; uctx_pool[pid].ss = CPU_GDT_UDATA | 3; uctx_pool[pid].esp = VM_USERHI; uctx_pool[pid].eflags = FL_IF; uctx_pool[pid].eip = elf_entry(elf_addr); seg_init_proc(get_pcpu_idx(), pid); return pid; }
int kexecve(const char *filename, char *const argv[], char *const envp[]) { // If first line is #! exec interpreter and feed // it the command line options and the file. // Otherwise, load the entire file into RAM, // and call image_load. // On error, return -1 and set errno. // On success, no return (0). // The latter implies we have to setup the process context // and free prior RAM. char *image = NULL; unsigned int image_size = 0; unsigned int i = 0; unsigned int j = 0; unsigned int start = 0; unsigned int end = 0; unsigned int len = 0; int argc = 0; char interpreter[MAX_PATH] = {0}; char args[MAX_PATH] = {0}; char *arg = NULL; char **argv2 = NULL; static int nr_recursion = 0; int delete_argv2 = 0; start_t elf_entry = NULL; unsigned char *exec = NULL; unsigned int exec_size = 0; asm_disable_interrupt(); if(!file_load(filename, &image, &image_size)) { printk("execve:: error loading file\n"); asm_enable_interrupt(); return -1; } // TODO - We should store argv2 in the process and // and mark if it should be free'd on exit. // Handle interpreter invocation. if(image[0] == '#' && image[1] == '!') { #ifdef _TEST_EXEC printk("execve:: image = [%s]\n", image); #endif for(i = 2; i < image_size; ++i) { if(!isspace(image[i])) { start = i; break; } } for(i = start + 1; i < image_size; ++i) { if(isspace(image[i])) { end = i; break; } } for(i = start,j=0; i < end; ++i,++j) { if(j >= MAX_PATH) { printk("execve:: interpreter name too long\n"); asm_enable_interrupt(); return -1; } interpreter[j] = image[i]; } for(i = end,j=0; i < image_size; ++i,++j) { if(image[i]=='\n') { break; } args[j]=image[i]; } arg = strtok(args," \t"); i = 0; while(arg) { if(!argv2) { argv2 = (char **)malloc(sizeof(char *) * MAX_PATH + 1); } if(i >= MAX_PATH) { free((void *)argv2); printk("execve:: error processing interpreter args\n"); asm_enable_interrupt(); return -1; } len = strlen(arg); argv2[i] = (char *)malloc(len + 1); strcpy(argv2[i],arg); argv2[i][len]='\0'; ++i; arg = strtok(NULL," \t"); } /* Now get the rest of the args. */ j = 0; while(i < MAX_PATH && argv[j]) { len = strnlen(argv[j],1024); argv2[i] = (char *)malloc(len + 1); strncpy(argv2[i],argv[j],1024); argv2[i][len] = '\0'; ++i; ++j; } if(argv[j] != NULL) { free((void *)argv2); printk("execve:: error argv[j] != NULL\n"); asm_enable_interrupt(); return -1; } /* Now copy the script filename. */ if(i >= MAX_PATH) { free((void *)argv2); printk("execve:: error i >= MAX_PATH\n"); asm_enable_interrupt(); return -1; } #if 0 /* argv[0] should be the filename */ len = strlen(filename); argv2[i] = (char *)malloc(len + 1); strcpy(argv2[i],filename); argv2[i][len]='\0'; ++i; if(i >= MAX_PATH) { free((void *)argv2); printk("execve:: error i >= MAX_PATH[2]\n"); return -1; } #endif argv2[i]='\0'; // Free the original file loaded. if(!file_unload(&image)) { free((void *)argv2); printk("execve:: error unloading file [%s]\n",filename); asm_enable_interrupt(); return -1; } #ifdef _TEST_EXEC printk("interpreter [%s]\n",interpreter); for(i = 0; argv2[i]; ++i) { printk("argv2[%d]=[%s]\n",i,argv2[i]); } for(i = 0; envp[i]; ++i) { printk("envp[%d]=[%s]\n",i,envp[i]); } return 0; #else // Call ourselves with the proper paramters. if(nr_recursion > EXEC_MAX_RECURSION) { printk("execve:: error nr_recursion > EXEC_MAX_RECURSION\n"); asm_enable_interrupt(); return -1; } nr_recursion++; asm_enable_interrupt(); return kexecve(interpreter, argv2, envp); #endif } // If we are in a recursive call, then we // allocated argv2 and it must be free'd. if(nr_recursion) { delete_argv2 = 1; } else { delete_argv2 = 0; argv2 = (char **)argv; } for(i = 0; argv2[i]; ++i) { argc++; } nr_recursion--; // At this point, the ELF image is in RAM. // Parse it out and jump to it. LINE(); elf_entry = image_load(image, image_size, &exec, &exec_size); LINE(); // TODO - Do we put envp into the process struct // and make it accessible via getenv() ? #ifdef _TEST_EXEC printk("elf_entry=[%x]\n",elf_entry); LINE(); i = elf_entry(); printk("returns =[%d]\n",i); #endif LINE(); if(!file_unload(&image)) { if(nr_recursion) { for(i = 0; i < argc; ++i) { free((void *)argv2[i]); } free((void *)argv2); } #ifdef _TEST_EXEC munmap(elf_entry, image_size); #endif printk("execve:: error unloading file [%s]\n",filename); return -1; } #ifdef _TEST_EXEC munmap(exec,exec_size); #else // Kernel // // - Set up the entry point and args // into the process structure... // Mark flag for first time execution // as we need to call into the entry point // when we schedule the process. // - Free the old process image... // // We have:- // // exec - memory image to free // exec_size - size of image // elf_entry - pointer to the start method // argc - argument count // argv2 - arguments // envp - environment // delete_argv2 - flag to indicate if argv2 should be free'd // // Free up prior memory. // Should also happen in exit.c. if(current_process->p_exec) { mem_unset_read_only(current_process->p_exec, current_process->p_exec_size); free((void *)current_process->p_exec); } if(current_process->p_delete_argv) { for(i = 0; i < current_process->p_argc; ++i) { free((void *)current_process->p_argv[i]); } free((void *)current_process->p_argv); } // Close all open files. for(i = 0; i < MAX_FILES; ++i) { for(j = 0; j < MAX_FILES; ++j) { if(current_process->file_desc[i] == &(current_process->file_tab[j])) { kclose(i); } } } // Close all open directories. for(i = 0; i < MAX_DIR; ++i) { if(current_process->dir_tab[i].__allocation == DEV_BLOCK_SIZE) { kclosedir(&(current_process->dir_tab[i])); } } // Setup our new image. current_process->p_exec = exec; current_process->p_exec_size = exec_size; current_process->p_elf_entry = elf_entry; current_process->p_argc = argc; current_process->p_argv = argv2; current_process->p_envp = envp; current_process->p_delete_argv = delete_argv2; current_process->p_first_exec = 1; asm_enable_interrupt(); schedule(); #endif return 0; }/* kexecve */