Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Early return from libafl edge generation if no exec hooks #85

Merged
merged 2 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions accel/tcg/cpu-exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,13 +1039,13 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)

//// --- Begin LibAFL code ---

int has_libafl_edge = 0;
bool libafl_edge_generated = false;
TranslationBlock *edge;

/* See if we can patch the calling TB. */
if (last_tb) {
// tb_add_jump(last_tb, tb_exit, tb);

if (last_tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
mmap_lock();
edge = libafl_gen_edge(cpu, last_tb->pc, pc, tb_exit, cs_base, flags, cflags);
Expand All @@ -1054,7 +1054,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
if (edge) {
tb_add_jump(last_tb, tb_exit, edge);
tb_add_jump(edge, 0, tb);
has_libafl_edge = 1;
libafl_edge_generated = true;
} else {
tb_add_jump(last_tb, tb_exit, tb);
}
Expand All @@ -1063,7 +1063,7 @@ cpu_exec_loop(CPUState *cpu, SyncClocks *sc)
}
}

if (has_libafl_edge) {
if (libafl_edge_generated) {
// execute the edge to make sure to log it the first execution
// the edge will then jump to the translated block
cpu_loop_exec_tb(cpu, edge, pc, &last_tb, &tb_exit);
Expand Down
14 changes: 9 additions & 5 deletions accel/tcg/translate-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,11 +378,20 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
int64_t ti;
void *host_pc;

// edge hooks generation callbacks
// early check if it should be skipped or not
bool no_exec_hook = libafl_qemu_hook_edge_gen(src_block, dst_block);
if (no_exec_hook) {
// no exec hooks to run for edges, not point in generating a TB
return NULL;
}

target_ulong pc = src_block ^ reverse_bits((target_ulong)exit_n);

assert_memory_lock();
qemu_thread_jit_write();

// TODO: this (get_page_addr_code_hostp) is a bottleneck in systemmode, investigate why
phys_pc = get_page_addr_code_hostp(env, src_block, &host_pc);
phys_pc ^= reverse_bits((tb_page_addr_t)exit_n);

Expand All @@ -401,11 +410,6 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
}
QEMU_BUILD_BUG_ON(CF_COUNT_MASK + 1 != TCG_MAX_INSNS);

// edge hooks generation callbacks
bool no_exec_hook = libafl_qemu_hook_edge_gen(src_block, dst_block);
if (no_exec_hook)
return NULL;

buffer_overflow:
assert_no_pages_locked();
tb = tcg_tb_alloc(tcg_ctx);
Expand Down
31 changes: 20 additions & 11 deletions include/libafl/exit.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ enum libafl_exit_reason_kind {
INTERNAL = 0,
BREAKPOINT = 1,
SYNC_EXIT = 2,
TIMEOUT = 3,
};

// QEMU exited on its own for some reason.
struct libafl_exit_reason_internal {
ShutdownCause cause;
int signal; // valid if cause == SHUTDOWN_CAUSE_HOST_SIGNAL
};

// A breakpoint has been triggered.
Expand All @@ -29,23 +36,20 @@ struct libafl_exit_reason_breakpoint {
};

// A synchronous exit has been triggered.
struct libafl_exit_reason_sync_exit {
};
struct libafl_exit_reason_sync_exit {};

// QEMU exited on its own for some reason.
struct libafl_exit_reason_internal {
ShutdownCause cause;
int signal; // valid if cause == SHUTDOWN_CAUSE_HOST_SIGNAL
};
// A timeout occured and we were asked to exit on timeout
struct libafl_exit_reason_timeout {};

struct libafl_exit_reason {
enum libafl_exit_reason_kind kind;
CPUState* cpu; // CPU that triggered an exit.
vaddr next_pc; // The PC that should be stored in the CPU when re-entering.
union {
struct libafl_exit_reason_internal internal;
struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT
struct libafl_exit_reason_sync_exit sync_exit; // kind == SYNC_EXIT
struct libafl_exit_reason_internal internal; // kind == INTERNAL
struct libafl_exit_reason_breakpoint breakpoint; // kind == BREAKPOINT
struct libafl_exit_reason_sync_exit sync_exit; // kind == SYNC_EXIT
struct libafl_exit_reason_timeout timeout; // kind == TIMEOUT
} data;
};

Expand All @@ -59,6 +63,11 @@ void libafl_sync_exit_cpu(void);

void libafl_exit_request_internal(CPUState* cpu, uint64_t pc,
ShutdownCause cause, int signal);
void libafl_exit_request_sync_backdoor(CPUState* cpu, target_ulong pc);
void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc);
void libafl_exit_request_sync_backdoor(CPUState* cpu, target_ulong pc);

