diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 44b1d6c6bf..5b3a454482 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -20,6 +20,8 @@ //// --- Begin LibAFL code --- +#include "tcg/tcg-internal.h" + struct libafl_breakpoint { target_ulong addr; struct libafl_breakpoint* next; @@ -27,6 +29,15 @@ struct libafl_breakpoint { extern struct libafl_breakpoint* libafl_qemu_breakpoints; +struct libafl_hook { + target_ulong addr; + void (*callback)(void); + TCGHelperInfo helper_info; + struct libafl_hook* next; +}; + +extern struct libafl_hook* libafl_qemu_hooks; + //// --- End LibAFL code --- /* Pairs with tcg_clear_temp_count. @@ -110,6 +121,14 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db, bp = bp->next; } + struct libafl_hook* hk = libafl_qemu_hooks; + while (hk) { + if (hk->addr == db->pc_next) { + tcg_gen_callN(hk->callback, NULL, 0, NULL); + } + hk = hk->next; + } + //// --- End LibAFL code --- /* Disassemble one instruction. The translate_insn hook should diff --git a/cpu.c b/cpu.c index 5f01cae2b4..c059d02f90 100644 --- a/cpu.c +++ b/cpu.c @@ -42,6 +42,10 @@ //// --- Begin LibAFL code --- +#include "tcg/tcg-op.h" +#include "tcg/tcg-internal.h" +#include "exec/helper-head.h" + struct libafl_breakpoint { target_ulong addr; struct libafl_breakpoint* next; @@ -49,6 +53,17 @@ struct libafl_breakpoint { struct libafl_breakpoint* libafl_qemu_breakpoints = NULL; +struct libafl_hook { + target_ulong addr; + void (*callback)(void); + TCGHelperInfo helper_info; + struct libafl_hook* next; +}; + +struct libafl_hook* libafl_qemu_hooks = NULL; + +void libafl_helper_table_add(TCGHelperInfo* info); + static GByteArray *libafl_qemu_mem_buf = NULL; int libafl_qemu_write_reg(int reg, uint8_t* val); @@ -56,6 +71,8 @@ int libafl_qemu_read_reg(int reg, uint8_t* val); int libafl_qemu_num_regs(void); int libafl_qemu_set_breakpoint(uint64_t addr); int libafl_qemu_remove_breakpoint(uint64_t addr); +int libafl_qemu_insert_hook(uint64_t addr, void (*callback)(void)); +int libafl_qemu_remove_hook(uint64_t addr); int libafl_qemu_write_reg(int reg, uint8_t* val) { @@ -126,6 +143,7 @@ int libafl_qemu_set_breakpoint(uint64_t addr) int libafl_qemu_remove_breakpoint(uint64_t addr) { CPUState *cpu; + int r = 0; target_ulong pc = (target_ulong) addr; struct libafl_breakpoint** bp = &libafl_qemu_breakpoints; @@ -136,11 +154,54 @@ int libafl_qemu_remove_breakpoint(uint64_t addr) } *bp = (*bp)->next; - return 1; + r = 1; } bp = &(*bp)->next; } - return 0; + return r; +} + +int libafl_qemu_insert_hook(uint64_t addr, void (*callback)(void)) +{ + CPUState *cpu; + + target_ulong pc = (target_ulong) addr; + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, pc); + } + + struct libafl_hook* hk = malloc(sizeof(struct libafl_hook)); + hk->addr = pc; + hk->callback = callback; + hk->helper_info.func = callback; + hk->helper_info.name = "libafl_hook"; + hk->helper_info.flags = dh_callflag(void); + hk->helper_info.typemask = dh_typemask(void, 0); + hk->next = libafl_qemu_hooks; + libafl_qemu_hooks = hk; + libafl_helper_table_add(&hk->helper_info); + return 1; +} + +int libafl_qemu_remove_hook(uint64_t addr) +{ + CPUState *cpu; + int r = 0; + + target_ulong pc = (target_ulong) addr; + struct libafl_hook** hk = &libafl_qemu_hooks; + while (*hk) { + if ((*hk)->addr == pc) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, pc); + } + + *hk = (*hk)->next; + r = 1; + } + hk = &(*hk)->next; + } + return r; } //// --- End LibAFL code ---