FRET-qemu/libafl/qemu_snapshot.c
2025-04-30 13:47:55 +02:00

91 lines
2.5 KiB
C

#include "qemu/osdep.h"
#include "qapi/error.h"
#include <stdlib.h>
#include <string.h>
#include "migration/snapshot.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "hw/core/cpu.h"
#include "system/runstate.h"
#include "libafl/qemu_snapshot.h"
static void save_snapshot_cb(void* opaque)
{
char* name = (char*)opaque;
Error* err = NULL;
if (!save_snapshot(name, true, NULL, false, NULL, &err)) {
error_report_err(err);
error_report("Could not save snapshot");
}
free(opaque);
}
static void load_snapshot_cb(void* opaque)
{
char* name = (char*)opaque;
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();
}
free(opaque);
}
void libafl_save_qemu_snapshot(char* name, bool sync)
{
// 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");
}
void libafl_load_qemu_snapshot(char* name, bool sync)
{
// 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");
}