Second round of cleanups (#83)
* get rid of as many extern / function definition in QEMU codebase. * mostly moved cpu / gdb related code. * move qemu snapshot code in dedicated files.
This commit is contained in:
parent
86d38fbfa7
commit
7f468ebba6
@ -39,99 +39,6 @@
|
|||||||
|
|
||||||
#include "libafl/exit.h"
|
#include "libafl/exit.h"
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
|
|
||||||
#include "sysemu/runstate.h"
|
|
||||||
#include "migration/snapshot.h"
|
|
||||||
#include "qapi/error.h"
|
|
||||||
#include "qemu/error-report.h"
|
|
||||||
#include "qemu/main-loop.h"
|
|
||||||
#include "hw/core/cpu.h"
|
|
||||||
#include "sysemu/hw_accel.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void libafl_save_qemu_snapshot(char *name, bool sync);
|
|
||||||
void libafl_load_qemu_snapshot(char *name, bool sync);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env, uint64_t pc)
|
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env, uint64_t pc)
|
||||||
{
|
{
|
||||||
CPUState* cpu = env_cpu(env);
|
CPUState* cpu = env_cpu(env);
|
||||||
|
152
cpu-target.c
152
cpu-target.c
@ -47,139 +47,10 @@
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
#include "exec/gdbstub.h"
|
|
||||||
|
|
||||||
#include "libafl/exit.h"
|
|
||||||
#include "libafl/hook.h"
|
|
||||||
|
|
||||||
int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg);
|
|
||||||
|
|
||||||
static __thread GByteArray *libafl_qemu_mem_buf = NULL;
|
|
||||||
|
|
||||||
target_ulong libafl_page_from_addr(target_ulong addr);
|
|
||||||
|
|
||||||
CPUState* libafl_qemu_get_cpu(int cpu_index);
|
|
||||||
int libafl_qemu_num_cpus(void);
|
|
||||||
CPUState* libafl_qemu_current_cpu(void);
|
|
||||||
int libafl_qemu_cpu_index(CPUState*);
|
|
||||||
|
|
||||||
int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val);
|
|
||||||
int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val);
|
|
||||||
int libafl_qemu_num_regs(CPUState* cpu);
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
hwaddr libafl_qemu_current_paging_id(CPUState* cpu);
|
#include "libafl/syx-snapshot/device-save.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void libafl_flush_jit(void);
|
|
||||||
|
|
||||||
extern int libafl_restoring_devices;
|
|
||||||
|
|
||||||
/*
|
|
||||||
void* libafl_qemu_g2h(CPUState *cpu, target_ulong x);
|
|
||||||
target_ulong libafl_qemu_h2g(CPUState *cpu, void* x);
|
|
||||||
|
|
||||||
void* libafl_qemu_g2h(CPUState *cpu, target_ulong x)
|
|
||||||
{
|
|
||||||
return g2h(cpu, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_ulong libafl_qemu_h2g(CPUState *cpu, void* x)
|
|
||||||
{
|
|
||||||
return h2g(cpu, x);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
target_ulong libafl_page_from_addr(target_ulong addr) {
|
|
||||||
return addr & TARGET_PAGE_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPUState* libafl_qemu_get_cpu(int cpu_index)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
if (cpu->cpu_index == cpu_index)
|
|
||||||
return cpu;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_num_cpus(void)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
int num = 0;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
num++;
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPUState* libafl_qemu_current_cpu(void)
|
|
||||||
{
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
if (current_cpu == NULL) {
|
|
||||||
return libafl_last_exit_cpu();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return current_cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_cpu_index(CPUState* cpu)
|
|
||||||
{
|
|
||||||
if (cpu) return cpu->cpu_index;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val)
|
|
||||||
{
|
|
||||||
return gdb_write_register(cpu, val, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
|
|
||||||
if (libafl_qemu_mem_buf == NULL) {
|
|
||||||
libafl_qemu_mem_buf = g_byte_array_sized_new(64);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_byte_array_set_size(libafl_qemu_mem_buf, 0);
|
|
||||||
|
|
||||||
len = gdb_read_register(cpu, libafl_qemu_mem_buf, reg);
|
|
||||||
|
|
||||||
if (len > 0) {
|
|
||||||
memcpy(val, libafl_qemu_mem_buf->data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_num_regs(CPUState* cpu)
|
|
||||||
{
|
|
||||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
|
||||||
return cc->gdb_num_core_regs;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
hwaddr libafl_qemu_current_paging_id(CPUState* cpu)
|
|
||||||
{
|
|
||||||
CPUClass* cc = CPU_GET_CLASS(cpu);
|
|
||||||
if (cc->sysemu_ops && cc->sysemu_ops->get_paging_id) {
|
|
||||||
return cc->sysemu_ops->get_paging_id(cpu);
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void libafl_flush_jit(void)
|
|
||||||
{
|
|
||||||
CPUState *cpu;
|
|
||||||
CPU_FOREACH(cpu) {
|
|
||||||
tb_flush(cpu);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
@ -203,7 +74,9 @@ static int cpu_common_post_load(void *opaque, int version_id)
|
|||||||
|
|
||||||
// flushing the TBs every restore makes it really slow
|
// flushing the TBs every restore makes it really slow
|
||||||
// TODO handle writes to X code with specific calls to tb_invalidate_phys_addr
|
// TODO handle writes to X code with specific calls to tb_invalidate_phys_addr
|
||||||
if (!libafl_restoring_devices) tb_flush(cpu);
|
if (!libafl_devices_is_restoring()) {
|
||||||
|
tb_flush(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
@ -462,23 +335,6 @@ void list_cpus(void)
|
|||||||
cpu_list();
|
cpu_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
|
||||||
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
|
||||||
{
|
|
||||||
mmap_lock();
|
|
||||||
tb_invalidate_phys_range(pc, pc + 1);
|
|
||||||
mmap_unlock();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc)
|
|
||||||
{
|
|
||||||
// TODO invalidate only the virtual pages related to the TB
|
|
||||||
tb_flush(cpu);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
//// --- End LibAFL code ---
|
|
||||||
|
|
||||||
/* enable or disable single step mode. EXCP_DEBUG is returned by the
|
/* enable or disable single step mode. EXCP_DEBUG is returned by the
|
||||||
CPU loop after each instruction */
|
CPU loop after each instruction */
|
||||||
void cpu_single_step(CPUState *cpu, int enabled)
|
void cpu_single_step(CPUState *cpu, int enabled)
|
||||||
|
@ -1648,30 +1648,6 @@ static void handle_query_thread_extra(GArray *params, void *user_ctx)
|
|||||||
gdb_put_strbuf();
|
gdb_put_strbuf();
|
||||||
}
|
}
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
|
||||||
|
|
||||||
struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds;
|
|
||||||
|
|
||||||
void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data);
|
|
||||||
void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data)
|
|
||||||
{
|
|
||||||
struct libafl_custom_gdb_cmd* c = malloc(sizeof(struct libafl_custom_gdb_cmd));
|
|
||||||
c->callback = callback;
|
|
||||||
c->data = data;
|
|
||||||
c->next = libafl_qemu_gdb_cmds;
|
|
||||||
libafl_qemu_gdb_cmds = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void libafl_qemu_gdb_reply(const char* buf, size_t len);
|
|
||||||
void libafl_qemu_gdb_reply(const char* buf, size_t len)
|
|
||||||
{
|
|
||||||
g_autoptr(GString) hex_buf = g_string_new("O");
|
|
||||||
gdb_memtohex(hex_buf, (const uint8_t *) buf, len);
|
|
||||||
gdb_put_packet(hex_buf->str);
|
|
||||||
}
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
|
||||||
|
|
||||||
static void handle_query_supported(GArray *params, void *user_ctx)
|
static void handle_query_supported(GArray *params, void *user_ctx)
|
||||||
{
|
{
|
||||||
CPUClass *cc;
|
CPUClass *cc;
|
||||||
|
@ -240,16 +240,4 @@ void gdb_breakpoint_remove_all(CPUState *cs);
|
|||||||
int gdb_target_memory_rw_debug(CPUState *cs, hwaddr addr,
|
int gdb_target_memory_rw_debug(CPUState *cs, hwaddr addr,
|
||||||
uint8_t *buf, int len, bool is_write);
|
uint8_t *buf, int len, bool is_write);
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
|
||||||
|
|
||||||
struct libafl_custom_gdb_cmd {
|
|
||||||
int (*callback)(void*, uint8_t*, size_t);
|
|
||||||
void* data;
|
|
||||||
struct libafl_custom_gdb_cmd* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds;
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
|
||||||
|
|
||||||
#endif /* GDBSTUB_INTERNALS_H */
|
#endif /* GDBSTUB_INTERNALS_H */
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
|
|
||||||
|
//// --- Begin LibAFL code ---
|
||||||
|
#include "libafl/gdb.h"
|
||||||
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
/* System emulation specific state */
|
/* System emulation specific state */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
CharBackend chr;
|
CharBackend chr;
|
||||||
@ -531,14 +535,7 @@ void gdb_handle_query_rcmd(GArray *params, void *ctx)
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
|
if (libafl_qemu_gdb_exec()) {
|
||||||
int recognized = 0;
|
|
||||||
while (*c) {
|
|
||||||
recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len);
|
|
||||||
c = &(*c)->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recognized) {
|
|
||||||
gdb_put_packet("OK");
|
gdb_put_packet("OK");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,11 @@
|
|||||||
#ifdef CONFIG_LINUX
|
#ifdef CONFIG_LINUX
|
||||||
#include "linux-user/loader.h"
|
#include "linux-user/loader.h"
|
||||||
#include "linux-user/qemu.h"
|
#include "linux-user/qemu.h"
|
||||||
|
|
||||||
|
//// --- Begin LibAFL code ---
|
||||||
|
#include "libafl/gdb.h"
|
||||||
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -305,27 +310,17 @@ void gdb_handle_query_rcmd(GArray *params, void *user_ctx)
|
|||||||
g_assert(gdbserver_state.mem_buf->len == 0);
|
g_assert(gdbserver_state.mem_buf->len == 0);
|
||||||
len = len / 2;
|
len = len / 2;
|
||||||
gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
|
gdb_hextomem(gdbserver_state.mem_buf, get_param(params, 0)->data, len);
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
|
||||||
|
|
||||||
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
|
if (libafl_qemu_gdb_exec()) {
|
||||||
int recognized = 0;
|
|
||||||
while (*c) {
|
|
||||||
recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len);
|
|
||||||
c = &(*c)->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (recognized) {
|
|
||||||
gdb_put_packet("OK");
|
gdb_put_packet("OK");
|
||||||
} else {
|
} else {
|
||||||
gdb_put_packet("");
|
gdb_put_packet("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char *get_filename_param(GArray *params, int i)
|
static const char *get_filename_param(GArray *params, int i)
|
||||||
{
|
{
|
||||||
const char *hex_filename = get_param(params, i)->data;
|
const char *hex_filename = get_param(params, i)->data;
|
||||||
|
31
include/libafl/cpu.h
Normal file
31
include/libafl/cpu.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
#include "exec/memory.h"
|
||||||
|
#include "qemu/rcu.h"
|
||||||
|
#include "cpu.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
uint8_t* libafl_paddr2host(CPUState* cpu, hwaddr addr, bool is_write);
|
||||||
|
hwaddr libafl_qemu_current_paging_id(CPUState* cpu);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
target_ulong libafl_page_from_addr(target_ulong addr);
|
||||||
|
CPUState* libafl_qemu_get_cpu(int cpu_index);
|
||||||
|
int libafl_qemu_num_cpus(void);
|
||||||
|
CPUState* libafl_qemu_current_cpu(void);
|
||||||
|
int libafl_qemu_cpu_index(CPUState*);
|
||||||
|
int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val);
|
||||||
|
int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val);
|
||||||
|
int libafl_qemu_num_regs(CPUState* cpu);
|
||||||
|
void libafl_flush_jit(void);
|
||||||
|
void libafl_breakpoint_invalidate(CPUState* cpu, target_ulong pc);
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
int libafl_qemu_main(void);
|
||||||
|
int libafl_qemu_run(void);
|
||||||
|
void libafl_set_qemu_env(CPUArchState* env);
|
||||||
|
#endif
|
@ -12,9 +12,6 @@ struct libafl_breakpoint {
|
|||||||
struct libafl_breakpoint* next;
|
struct libafl_breakpoint* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
// in cpu-target.c
|
|
||||||
void libafl_breakpoint_invalidate(CPUState* cpu, target_ulong pc);
|
|
||||||
|
|
||||||
int libafl_qemu_set_breakpoint(target_ulong pc);
|
int libafl_qemu_set_breakpoint(target_ulong pc);
|
||||||
int libafl_qemu_remove_breakpoint(target_ulong pc);
|
int libafl_qemu_remove_breakpoint(target_ulong pc);
|
||||||
void libafl_qemu_trigger_breakpoint(CPUState* cpu);
|
void libafl_qemu_trigger_breakpoint(CPUState* cpu);
|
||||||
|
14
include/libafl/gdb.h
Normal file
14
include/libafl/gdb.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
struct libafl_custom_gdb_cmd {
|
||||||
|
bool (*callback)(void*, uint8_t*, size_t);
|
||||||
|
void* data;
|
||||||
|
struct libafl_custom_gdb_cmd* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
void libafl_qemu_add_gdb_cmd(bool (*callback)(void*, uint8_t*, size_t),
|
||||||
|
void* data);
|
||||||
|
void libafl_qemu_gdb_reply(const uint8_t* buf, size_t len);
|
||||||
|
bool libafl_qemu_gdb_exec(void);
|
6
include/libafl/qemu_snapshot.h
Normal file
6
include/libafl/qemu_snapshot.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
void libafl_save_qemu_snapshot(char* name, bool sync);
|
||||||
|
void libafl_load_qemu_snapshot(char* name, bool sync);
|
@ -24,3 +24,5 @@ void device_restore_all(DeviceSaveState* device_save_state);
|
|||||||
void device_free_all(DeviceSaveState* dss);
|
void device_free_all(DeviceSaveState* dss);
|
||||||
|
|
||||||
char** device_list_all(void);
|
char** device_list_all(void);
|
||||||
|
|
||||||
|
bool libafl_devices_is_restoring(void);
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/interval-tree.h"
|
||||||
|
|
||||||
|
#include "exec/cpu-defs.h"
|
||||||
|
|
||||||
struct libafl_mapinfo {
|
struct libafl_mapinfo {
|
||||||
target_ulong start;
|
target_ulong start;
|
||||||
@ -13,9 +16,17 @@ struct libafl_mapinfo {
|
|||||||
bool is_valid;
|
bool is_valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void libafl_dump_core_exec(int signal);
|
||||||
|
|
||||||
void libafl_qemu_handle_crash(int host_sig, siginfo_t* info, void* puc);
|
void libafl_qemu_handle_crash(int host_sig, siginfo_t* info, void* puc);
|
||||||
|
|
||||||
IntervalTreeNode* libafl_maps_first(IntervalTreeRoot* map_info);
|
IntervalTreeNode* libafl_maps_first(IntervalTreeRoot* map_info);
|
||||||
IntervalTreeNode* libafl_maps_next(IntervalTreeNode* pageflags_maps_node,
|
IntervalTreeNode* libafl_maps_next(IntervalTreeNode* pageflags_maps_node,
|
||||||
IntervalTreeRoot* proc_maps_node,
|
IntervalTreeRoot* proc_maps_node,
|
||||||
struct libafl_mapinfo* ret);
|
struct libafl_mapinfo* ret);
|
||||||
|
|
||||||
|
uint64_t libafl_load_addr(void);
|
||||||
|
struct image_info* libafl_get_image_info(void);
|
||||||
|
|
||||||
|
uint64_t libafl_get_brk(void);
|
||||||
|
uint64_t libafl_set_brk(uint64_t new_brk);
|
||||||
|
@ -1,15 +1,3 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
#include "exec/memory.h"
|
|
||||||
#include "qemu/rcu.h"
|
|
||||||
#include "cpu.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uintptr_t libafl_qemu_host_page_size(void);
|
uintptr_t libafl_qemu_host_page_size(void);
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
uint8_t* libafl_paddr2host(CPUState* cpu, hwaddr addr, bool is_write);
|
|
||||||
#endif
|
|
||||||
|
160
libafl/cpu.c
Normal file
160
libafl/cpu.c
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#include "qemu/osdep.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
#include "qemu.h"
|
||||||
|
#include "user-internals.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "exec/gdbstub.h"
|
||||||
|
#include "exec/cpu-defs.h"
|
||||||
|
#include "exec/tb-flush.h"
|
||||||
|
#include "exec/exec-all.h"
|
||||||
|
#include "hw/core/sysemu-cpu-ops.h"
|
||||||
|
|
||||||
|
#include "libafl/cpu.h"
|
||||||
|
|
||||||
|
#include "libafl/exit.h"
|
||||||
|
#include "libafl/hook.h"
|
||||||
|
|
||||||
|
int gdb_write_register(CPUState* cpu, uint8_t* mem_buf, int reg);
|
||||||
|
|
||||||
|
static __thread GByteArray* libafl_qemu_mem_buf = NULL;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
static __thread CPUArchState* libafl_qemu_env;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
uint8_t* libafl_paddr2host(CPUState* cpu, hwaddr addr, bool is_write)
|
||||||
|
{
|
||||||
|
if (addr == -1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hwaddr xlat;
|
||||||
|
MemoryRegion* mr;
|
||||||
|
WITH_RCU_READ_LOCK_GUARD()
|
||||||
|
{
|
||||||
|
mr = address_space_translate(cpu->as, addr, &xlat, NULL, is_write,
|
||||||
|
MEMTXATTRS_UNSPECIFIED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return qemu_map_ram_ptr(mr->ram_block, xlat);
|
||||||
|
}
|
||||||
|
|
||||||
|
hwaddr libafl_qemu_current_paging_id(CPUState* cpu)
|
||||||
|
{
|
||||||
|
CPUClass* cc = CPU_GET_CLASS(cpu);
|
||||||
|
if (cc->sysemu_ops && cc->sysemu_ops->get_paging_id) {
|
||||||
|
return cc->sysemu_ops->get_paging_id(cpu);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void libafl_breakpoint_invalidate(CPUState* cpu, target_ulong pc)
|
||||||
|
{
|
||||||
|
// TODO invalidate only the virtual pages related to the TB
|
||||||
|
tb_flush(cpu);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void libafl_breakpoint_invalidate(CPUState* cpu, target_ulong pc)
|
||||||
|
{
|
||||||
|
mmap_lock();
|
||||||
|
tb_invalidate_phys_range(pc, pc + 1);
|
||||||
|
mmap_unlock();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
target_ulong libafl_page_from_addr(target_ulong addr)
|
||||||
|
{
|
||||||
|
return addr & TARGET_PAGE_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUState* libafl_qemu_get_cpu(int cpu_index)
|
||||||
|
{
|
||||||
|
CPUState* cpu;
|
||||||
|
CPU_FOREACH(cpu)
|
||||||
|
{
|
||||||
|
if (cpu->cpu_index == cpu_index)
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_num_cpus(void)
|
||||||
|
{
|
||||||
|
CPUState* cpu;
|
||||||
|
int num = 0;
|
||||||
|
CPU_FOREACH(cpu) { num++; }
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUState* libafl_qemu_current_cpu(void)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
if (current_cpu == NULL) {
|
||||||
|
return libafl_last_exit_cpu();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return current_cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_cpu_index(CPUState* cpu)
|
||||||
|
{
|
||||||
|
if (cpu)
|
||||||
|
return cpu->cpu_index;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val)
|
||||||
|
{
|
||||||
|
return gdb_write_register(cpu, val, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (libafl_qemu_mem_buf == NULL) {
|
||||||
|
libafl_qemu_mem_buf = g_byte_array_sized_new(64);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_byte_array_set_size(libafl_qemu_mem_buf, 0);
|
||||||
|
|
||||||
|
len = gdb_read_register(cpu, libafl_qemu_mem_buf, reg);
|
||||||
|
|
||||||
|
if (len > 0) {
|
||||||
|
memcpy(val, libafl_qemu_mem_buf->data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_num_regs(CPUState* cpu)
|
||||||
|
{
|
||||||
|
CPUClass* cc = CPU_GET_CLASS(cpu);
|
||||||
|
return cc->gdb_num_core_regs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libafl_flush_jit(void)
|
||||||
|
{
|
||||||
|
CPUState* cpu;
|
||||||
|
CPU_FOREACH(cpu) { tb_flush(cpu); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
__attribute__((weak)) int libafl_qemu_main(void)
|
||||||
|
{
|
||||||
|
libafl_qemu_run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libafl_qemu_run(void)
|
||||||
|
{
|
||||||
|
cpu_loop(libafl_qemu_env);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libafl_set_qemu_env(CPUArchState* env) { libafl_qemu_env = env; }
|
||||||
|
#endif
|
@ -7,6 +7,7 @@
|
|||||||
#include "exec/translator.h"
|
#include "exec/translator.h"
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
#include "libafl/cpu.h"
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
#define THREAD_MODIFIER __thread
|
#define THREAD_MODIFIER __thread
|
||||||
|
35
libafl/gdb.c
Normal file
35
libafl/gdb.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "libafl/gdb.h"
|
||||||
|
#include "gdbstub/internals.h"
|
||||||
|
|
||||||
|
static struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds;
|
||||||
|
|
||||||
|
void libafl_qemu_add_gdb_cmd(bool (*callback)(void*, uint8_t*, size_t),
|
||||||
|
void* data)
|
||||||
|
{
|
||||||
|
struct libafl_custom_gdb_cmd* c =
|
||||||
|
malloc(sizeof(struct libafl_custom_gdb_cmd));
|
||||||
|
c->callback = callback;
|
||||||
|
c->data = data;
|
||||||
|
c->next = libafl_qemu_gdb_cmds;
|
||||||
|
libafl_qemu_gdb_cmds = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libafl_qemu_gdb_reply(const uint8_t* buf, size_t len)
|
||||||
|
{
|
||||||
|
g_autoptr(GString) hex_buf = g_string_new("O");
|
||||||
|
gdb_memtohex(hex_buf, buf, len);
|
||||||
|
gdb_put_packet(hex_buf->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool libafl_qemu_gdb_exec(void)
|
||||||
|
{
|
||||||
|
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
|
||||||
|
bool recognized = false;
|
||||||
|
while (*c) {
|
||||||
|
recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data,
|
||||||
|
gdbserver_state.mem_buf->len);
|
||||||
|
c = &(*c)->next;
|
||||||
|
}
|
||||||
|
return recognized;
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
#include "libafl/hooks/tcg/instruction.h"
|
#include "libafl/hooks/tcg/instruction.h"
|
||||||
|
|
||||||
|
#include "libafl/cpu.h"
|
||||||
|
|
||||||
target_ulong libafl_gen_cur_pc;
|
target_ulong libafl_gen_cur_pc;
|
||||||
struct libafl_instruction_hook*
|
struct libafl_instruction_hook*
|
||||||
libafl_qemu_instruction_hooks[LIBAFL_TABLES_SIZE];
|
libafl_qemu_instruction_hooks[LIBAFL_TABLES_SIZE];
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
#include "libafl/hooks/thread.h"
|
#include "libafl/hooks/thread.h"
|
||||||
|
#include "libafl/cpu.h"
|
||||||
|
|
||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
|
|
||||||
extern __thread CPUArchState* libafl_qemu_env;
|
|
||||||
|
|
||||||
struct libafl_new_thread_hook* libafl_new_thread_hooks;
|
struct libafl_new_thread_hook* libafl_new_thread_hooks;
|
||||||
size_t libafl_new_thread_hooks_num = 0;
|
size_t libafl_new_thread_hooks_num = 0;
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ size_t libafl_add_new_thread_hook(bool (*callback)(uint64_t data,
|
|||||||
|
|
||||||
bool libafl_hook_new_thread_run(CPUArchState* env)
|
bool libafl_hook_new_thread_run(CPUArchState* env)
|
||||||
{
|
{
|
||||||
libafl_qemu_env = env;
|
libafl_set_qemu_env(env);
|
||||||
|
|
||||||
if (libafl_new_thread_hooks) {
|
if (libafl_new_thread_hooks) {
|
||||||
bool continue_execution = true;
|
bool continue_execution = true;
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
specific_ss.add(files(
|
specific_ss.add(files(
|
||||||
|
'cpu.c',
|
||||||
'exit.c',
|
'exit.c',
|
||||||
'hook.c',
|
'hook.c',
|
||||||
'jit.c',
|
'jit.c',
|
||||||
'utils.c',
|
'utils.c',
|
||||||
|
'gdb.c',
|
||||||
|
|
||||||
# TCG-related hooks
|
# TCG-related hooks
|
||||||
'hooks/tcg/backdoor.c',
|
'hooks/tcg/backdoor.c',
|
||||||
@ -17,6 +19,7 @@ specific_ss.add(files(
|
|||||||
))
|
))
|
||||||
|
|
||||||
specific_ss.add(when : 'CONFIG_SOFTMMU', if_true : [files(
|
specific_ss.add(when : 'CONFIG_SOFTMMU', if_true : [files(
|
||||||
|
'qemu_snapshot.c',
|
||||||
'syx-snapshot/device-save.c',
|
'syx-snapshot/device-save.c',
|
||||||
'syx-snapshot/syx-snapshot.c',
|
'syx-snapshot/syx-snapshot.c',
|
||||||
'syx-snapshot/syx-cow-cache.c',
|
'syx-snapshot/syx-cow-cache.c',
|
||||||
@ -24,6 +27,7 @@ specific_ss.add(when : 'CONFIG_SOFTMMU', if_true : [files(
|
|||||||
)])
|
)])
|
||||||
|
|
||||||
specific_ss.add(when : 'CONFIG_USER_ONLY', if_true : [files(
|
specific_ss.add(when : 'CONFIG_USER_ONLY', if_true : [files(
|
||||||
|
'user.c',
|
||||||
'hooks/syscall.c',
|
'hooks/syscall.c',
|
||||||
'hooks/thread.c',
|
'hooks/thread.c',
|
||||||
)])
|
)])
|
||||||
|
89
libafl/qemu_snapshot.c
Normal file
89
libafl/qemu_snapshot.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include "libafl/qemu_snapshot.h"
|
||||||
|
|
||||||
|
#include "sysemu/runstate.h"
|
||||||
|
#include "migration/snapshot.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
|
#include "qemu/main-loop.h"
|
||||||
|
#include "hw/core/cpu.h"
|
||||||
|
#include "sysemu/hw_accel.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.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");
|
||||||
|
}
|
@ -11,12 +11,13 @@
|
|||||||
|
|
||||||
#include "migration/savevm.h"
|
#include "migration/savevm.h"
|
||||||
|
|
||||||
int libafl_restoring_devices;
|
|
||||||
|
|
||||||
extern SaveState savevm_state;
|
extern SaveState savevm_state;
|
||||||
|
|
||||||
extern int vmstate_save(QEMUFile* f, SaveStateEntry* se, JSONWriter* vmdesc);
|
extern int vmstate_save(QEMUFile* f, SaveStateEntry* se, JSONWriter* vmdesc);
|
||||||
|
|
||||||
|
static bool libafl_restoring_devices = false;
|
||||||
|
|
||||||
|
bool libafl_devices_is_restoring(void) { return libafl_restoring_devices; }
|
||||||
|
|
||||||
// iothread must be locked
|
// iothread must be locked
|
||||||
DeviceSaveState* device_save_all(void)
|
DeviceSaveState* device_save_all(void)
|
||||||
{
|
{
|
||||||
@ -101,8 +102,8 @@ void device_restore_all(DeviceSaveState* dss)
|
|||||||
|
|
||||||
QEMUFile* f = qemu_file_new_input(ioc);
|
QEMUFile* f = qemu_file_new_input(ioc);
|
||||||
|
|
||||||
int save_libafl_restoring_devices = libafl_restoring_devices;
|
bool save_libafl_restoring_devices = libafl_restoring_devices;
|
||||||
libafl_restoring_devices = 1;
|
libafl_restoring_devices = true;
|
||||||
|
|
||||||
qemu_load_device_state(f);
|
qemu_load_device_state(f);
|
||||||
|
|
||||||
|
37
libafl/user.c
Normal file
37
libafl/user.c
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu.h"
|
||||||
|
#include "loader.h"
|
||||||
|
|
||||||
|
#include "libafl/user.h"
|
||||||
|
|
||||||
|
void (*libafl_dump_core_hook)(int host_sig) = NULL;
|
||||||
|
static struct image_info libafl_image_info;
|
||||||
|
|
||||||
|
extern abi_ulong target_brk, initial_target_brk;
|
||||||
|
|
||||||
|
void host_signal_handler(int host_sig, siginfo_t* info, void* puc);
|
||||||
|
|
||||||
|
void libafl_qemu_handle_crash(int host_sig, siginfo_t* info, void* puc)
|
||||||
|
{
|
||||||
|
host_signal_handler(host_sig, info, puc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libafl_dump_core_exec(int signal)
|
||||||
|
{
|
||||||
|
if (libafl_dump_core_hook) {
|
||||||
|
libafl_dump_core_hook(signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t libafl_load_addr(void) { return libafl_image_info.load_addr; }
|
||||||
|
|
||||||
|
struct image_info* libafl_get_image_info(void) { return &libafl_image_info; }
|
||||||
|
|
||||||
|
uint64_t libafl_get_brk(void) { return (uint64_t)target_brk; }
|
||||||
|
|
||||||
|
uint64_t libafl_set_brk(uint64_t new_brk)
|
||||||
|
{
|
||||||
|
uint64_t old_brk = (uint64_t)target_brk;
|
||||||
|
target_brk = (abi_ulong)new_brk;
|
||||||
|
return old_brk;
|
||||||
|
}
|
@ -5,24 +5,3 @@ uintptr_t libafl_qemu_host_page_size(void)
|
|||||||
{
|
{
|
||||||
return qemu_real_host_page_size();
|
return qemu_real_host_page_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
|
||||||
|
|
||||||
uint8_t* libafl_paddr2host(CPUState* cpu, hwaddr addr, bool is_write)
|
|
||||||
{
|
|
||||||
if (addr == -1) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hwaddr xlat;
|
|
||||||
MemoryRegion* mr;
|
|
||||||
WITH_RCU_READ_LOCK_GUARD()
|
|
||||||
{
|
|
||||||
mr = address_space_translate(cpu->as, addr, &xlat, NULL, is_write,
|
|
||||||
MEMTXATTRS_UNSPECIFIED);
|
|
||||||
}
|
|
||||||
|
|
||||||
return qemu_map_ram_ptr(mr->ram_block, xlat);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -57,6 +57,11 @@
|
|||||||
#include "tcg/perf.h"
|
#include "tcg/perf.h"
|
||||||
#include "exec/page-vary.h"
|
#include "exec/page-vary.h"
|
||||||
|
|
||||||
|
//// --- End LibAFL code ---
|
||||||
|
#include "libafl/cpu.h"
|
||||||
|
#include "libafl/user.h"
|
||||||
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
#ifdef CONFIG_SEMIHOSTING
|
#ifdef CONFIG_SEMIHOSTING
|
||||||
#include "semihosting/semihost.h"
|
#include "semihosting/semihost.h"
|
||||||
#endif
|
#endif
|
||||||
@ -685,45 +690,22 @@ static int parse_args(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
uint64_t libafl_load_addr(void);
|
|
||||||
int libafl_qemu_main(void);
|
|
||||||
int libafl_qemu_run(void);
|
|
||||||
|
|
||||||
__thread CPUArchState *libafl_qemu_env;
|
|
||||||
|
|
||||||
struct image_info libafl_image_info;
|
|
||||||
struct linux_binprm bprm;
|
struct linux_binprm bprm;
|
||||||
|
|
||||||
uint64_t libafl_load_addr(void) {
|
|
||||||
return libafl_image_info.load_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__((weak)) int libafl_qemu_main(void)
|
|
||||||
{
|
|
||||||
libafl_qemu_run();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int libafl_qemu_run(void)
|
|
||||||
{
|
|
||||||
cpu_loop(libafl_qemu_env);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
|
||||||
|
|
||||||
#ifdef AS_LIB
|
#ifdef AS_LIB
|
||||||
int qemu_user_init(int argc, char **argv, char **envp);
|
int qemu_user_init(int argc, char **argv, char **envp);
|
||||||
int qemu_user_init(int argc, char **argv, char **envp)
|
int qemu_user_init(int argc, char **argv, char **envp)
|
||||||
#else
|
#else
|
||||||
|
//// --- End LibAFL code ---
|
||||||
int main(int argc, char **argv, char **envp)
|
int main(int argc, char **argv, char **envp)
|
||||||
|
//// --- Begin LibAFL code ---
|
||||||
#endif
|
#endif
|
||||||
|
//// --- End LibAFL code ---
|
||||||
{
|
{
|
||||||
struct target_pt_regs regs1, *regs = ®s1;
|
struct target_pt_regs regs1, *regs = ®s1;
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
//struct image_info info1, *info = &info1;
|
//struct image_info info1, *info = &info1;
|
||||||
struct image_info *info = &libafl_image_info;
|
struct image_info *info = libafl_get_image_info();
|
||||||
// struct linux_binprm bprm;
|
// struct linux_binprm bprm;
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
TaskState *ts;
|
TaskState *ts;
|
||||||
@ -1076,7 +1058,7 @@ int main(int argc, char **argv, char **envp)
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
libafl_qemu_env = env;
|
libafl_set_qemu_env(env);
|
||||||
|
|
||||||
#ifndef AS_LIB
|
#ifndef AS_LIB
|
||||||
return libafl_qemu_main();
|
return libafl_qemu_main();
|
||||||
|
@ -34,12 +34,21 @@
|
|||||||
#include "user/safe-syscall.h"
|
#include "user/safe-syscall.h"
|
||||||
#include "tcg/tcg.h"
|
#include "tcg/tcg.h"
|
||||||
|
|
||||||
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
|
#include "libafl/user.h"
|
||||||
|
|
||||||
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
/* target_siginfo_t must fit in gdbstub's siginfo save area. */
|
/* target_siginfo_t must fit in gdbstub's siginfo save area. */
|
||||||
QEMU_BUILD_BUG_ON(sizeof(target_siginfo_t) > MAX_SIGINFO_LENGTH);
|
QEMU_BUILD_BUG_ON(sizeof(target_siginfo_t) > MAX_SIGINFO_LENGTH);
|
||||||
|
|
||||||
static struct target_sigaction sigact_table[TARGET_NSIG];
|
static struct target_sigaction sigact_table[TARGET_NSIG];
|
||||||
|
|
||||||
static void host_signal_handler(int host_signum, siginfo_t *info,
|
//// --- Begin LibAFL code ---
|
||||||
|
/* static */
|
||||||
|
//// --- End LibAFL code ---
|
||||||
|
void host_signal_handler(int host_signum, siginfo_t *info,
|
||||||
void *puc);
|
void *puc);
|
||||||
|
|
||||||
/* Fallback addresses into sigtramp page. */
|
/* Fallback addresses into sigtramp page. */
|
||||||
@ -729,7 +738,6 @@ void die_with_signal(int host_sig)
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
void (*libafl_dump_core_hook)(int host_sig);
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
@ -770,8 +778,8 @@ void dump_core_and_abort(CPUArchState *env, int target_sig)
|
|||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
if (libafl_dump_core_hook) libafl_dump_core_hook(host_sig);
|
libafl_dump_core_exec(host_sig);
|
||||||
|
|
||||||
// die_with_signal_nodfl(host_sig); // to trigger LibAFL sig handler
|
// die_with_signal_nodfl(host_sig); // to trigger LibAFL sig handler
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
@ -890,9 +898,9 @@ void die_from_signal(siginfo_t *info)
|
|||||||
sig, code, info->si_addr);
|
sig, code, info->si_addr);
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
//// --- Begin LibAFL code ---
|
||||||
|
|
||||||
if (libafl_dump_core_hook) libafl_dump_core_hook(info->si_signo);
|
libafl_dump_core_exec(info->si_signo);
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
die_with_signal(info->si_signo);
|
die_with_signal(info->si_signo);
|
||||||
@ -997,15 +1005,12 @@ static uintptr_t host_sigbus_handler(CPUState *cpu, siginfo_t *info,
|
|||||||
pc, guest_addr);
|
pc, guest_addr);
|
||||||
} */
|
} */
|
||||||
|
|
||||||
#include "libafl/user.h"
|
|
||||||
|
|
||||||
void libafl_qemu_handle_crash(int host_sig, siginfo_t *info, void *puc) {
|
|
||||||
host_signal_handler(host_sig, info, puc);
|
|
||||||
}
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
//// --- End LibAFL code ---
|
||||||
|
|
||||||
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
|
//// --- Begin LibAFL code ---
|
||||||
|
/* static */
|
||||||
|
//// --- End LibAFL code ---
|
||||||
|
void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
|
||||||
{
|
{
|
||||||
CPUState *cpu = thread_cpu;
|
CPUState *cpu = thread_cpu;
|
||||||
CPUArchState *env = cpu_env(cpu);
|
CPUArchState *env = cpu_env(cpu);
|
||||||
|
@ -805,7 +805,10 @@ static inline int host_to_target_sock_type(int host_type)
|
|||||||
return target_type;
|
return target_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static abi_ulong target_brk, initial_target_brk;
|
//// --- Begin LibAFL code ---
|
||||||
|
/* static */
|
||||||
|
//// --- End LibAFL code ---
|
||||||
|
abi_ulong target_brk, initial_target_brk;
|
||||||
|
|
||||||
void target_set_brk(abi_ulong new_brk)
|
void target_set_brk(abi_ulong new_brk)
|
||||||
{
|
{
|
||||||
@ -813,23 +816,6 @@ void target_set_brk(abi_ulong new_brk)
|
|||||||
initial_target_brk = target_brk;
|
initial_target_brk = target_brk;
|
||||||
}
|
}
|
||||||
|
|
||||||
//// --- Begin LibAFL code ---
|
|
||||||
|
|
||||||
uint64_t libafl_get_brk(void);
|
|
||||||
uint64_t libafl_set_brk(uint64_t new_brk);
|
|
||||||
|
|
||||||
uint64_t libafl_get_brk(void) {
|
|
||||||
return (uint64_t)target_brk;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t libafl_set_brk(uint64_t new_brk) {
|
|
||||||
uint64_t old_brk = (uint64_t)target_brk;
|
|
||||||
target_brk = (abi_ulong)new_brk;
|
|
||||||
return old_brk;
|
|
||||||
}
|
|
||||||
|
|
||||||
//// --- End LibAFL code ---
|
|
||||||
|
|
||||||
/* do_brk() must return target values and target errnos. */
|
/* do_brk() must return target values and target errnos. */
|
||||||
abi_long do_brk(abi_ulong brk_val)
|
abi_long do_brk(abi_ulong brk_val)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user