From bd9237e8afc80f9b6afeeac69b1019c6d7b76103 Mon Sep 17 00:00:00 2001 From: Yannick Naumann Date: Mon, 12 Aug 2024 15:36:31 +0200 Subject: [PATCH] Add snapshots and register write for code benchmarking --- system/main.c | 163 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 128 insertions(+), 35 deletions(-) diff --git a/system/main.c b/system/main.c index 6652a645ba..7174e359f1 100644 --- a/system/main.c +++ b/system/main.c @@ -26,11 +26,32 @@ #include "qemu-main.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" +#include "migration/snapshot.h" #ifdef CONFIG_SDL #include #endif + + + +int snapshot_save(const char *name); +int snapshot_load(const char *name); + +int snapshot_save(const char *name) +{ + Error *err = NULL; + save_snapshot(name, true, NULL, false, NULL, &err); + return err == 0; +} + +int snapshot_load(const char *name) +{ + Error *err = NULL; + load_snapshot(name, NULL, false, NULL, &err); + return err == 0; +} + int qemu_default_main(void) { int status; @@ -48,55 +69,127 @@ int (*qemu_main)(void) = qemu_default_main; #include #include #include "exec/cpu-common.h" -void libafl_qemu_set_native_breakpoint( vaddr ); -void libafl_qemu_remove_native_breakpoint( vaddr ); +void libafl_qemu_set_native_breakpoint(vaddr); +void libafl_qemu_remove_native_breakpoint(vaddr); +int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val); +int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val); +CPUState* libafl_qemu_current_cpu(void); +int libafl_qemu_num_regs(CPUState* cpu); +int libafl_qemu_num_cpus(void); +CPUState* libafl_qemu_get_cpu(int cpu_index); int64_t icount_get_raw(void); //========= Instrumentation end int main(int argc, char **argv) { -//========= Instrumentation start + + int input_size; + printf("argc: %d\n", argc); + //========= Instrumentation start // read addr and input to load - if (argc < 3) { + if (argc < 3) + { fprintf(stderr, "Need address and input file argument\n"); exit(1); } - hwaddr start = (hwaddr) strtoll(argv[1], NULL, 16); - hwaddr end = (hwaddr) strtoll(argv[2], NULL, 16); + hwaddr prep = (hwaddr)strtoll(argv[1], NULL, 16); + hwaddr start = (hwaddr)strtoll(argv[2], NULL, 16); + hwaddr end = (hwaddr)strtoll(argv[3], NULL, 16); + input_size = atoi(argv[4]); + char* output_path = argv[5]; // hwaddr target_addr = (hwaddr) strtoll(argv[1], NULL, 16); // vm_start(); - // char buffer[4097]; - // FILE* inputfile = fopen(argv[2], "rb"); - // if (!inputfile) { - // perror("fopen"); - // exit(1); - // } - // size_t read_len = fread(buffer, sizeof(char), 4096, inputfile); - // buffer[read_len]=0; - // if (!read_len) { - // fprintf(stderr, "No input in file\n"); - // exit(1); - // } - // printf("Load at %lx: %s\n", target_addr, buffer); // fix arguments for qemu - argv[2]=argv[0]; - argv=&argv[2]; - argc-=2; -//========= Instrumentation end + argv[5]=argv[0]; + argv=&argv[5]; + + argc -= 5; + + + unsigned long deltas[input_size]; + u_int32_t inputs[input_size]; + //========= Instrumentation end qemu_init(argc, argv); -//========= Instrumentation start + //========= Instrumentation start + + libafl_qemu_set_native_breakpoint(prep); + //set int in in the vm to i + vm_start(); + qemu_main_loop(); + + //Now execution is halted at the start of the task we want to measure in order to write the input to a register + libafl_qemu_remove_native_breakpoint(prep); + + snapshot_save("base"); + + uint8_t register_in_32b[4]; + uint8_t reg_tmp_val[4]; // load input - // cpu_physical_memory_rw(target_addr, buffer, read_len, true); - libafl_qemu_set_native_breakpoint(start); - vm_start(); - qemu_main_loop(); - libafl_qemu_remove_native_breakpoint(start); - libafl_qemu_set_native_breakpoint(end); - printf("Start: %lu\n", icount_get_raw()); - vm_start(); - qemu_main_loop(); - printf("End: %lu\n", icount_get_raw()); + //cpu_physical_memory_rw(target_addr, buffer, read_len, true); + + for (u_int32_t i = 0; i < input_size; i++) + { + //load the system in the halted state at the beginning of the task; Write input to register + snapshot_load("base"); + CPUState *cpu = libafl_qemu_get_cpu(0); + if (cpu == NULL) { + printf("Error: CPU is NULL.\n"); + } + //printf("reg count: %d\n", libafl_qemu_num_regs(cpu)); + + //Write i to register format + register_in_32b[0] = i & 0xFF; // Least significant byte + register_in_32b[1] = (i >> 8) & 0xFF; + register_in_32b[2] = (i >> 16) & 0xFF; + register_in_32b[3] = (i >> 24) & 0xFF; // Most significant byte + + + int length = libafl_qemu_read_reg(cpu, 12, reg_tmp_val); + if(length != 4) { + printf("Error: Could not read register\n"); + } + libafl_qemu_write_reg(cpu, 12, register_in_32b); + + //Read Result to unint32_t (for debugging) + //uint32_t res_val = (uint32_t)res_ptr[0] | ((uint32_t)res_ptr[1] << 8) | ((uint32_t)res_ptr[2] << 16) | ((uint32_t)res_ptr[3] << 24); + + libafl_qemu_set_native_breakpoint(start); + + vm_start(); + qemu_main_loop(); + + // Now execution is halted at the beginning of the snipped we want to measure. The written input value has been read from the register + libafl_qemu_remove_native_breakpoint(start); + libafl_qemu_set_native_breakpoint(end); + + //Write back the original value to the register + libafl_qemu_write_reg(cpu, 12, reg_tmp_val); + + unsigned long start_count = icount_get_raw(); + printf("Start: %lu\n", start_count); + vm_start(); + qemu_main_loop(); + libafl_qemu_remove_native_breakpoint(end); + unsigned long end_count = icount_get_raw(); + printf("End: %lu\n", end_count); + inputs[i] = i; + deltas[i] = end_count - start_count; + + printf("Delta: %lu\n", deltas[i]); + } + + // // Write to serial port + // qemu_chr_fe_write(serial_chr, data, length); + FILE *fptr = fopen(output_path, "w"); + + for (int i = 0; i < input_size; i++) { + fprintf(fptr, "%d,%lu\n", inputs[i], deltas[i]); + } + + fclose(fptr); + // // Write some text to the file + // fprintf(fptr, "%lu",delta); return 0; -//========= Instrumentation end + //========= Instrumentation end return qemu_main(); } #endif