static void _vm_rstep(VMState *state, unsigned long nsteps, VMStateDiff **diff, bool *hit_bp, bool first) { VMSingleStateDiff *singlediff; VMStateDiff *next; *hit_bp = false; state->stopped_running = false; while (nsteps-- && (*diff)->next) { if (!first && _hit_breakpoint(state)) { *hit_bp = true; break; } first = false; state->cycles = (*diff)->cycles; SETPC(state, (*diff)->pc); singlediff = (*diff)->singlediff; /* Apply singlediff changes */ while (singlediff) { vm_write_nbytes( state, NULL, singlediff->type, singlediff->location, singlediff->oldval, singlediff->nbytes ); singlediff = singlediff->next; } /* Deallocate diff */ _vm_close_iterable((VMIterable *) (*diff)->singlediff); next = (*diff)->next; free(*diff); *diff = next; } }
/* initialization */ static void initialize(void) { int i; for (i=0; i<NMSGS-1; i++) messages[i].next = &messages[i+1]; messages[NMSGS-1].next = NULL; for (i=0; i<NTHREADS-1; i++) threads[i].next = &threads[i+1]; threads[NTHREADS-1].next = NULL; for (i=0; i<NTHREADS; i++) { setjmp( threads[i].context ); SETSTACK( &threads[i].context, &stacks[i] ); SETPC( &threads[i].context, run ); threads[i].waitsFor = NULL; } thread0.next = NULL; thread0.waitsFor = NULL; thread0.msg = NULL; TIMER_INIT(); }
/* Load the loadable segments of the program into the VMState. Disassemble The Executable Segment. */ static bool _elf32_read(VMState *state, char *program, size_t program_size) { Elf32_Ehdr *ehdr; Elf32_Phdr *phdr; char *rom; int i; struct _mapping *rommapping = get_info_type_mapping(VM_INFO_ROM); rom = (char *) state->chunk + rommapping->offset; ehdr = (Elf32_Ehdr *) program; SETPC(state, ehdr->e_entry); if (!ehdr->e_phoff) { vm_seterrno(VM_NO_SEGMENTS); return false; } phdr = (Elf32_Phdr *) (program + ehdr->e_phoff); for (i = 0; i < ehdr->e_phnum; i++) { if (phdr->p_type & PT_LOAD) { char *startaddr; startaddr = rom + LOAD_ADDRESS; if (phdr->p_flags & PF_X) { /* executable segment, disassemble */ if (state->instructions) { /* Will there ever be multiple executable segments? Text and data segments may both be executable. */ vm_seterrno(VM_MULTIPLE_EXECUTABLE_SEGMENTS); return false; } state->instructions_size = (phdr->p_filesz / sizeof(OPCODE_TYPE)); state->instructions = disassemble( (OPCODE_TYPE *) (program + phdr->p_offset), state->instructions_size); state->executable_segment_offset = LOAD_ADDRESS; } if (LOAD_ADDRESS + phdr->p_memsz > rommapping->end - rommapping->offset) { vm_seterrno(VM_ERROR_PROGRAM_TOO_BIG); return false; } /* load segment into the ROM of the VM */ memcpy(startaddr, program + phdr->p_offset, phdr->p_filesz); /* NUL the rest */ memset(startaddr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); } phdr++; } if (!_vm_errno && !state->instructions) vm_seterrno(VM_NO_EXECUTABLE_SEGMENT); return (bool) state->instructions; }