VMStateDiff * vm_rstep(VMState *state, int nsteps, VMStateDiff *diff, bool *hit_bp) { VMSingleStateDiff *singlediff; VMStateDiff *next; *hit_bp = false; while (nsteps--) { state->cycles = diff->cycles; state->pc = diff->pc; singlediff = diff->singlediff; while (singlediff) { OPCODE_TYPE *location; location = _get_location(state, singlediff->type, singlediff->location); *location = singlediff->oldval; singlediff = (VMSingleStateDiff *) singlediff->next; } /* unwind the diff list */ _vm_close_iterable((VMIterable *) diff->singlediff); next = (VMStateDiff *) diff->next; free(diff); diff = next; } return diff; }
bool vm_write(VMState *state, VMStateDiff *diff, VMInfoType type, size_t destaddr, OPCODE_TYPE value) { OPCODE_TYPE *dest; VMSingleStateDiff *singlediff; if (!(dest =_get_location(state, type, destaddr))) goto error; /* update our diffs */ err_malloc((singlediff = malloc(sizeof(VMSingleStateDiff)))); singlediff->oldval = *dest; singlediff->newval = value; singlediff->type = type; singlediff->location = destaddr; singlediff->next = (VMIterable *) diff->singlediff; diff->singlediff = singlediff; /* finally, write the value */ *dest = value; return true; error: return false; }
OPCODE_TYPE vm_info(VMState *state, VMInfoType type, size_t vmaddr, bool *errorp) { OPCODE_TYPE *dest; if (!(dest = _get_location(state, type, vmaddr))) { if (errorp) *errorp = true; return 0; } return *dest; }
OPCODE_TYPE vm_info(VMState *state, VMInfoType type, size_t vmaddr, bool *successp) { OPCODE_TYPE *dest; if (!(dest = _get_location(state, type, vmaddr))) { if (successp) *successp = false; return 0; } if (successp) *successp = true; return *dest; }
static void _vm_rstep(VMState *state, int 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; #if 0 printf("Applying diff: "); _print_diff(state, *diff); #endif state->cycles = (*diff)->cycles; state->registers[PC] = (*diff)->pc; singlediff = (*diff)->singlediff; /* Apply singlediff changes */ while (singlediff) { OPCODE_TYPE *location; location = _get_location(state, singlediff->type, singlediff->location); *location = singlediff->oldval; singlediff = singlediff->next; } /* Deallocate diff */ _vm_close_iterable((VMIterable *) (*diff)->singlediff); next = (*diff)->next; free(*diff); *diff = next; } }
BIGTYPE vm_info_nbytes(VMState *state, VMInfoType type, size_t vmaddr, bool *errorp, int nbytes) { BIGTYPE result = 0; char *location; if (!(location = _get_location(state, type, vmaddr, NULL))) { if (errorp) *errorp = true; return 0; } memcpy(&result, location, nbytes); vm_convert_endianness((char *) &result, nbytes); return result; }
bool vm_write_nbytes(VMState *state, VMStateDiff *diff, VMInfoType type, size_t destaddr, BIGTYPE value, int nbytes) { char *location; VMSingleStateDiff *singlediff; if (!(location = _get_location(state, type, destaddr, NULL))) goto error; if (diff) { /* update our diffs */ err_malloc((singlediff = malloc(sizeof(VMSingleStateDiff)))); /* We already did error checking, don't do it again. Read and store in host endianness so rstep can write to uC endianness. */ singlediff->oldval = vm_info(state, type, destaddr, NULL); #ifdef VM_DEBUG singlediff->newval = value; #endif singlediff->type = type; singlediff->location = destaddr; singlediff->nbytes = nbytes; singlediff->next = diff->singlediff; diff->singlediff = singlediff; } /* finally, write the value */ vm_convert_endianness((char *) &value, nbytes); memcpy(location, &value, nbytes); return true; error: return false; }