Skip to content

Commit

Permalink
Add pre/post cpu_run hooks + Refactoring (#82)
Browse files Browse the repository at this point in the history
* Add cpu_run pre/post exec hooks, to hook the cpu just before / after it runs target code.
* Refactor hooks to separate them in different files
* Remove most extern variables
* Reduce the amount of extra code in QEMU
* Add clang-format script
  • Loading branch information
rmalmain committed Aug 13, 2024
1 parent 11b27cc commit 86d38fb
Show file tree
Hide file tree
Showing 44 changed files with 2,147 additions and 1,498 deletions.
18 changes: 18 additions & 0 deletions accel/kvm/kvm-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
#include "hw/boards.h"
#include "sysemu/stats.h"

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

#include "libafl/hooks/cpu_run.h"

//// --- End LibAFL code ---

/* This check must be after config-host.h is included */
#ifdef CONFIG_EVENTFD
#include <sys/eventfd.h>
Expand Down Expand Up @@ -2866,10 +2872,22 @@ int kvm_cpu_exec(CPUState *cpu)
*/
smp_rmb();

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

libafl_hook_cpu_run_pre_exec(cpu);

//// --- End LibAFL code ---

run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);

attrs = kvm_arch_post_run(cpu, run);

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

libafl_hook_cpu_run_post_exec(cpu);

//// --- End LibAFL code ---

#ifdef KVM_HAVE_MCE_INJECTION
if (unlikely(have_sigbus_pending)) {
bql_lock();
Expand Down
61 changes: 10 additions & 51 deletions accel/tcg/translate-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@

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

#include "libafl/hook.h"
#include "libafl/hooks/tcg/block.h"
#include "libafl/hooks/tcg/edge.h"

//// --- End LibAFL code ---

Expand Down Expand Up @@ -284,24 +285,7 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb,

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

struct libafl_block_hook* hook = libafl_block_hooks;
while (hook) {
uint64_t cur_id = 0;
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);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
tcg_gen_callN(&hook->helper_info, NULL, tmp2);
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;
}
libafl_qemu_hook_block_run(pc);

//// --- End LibAFL code ---

Expand Down Expand Up @@ -361,21 +345,9 @@ static int libafl_setjmp_gen_code(CPUArchState *env, TranslationBlock *tb,
#error Unhandled TARGET_INSN_START_EXTRA_WORDS value
#endif

struct libafl_edge_hook* hook = libafl_edge_hooks;
while (hook) {
if (hook->cur_id != (uint64_t)-1 && hook->helper_info.func) {
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(hook->cur_id);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
tcg_gen_callN(&hook->helper_info, NULL, tmp2);
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
}
if (hook->cur_id != (uint64_t)-1 && hook->jit) {
hook->jit(hook->data, hook->cur_id);
}
hook = hook->next;
}
// run edge hooks
libafl_qemu_hook_edge_run();

tcg_gen_goto_tb(0);
tcg_gen_exit_tb(tb, 0);

Expand Down Expand Up @@ -430,16 +402,7 @@ 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
struct libafl_edge_hook* hook = libafl_edge_hooks;
int no_exec_hook = 1;
while (hook) {
hook->cur_id = 0;
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))
no_exec_hook = 0;
hook = hook->next;
}
bool no_exec_hook = libafl_qemu_hook_edge_gen(src_block, dst_block);
if (no_exec_hook)
return NULL;

Expand Down Expand Up @@ -749,13 +712,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
tb->tc.size = gen_code_size;

//// --- Begin LibAFL code ---
struct libafl_block_hook *hook = libafl_block_hooks;
while (hook)
{
if (hook->post_gen)
hook->post_gen(hook->data, pc, tb->size);
hook = hook->next;
}

libafl_qemu_hook_block_post_gen(tb, pc);

//// --- End LibAFL code ---

