Multiple fixes for systemmode (#13)
* Systemmode: handle breakpoints natively * systemmode: buffer snapshot name fixes a bug where the name pointer becomes stale. * systemmode: allow synchronous snapshotting Add a flag to take snapshots synchronosly. This should be used to take or load snapshots while the emulator is not running. Co-authored-by: Alwin Berger <alwin.berger@tu-dortmund.de>
This commit is contained in:
parent
ddb71cf438
commit
668fc28b05
@ -40,9 +40,11 @@
|
|||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/main-loop.h"
|
#include "qemu/main-loop.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
void libafl_save_qemu_snapshot(char *name);
|
void libafl_save_qemu_snapshot(char *name, bool sync);
|
||||||
void libafl_load_qemu_snapshot(char *name);
|
void libafl_load_qemu_snapshot(char *name, bool sync);
|
||||||
|
|
||||||
static void save_snapshot_cb(void* opaque)
|
static void save_snapshot_cb(void* opaque)
|
||||||
{
|
{
|
||||||
@ -52,11 +54,26 @@ static void save_snapshot_cb(void* opaque)
|
|||||||
error_report_err(err);
|
error_report_err(err);
|
||||||
error_report("Could not save snapshot");
|
error_report("Could not save snapshot");
|
||||||
}
|
}
|
||||||
|
free(opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libafl_save_qemu_snapshot(char *name)
|
void libafl_save_qemu_snapshot(char *name, bool sync)
|
||||||
{
|
{
|
||||||
aio_bh_schedule_oneshot_full(qemu_get_aio_context(), save_snapshot_cb, (void*)name, "save_snapshot");
|
// use snapshots synchronously, use if main loop is not running
|
||||||
|
if (sync) {
|
||||||
|
//TODO: eliminate this code duplication
|
||||||
|
//by passing a heap-allocated buffer from rust to c,
|
||||||
|
//which c needs to free
|
||||||
|
Error *err = NULL;
|
||||||
|
if(!save_snapshot(name, true, NULL, false, NULL, &err)) {
|
||||||
|
error_report_err(err);
|
||||||
|
error_report("Could not save snapshot");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char* name_buffer = malloc(strlen(name)+1);
|
||||||
|
strcpy(name_buffer, name);
|
||||||
|
aio_bh_schedule_oneshot_full(qemu_get_aio_context(), save_snapshot_cb, (void*)name_buffer, "save_snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void load_snapshot_cb(void* opaque)
|
static void load_snapshot_cb(void* opaque)
|
||||||
@ -76,11 +93,33 @@ static void load_snapshot_cb(void* opaque)
|
|||||||
if (loaded && saved_vm_running) {
|
if (loaded && saved_vm_running) {
|
||||||
vm_start();
|
vm_start();
|
||||||
}
|
}
|
||||||
|
free(opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libafl_load_qemu_snapshot(char *name)
|
void libafl_load_qemu_snapshot(char *name, bool sync)
|
||||||
{
|
{
|
||||||
aio_bh_schedule_oneshot_full(qemu_get_aio_context(), load_snapshot_cb, (void*)name, "load_snapshot");
|
// use snapshots synchronously, use if main loop is not running
|
||||||
|
if (sync) {
|
||||||
|
//TODO: see libafl_save_qemu_snapshot
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
|
int saved_vm_running = runstate_is_running();
|
||||||
|
vm_stop(RUN_STATE_RESTORE_VM);
|
||||||
|
|
||||||
|
bool loaded = load_snapshot(name, NULL, false, NULL, &err);
|
||||||
|
|
||||||
|
if(!loaded) {
|
||||||
|
error_report_err(err);
|
||||||
|
error_report("Could not load snapshot");
|
||||||
|
}
|
||||||
|
if (loaded && saved_vm_running) {
|
||||||
|
vm_start();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char* name_buffer = malloc(strlen(name)+1);
|
||||||
|
strcpy(name_buffer, name);
|
||||||
|
aio_bh_schedule_oneshot_full(qemu_get_aio_context(), load_snapshot_cb, (void*)name_buffer, "load_snapshot");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -93,12 +132,16 @@ void libafl_qemu_trigger_breakpoint(CPUState* cpu);
|
|||||||
|
|
||||||
void libafl_qemu_trigger_breakpoint(CPUState* cpu)
|
void libafl_qemu_trigger_breakpoint(CPUState* cpu)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
qemu_system_debug_request();
|
||||||
|
#else
|
||||||
if (cpu->running) {
|
if (cpu->running) {
|
||||||
cpu->exception_index = EXCP_LIBAFL_BP;
|
cpu->exception_index = EXCP_LIBAFL_BP;
|
||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
} else {
|
} else {
|
||||||
libafl_qemu_break_asap = 1;
|
libafl_qemu_break_asap = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env)
|
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env)
|
||||||
|
@ -670,6 +670,9 @@ static bool main_loop_should_exit(int *status)
|
|||||||
|
|
||||||
if (qemu_debug_requested()) {
|
if (qemu_debug_requested()) {
|
||||||
vm_stop(RUN_STATE_DEBUG);
|
vm_stop(RUN_STATE_DEBUG);
|
||||||
|
//// --- Begin LibAFL code ---
|
||||||
|
return true; // exit back to fuzzing harness
|
||||||
|
//// --- End LibAFL code ---
|
||||||
}
|
}
|
||||||
if (qemu_suspend_requested()) {
|
if (qemu_suspend_requested()) {
|
||||||
qemu_system_suspend();
|
qemu_system_suspend();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user