#ifndef CONFIG_USER_ONLY
void libafl_exit_request_timeout(void);
#endif

struct libafl_exit_reason* libafl_get_exit_reason(void);
12 changes: 12 additions & 0 deletions libafl/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ static void prepare_qemu_exit(CPUState* cpu, target_ulong next_pc)
qemu_system_debug_request();
cpu->stopped = true; // TODO check if still needed
#endif

// in usermode, this may be called from the syscall hook, thus already out
// of the cpu_exec but still in the cpu_loop
if (cpu->running) {
Expand Down Expand Up @@ -125,6 +126,17 @@ void libafl_exit_request_breakpoint(CPUState* cpu, target_ulong pc)
prepare_qemu_exit(cpu, pc);
}

#ifndef CONFIG_USER_ONLY
void libafl_exit_request_timeout(void)
{
expected_exit = true;
last_exit_reason.kind = TIMEOUT;
last_exit_reason.cpu = current_cpu;

qemu_system_debug_request();
}
#endif

void libafl_qemu_trigger_breakpoint(CPUState* cpu)
{
CPUClass* cc = CPU_GET_CLASS(cpu);
Expand Down
7 changes: 6 additions & 1 deletion libafl/hooks/tcg/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ void libafl_qemu_hook_block_run(target_ulong pc)

while (hook) {
uint64_t cur_id = 0;
if (hook->gen)

if (hook->gen) {
cur_id = hook->gen(hook->data, pc);
}

if (cur_id != (uint64_t)-1 && hook->helper_info.func) {
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
Expand All @@ -81,9 +84,11 @@ void libafl_qemu_hook_block_run(target_ulong pc)
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
}

if (cur_id != (uint64_t)-1 && hook->jit) {
hook->jit(hook->data, cur_id);
}

hook = hook->next;
}
}
11 changes: 9 additions & 2 deletions libafl/hooks/tcg/edge.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,22 @@ bool libafl_qemu_hook_edge_gen(target_ulong src_block, target_ulong dst_block)
{
struct libafl_edge_hook* hook = libafl_edge_hooks;
bool no_exec_hook = true;

while (hook) {
hook->cur_id = 0;
if (hook->gen)

if (hook->gen) {
hook->cur_id = hook->gen(hook->data, src_block, dst_block);
}

if (hook->cur_id != (uint64_t)-1 &&
(hook->helper_info.func || hook->jit))
(hook->helper_info.func || hook->jit)) {
no_exec_hook = false;
}

hook = hook->next;
}

return no_exec_hook;
}

Expand Down
4 changes: 2 additions & 2 deletions libafl/syx-snapshot/syx-snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,8 +713,8 @@ SyxSnapshotCheckResult syx_snapshot_check(SyxSnapshot* ref_snapshot)
void syx_snapshot_root_restore(SyxSnapshot* snapshot)
{
// health check.
CPUState* cpu;
CPU_FOREACH(cpu) { assert(cpu->stopped); }
// CPUState* cpu;
// CPU_FOREACH(cpu) { assert(cpu->stopped); }

bool must_unlock_bql = false;

Expand Down
7 changes: 6 additions & 1 deletion subprojects/libvduse/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ add_project_arguments(cc.get_supported_arguments('-Wsign-compare',
'-Wstrict-aliasing'),
native: false, language: 'c')

#### --- Begin LibAFL code ---
keyval = import('keyval')
config_host = keyval.load(meson.global_build_root() / 'config-host.mak')
#### --- End LibAFL code ---

libvduse = static_library('vduse',
files('libvduse.c'),
c_args: '-D_GNU_SOURCE',
pic: 'AS_SHARED_LIB' in config_host)
#### --- Begin LibAFL code ---
pic: 'AS_SHARED_LIB' in config_host
#### --- End LibAFL code ---
)

libvduse_dep = declare_dependency(link_with: libvduse,
include_directories: include_directories('.'))
Loading