/*
Expand Down
45 changes: 6 additions & 39 deletions accel/tcg/translator.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags,
#include "libafl/exit.h"
#include "libafl/hook.h"

#include "libafl/hooks/tcg/instruction.h"
#include "libafl/hooks/tcg/backdoor.h"

#ifndef TARGET_LONG_BITS
#error "TARGET_LONG_BITS not defined"
#endif
Expand Down Expand Up @@ -168,37 +171,10 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,

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

struct libafl_hook* hk = libafl_search_instruction_hook(db->pc_next);
if (hk) {
TCGv_i64 tmp0 = tcg_constant_i64(hk->data);
#if TARGET_LONG_BITS == 32
TCGv_i32 tmp1 = tcg_constant_i32(db->pc_next);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i32_temp(tmp1) };
#else
TCGv_i64 tmp1 = tcg_constant_i64(db->pc_next);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
#endif
// tcg_gen_callN(hk->callback, NULL, 2, tmp2);
tcg_gen_callN(&hk->helper_info, NULL, tmp2);
#if TARGET_LONG_BITS == 32
tcg_temp_free_i32(tmp1);
#else
tcg_temp_free_i64(tmp1);
#endif
tcg_temp_free_i64(tmp0);
}

struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
while (bp) {
if (bp->addr == db->pc_next) {
TCGv_i64 tmp0 = tcg_constant_i64((uint64_t)db->pc_next);
gen_helper_libafl_qemu_handle_breakpoint(tcg_env, tmp0);
tcg_temp_free_i64(tmp0);
}
bp = bp->next;
}
libafl_qemu_hook_instruction_run(db->pc_next);

libafl_gen_cur_pc = db->pc_next;
libafl_qemu_breakpoint_run(libafl_gen_cur_pc);

// 0x0f, 0x3a, 0xf2, 0x44
uint8_t backdoor = translator_ldub(cpu_env(cpu), db, db->pc_next);
Expand All @@ -209,16 +185,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
if (backdoor == 0xf2) {
backdoor = translator_ldub(cpu_env(cpu), db, db->pc_next +3);
if (backdoor == 0x44) {
struct libafl_backdoor_hook* bhk = libafl_backdoor_hooks;
while (bhk) {
TCGv_i64 tmp0 = tcg_constant_i64(bhk->data);
TCGv tmp2 = tcg_constant_tl(db->pc_next);
TCGTemp *args[3] = { tcgv_i64_temp(tmp0), tcgv_ptr_temp(tcg_env), tcgv_tl_temp(tmp2) };

tcg_gen_callN(&bhk->helper_info, NULL, args);

bhk = bhk->next;
}
libafl_qemu_hook_backdoor_run(db->pc_next);

db->pc_next += 4;
goto post_translate_insn;
Expand Down
15 changes: 9 additions & 6 deletions include/libafl/exit.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include "qemu/osdep.h"

#include "exec/cpu-defs.h"
#include "exec/translator.h"

#define EXCP_LIBAFL_EXIT 0xf4775747

Expand All @@ -10,14 +12,13 @@ struct libafl_breakpoint {
struct libafl_breakpoint* next;
};

extern struct libafl_breakpoint* libafl_qemu_breakpoints;

// in cpu-target.c
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc);
void libafl_breakpoint_invalidate(CPUState* cpu, target_ulong pc);

int libafl_qemu_set_breakpoint(target_ulong pc);
int libafl_qemu_remove_breakpoint(target_ulong pc);
void libafl_qemu_trigger_breakpoint(CPUState* cpu);
void libafl_qemu_breakpoint_run(vaddr pc_next);

enum libafl_exit_reason_kind {
INTERNAL = 0,
Expand All @@ -31,7 +32,8 @@ 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 {
Expand All @@ -46,7 +48,7 @@ struct libafl_exit_reason {
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_sync_exit sync_exit; // kind == SYNC_EXIT
} data;
};

Expand All @@ -58,7 +60,8 @@ void libafl_exit_signal_vm_start(void);
bool libafl_exit_asap(void);
void libafl_sync_exit_cpu(void);

void libafl_exit_request_internal(CPUState* cpu, uint64_t pc, ShutdownCause cause, int signal);
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);
struct libafl_exit_reason* libafl_get_exit_reason(void);
Loading

0 comments on commit 86d38fb

Please sign in to comment.