struct execution_result executor_instruction_execute(uint8_t *instruction, size_t instruction_length, struct tracking_trace *trace, struct context *context, void *code, struct tbgen_result tbgen_result) { result.type = EXECUTION_RTYPE_SUCCESS; struct stack *mappings = stack_init(); char retval = map_and_copy(mappings, trace, context, tbgen_result); if(retval) { result.type = EXECUTION_RTYPE_MAPPING_ERROR; goto unmap_all; } struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_sigaction = sighandler; act.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &act, NULL); sigaction(SIGILL, &act, NULL); sigaction(SIGALRM, &act, NULL); sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGSYS, &act, NULL); sigaction(SIGTRAP, &act, NULL); // alarm(1); // __asm__ ("mov $0x00112244556677, %rsi\nbtc %ax, (%rsi)\n"); #ifndef DRYRUN if(!setjmp(jbuf)) ((void (*)(void))code)(); else result.type = EXECUTION_RTYPE_SIGNAL; #endif alarm(0); act.sa_sigaction = NULL; sigaction(SIGSEGV, &act, NULL); sigaction(SIGILL, &act, NULL); sigaction(SIGALRM, &act, NULL); sigaction(SIGBUS, &act, NULL); sigaction(SIGFPE, &act, NULL); sigaction(SIGSYS, &act, NULL); sigaction(SIGTRAP, &act, NULL); write_back(trace, context); unmap_all: unmap_all(mappings); stack_free(mappings); executor_virt_calc(context); return result; }
/* * syscall_fork * * Implements the fork system call, which makes a copy of an existing process. * After this call has completed, the two processes will have exactly the same * state, with the exception of their process ids and the return value from the * fork call. The return value that the parent process sees will be the (non-zero) * process id of the child. The child will see a return value of 0. Based on this, * each of the two processes can go their separate ways, with the child process * typically taking completely different code * path, such as a call to exec. * * This call is an alternative to start_process. fork is the standard way to create * processes under UNIX, and in most cases is the *only* way for new processes to * be started, at least from user-space. * * The *full* state of a process must be copied here, including all fields of the * process object, and all of the memory associated with the process in its various * segments (text, data, and stack). */ pid_t syscall_fork(regs * r) { /* * Find a free process identifier */ pid_t child_pid = get_free_pid(); if (0 > child_pid) return -EAGAIN; process *parent = current_process; process *child = &processes[child_pid]; memset(child, 0, sizeof(process)); child->pid = child_pid; child->parent_pid = parent->pid; child->exists = 1; /* * Create a page directory for the new process, and set the segment ranges. * Note that we have to temporarily disable paging here, because we need to * deal with physical memory when allocating a page directory and setting up * the mappings. */ disable_paging(); child->pdir = (page_dir) alloc_page(); child->text_start = parent->text_start; child->text_end = parent->text_end; child->data_start = parent->data_start; child->data_end = parent->data_end; child->stack_start = parent->stack_start; child->stack_end = parent->stack_end; /* * Identity map memory 0-6Mb */ unsigned int addr; for (addr = 0 * MB; addr < 6 * MB; addr += PAGE_SIZE) map_page(child->pdir, addr, addr, PAGE_USER, PAGE_READ_ONLY); /* * Copy parent's text, data, and stack segments to child */ map_and_copy(parent->pdir, child->pdir, child->text_start, child->text_end); map_and_copy(parent->pdir, child->pdir, child->data_start, child->data_end); map_and_copy(parent->pdir, child->pdir, child->stack_start, child->stack_end); enable_paging(current_process->pdir); /* * Copy file handles. The reference count is increased on each of them, so * that we can keep track of how many file descriptors refere to each file * handle. This information is needed so we know when to destroy a file handle * (i.e. when its reference count reaches 0). */ int i; for (i = 0; i < MAX_FDS; i++) { if (NULL != parent->filedesc[i]) { child->filedesc[i] = parent->filedesc[i]; child->filedesc[i]->refcount++; } } /* * Copy the saved CPU registers of the current process, which determines its * execution state (instruction pointer, stack pointer etc.) */ child->saved_regs = *r; child->saved_regs.eax = 0; /* child's return value from fork */ memmove(child->cwd, parent->cwd, PATH_MAX); /* * Place the process on the ready list, so that it can begin execution on a * subsequent context switch */ child->ready = 1; list_add(&ready, child); /* * Return the child's process id... note that this value will only go to the * parent, since we set the child's return value from fork above */ return child_pid; }