int before_block_exec(CPUState *env, TranslationBlock *tb) { uint64_t count = rr_get_guest_instr_count(); if (!snipping && count+tb->icount > start_count) { sassert((oldlog = fopen(rr_nondet_log->name, "r")), 8); sassert(fread(&orig_last_prog_point, sizeof(RR_prog_point), 1, oldlog) == 1, 9); printf("Original ending prog point: "); rr_spit_prog_point(orig_last_prog_point); actual_start_count = count; printf("Saving snapshot at instr count %lu...\n", count); // Force running state global_state_store_running(); printf("writing snapshot:\t%s\n", snp_name); QIOChannelFile* ioc = qio_channel_file_new_path(snp_name, O_WRONLY | O_CREAT, 0660, NULL); QEMUFile* snp = qemu_fopen_channel_output(QIO_CHANNEL(ioc)); qemu_savevm_state(snp, NULL); qemu_fclose(snp); printf("Beginning cut-and-paste process at prog point:\n"); rr_spit_prog_point(rr_prog_point()); printf("Writing entries to %s...\n", nondet_name); newlog = fopen(nondet_name, "w"); sassert(newlog, 10); // We'll fix this up later. RR_prog_point prog_point = {0}; fwrite(&prog_point.guest_instr_count, sizeof(prog_point.guest_instr_count), 1, newlog); fseek(oldlog, ftell(rr_nondet_log->fp), SEEK_SET); // If there are items in the queue, then start copying the log // from there RR_log_entry *item = rr_get_queue_head(); if (item != NULL) fseek(oldlog, item->header.file_pos, SEEK_SET); while (prog_point.guest_instr_count < end_count && !feof(oldlog)) { prog_point = copy_entry(); } if (!feof(oldlog)) { // prog_point is the first one AFTER what we want printf("Reached end of old nondet log.\n"); } else { printf("Past desired ending point for log.\n"); } snipping = true; printf("Continuing with replay.\n"); } if (snipping && !done && count > end_count) { end_snip(); rr_end_replay_requested = 1; } return 0; }
int before_block_exec(CPUState *env, TranslationBlock *tb) { uint64_t count = rr_prog_point.guest_instr_count; if (!snipping && count+tb->num_guest_insns > start_count) { sassert((oldlog = fopen(rr_nondet_log->name, "r"))); sassert(fread(&orig_last_prog_point, sizeof(RR_prog_point), 1, oldlog) == 1); printf("Original ending prog point: "); rr_spit_prog_point(orig_last_prog_point); actual_start_count = count; printf("Saving snapshot at instr count %lu...\n", count); do_savevm_rr(get_monitor(), snp_name); printf("Beginning cut-and-paste process at prog point:\n"); rr_spit_prog_point(rr_prog_point); printf("Writing entries to %s...\n", nondet_name); newlog = fopen(nondet_name, "w"); sassert(newlog); // We'll fix this up later. RR_prog_point prog_point = {0, 0, 0}; fwrite(&prog_point, sizeof(RR_prog_point), 1, newlog); fseek(oldlog, ftell(rr_nondet_log->fp), SEEK_SET); RR_log_entry *item = rr_get_queue_head(); while (item != NULL && item->header.prog_point.guest_instr_count < end_count) { write_entry(item); item = item->next; } while (prog_point.guest_instr_count < end_count && !feof(oldlog)) { prog_point = copy_entry(); } if (!feof(oldlog)) { // prog_point is the first one AFTER what we want printf("Reached end of old nondet log.\n"); } else { printf("Past desired ending point for log.\n"); } snipping = true; printf("Continuing with replay.\n"); } if (snipping && !done && count > end_count) { end_snip(); init_timer_alarm(); rr_do_end_replay(0); } return 0; }
static void end_snip(void) { RR_prog_point prog_point = rr_prog_point(); printf("Ending cut-and-paste on prog point:\n"); rr_spit_prog_point(prog_point); prog_point.guest_instr_count -= actual_start_count; RR_header end; end.kind = RR_LAST; end.callsite_loc = RR_CALLSITE_LAST; end.prog_point = prog_point; end.prog_point.guest_instr_count -= actual_start_count; sassert(fwrite(&(end.prog_point), sizeof(end.prog_point), 1, newlog) == 1); sassert(fwrite(&(end.kind), sizeof(end.kind), 1, newlog) == 1); sassert(fwrite(&(end.callsite_loc), sizeof(end.callsite_loc), 1, newlog) == 1); rewind(newlog); fwrite(&prog_point, sizeof(RR_prog_point), 1, newlog); fclose(newlog); done = true; }
static void rr_spit_log_entry(RR_log_entry item) { rr_spit_prog_point(item.header.prog_point); switch (item.header.kind) { case RR_INPUT_1: printf("\tRR_INPUT_1 %d from %s\n", item.variant.input_1, get_callsite_string(item.header.callsite_loc)); break; case RR_INPUT_2: printf("\tRR_INPUT_2 %d from %s\n", item.variant.input_2, get_callsite_string(item.header.callsite_loc)); break; case RR_INPUT_4: printf("\tRR_INPUT_4 %d from %s\n", item.variant.input_4, get_callsite_string(item.header.callsite_loc)); break; case RR_INPUT_8: printf("\tRR_INPUT_8 %ld from %s\n", item.variant.input_8, get_callsite_string(item.header.callsite_loc)); break; case RR_INTERRUPT_REQUEST: printf("\tRR_INTERRUPT_REQUEST_%d from %s\n", item.variant.interrupt_request, get_callsite_string(item.header.callsite_loc)); break; case RR_EXIT_REQUEST: printf("\tRR_EXIT_REQUEST_%d from %s\n", item.variant.exit_request, get_callsite_string(item.header.callsite_loc)); break; case RR_SKIPPED_CALL: { RR_skipped_call_args *args = &item.variant.call_args; int callbytes; switch (item.variant.call_args.kind) { case RR_CALL_CPU_MEM_RW: callbytes = sizeof(args->variant.cpu_mem_rw_args) + args->variant.cpu_mem_rw_args.len; break; case RR_CALL_MEM_REGION_CHANGE: callbytes = sizeof(args->variant.mem_region_change_args) + args->variant.mem_region_change_args.len; break; case RR_CALL_CPU_MEM_UNMAP: callbytes = sizeof(args->variant.cpu_mem_unmap) + args->variant.cpu_mem_unmap.len; break; case RR_CALL_HD_TRANSFER: callbytes = sizeof(args->variant.hd_transfer_args); printf("This is a HD transfer. Source: 0x%lx, Dest: 0x%lx, Len: %d\n", args->variant.hd_transfer_args.src_addr, args->variant.hd_transfer_args.dest_addr, args->variant.hd_transfer_args.num_bytes); break; } printf("\tRR_SKIPPED_CALL_(%s) from %s %d bytes\n", get_skipped_call_kind_string(item.variant.call_args.kind), get_callsite_string(item.header.callsite_loc), callbytes); break; } case RR_LAST: printf("\tRR_LAST\n"); break; case RR_DEBUG: printf("\tRR_DEBUG\n"); break; default: printf("\tUNKNOWN RR log kind %d\n", item.header.kind); break; } }