diff --git a/cpu-target.c b/cpu-target.c index b7d4d76d35..d82b61625b 100644 --- a/cpu-target.c +++ b/cpu-target.c @@ -62,6 +62,16 @@ int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val); int libafl_qemu_num_regs(CPUState* cpu); //// --- Begin LibAFL code --- +int libafl_qemu_set_breakpoint(target_ulong addr); +int libafl_qemu_remove_breakpoint(target_ulong addr); +void libafl_qemu_set_native_breakpoint( vaddr ); +void libafl_qemu_remove_native_breakpoint( vaddr ); +size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t), + uint64_t data, int invalidate); +size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate); +int libafl_qemu_remove_hook(size_t num, int invalidate); +struct libafl_hook* libafl_search_hook(target_ulong addr); +void libafl_flush_jit(void); #ifndef CONFIG_USER_ONLY hwaddr libafl_qemu_current_paging_id(CPUState* cpu); @@ -175,6 +185,137 @@ hwaddr libafl_qemu_current_paging_id(CPUState* cpu) } #endif +int libafl_qemu_remove_breakpoint(target_ulong pc) +{ + CPUState *cpu; + int r = 0; + + struct libafl_breakpoint** bp = &libafl_qemu_breakpoints; + while (*bp) { + if ((*bp)->addr == pc) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, pc); + } + + *bp = (*bp)->next; + r = 1; + } else { + bp = &(*bp)->next; + } + } + return r; +} + +void libafl_qemu_set_native_breakpoint(vaddr pc) +{ + CPUState *cpu; + CPU_FOREACH(cpu) { + cpu_breakpoint_insert(cpu, pc, BP_GDB, NULL); + } +} + +void libafl_qemu_remove_native_breakpoint(vaddr pc) +{ + CPUState *cpu; + CPU_FOREACH(cpu) { + cpu_breakpoint_remove(cpu, pc, BP_GDB); + } +} + +size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t), + uint64_t data, int invalidate) +{ + CPUState *cpu; + + if (invalidate) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, pc); + } + } + + size_t idx = LIBAFL_TABLES_HASH(pc); + + struct libafl_hook* hk = calloc(sizeof(struct libafl_hook), 1); + hk->addr = pc; + hk->callback = callback; + hk->data = data; + 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) | dh_typemask(tl, 1) | dh_typemask(i64, 2); + hk->num = libafl_qemu_hooks_num++; + hk->next = libafl_qemu_hooks[idx]; + libafl_qemu_hooks[idx] = hk; + return hk->num; +} + +size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate) +{ + CPUState *cpu; + size_t r = 0; + + size_t idx = LIBAFL_TABLES_HASH(addr); + struct libafl_hook** hk = &libafl_qemu_hooks[idx]; + while (*hk) { + if ((*hk)->addr == addr) { + if (invalidate) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, addr); + } + } + + void *tmp = *hk; + *hk = (*hk)->next; + free(tmp); + r++; + } else { + hk = &(*hk)->next; + } + } + return r; +} + +int libafl_qemu_remove_hook(size_t num, int invalidate) +{ + CPUState *cpu; + size_t idx; + + for (idx = 0; idx < LIBAFL_TABLES_SIZE; ++idx) { + struct libafl_hook** hk = &libafl_qemu_hooks[idx]; + while (*hk) { + if ((*hk)->num == num) { + if (invalidate) { + CPU_FOREACH(cpu) { + libafl_breakpoint_invalidate(cpu, (*hk)->addr); + } + } + + void *tmp = *hk; + *hk = (*hk)->next; + free(tmp); + return 1; + } else { + hk = &(*hk)->next; + } + } + } + return 0; +} + +struct libafl_hook* libafl_search_hook(target_ulong addr) +{ + size_t idx = LIBAFL_TABLES_HASH(addr); + + struct libafl_hook* hk = libafl_qemu_hooks[idx]; + while (hk) { + if (hk->addr == addr) { + return hk; + } + hk = hk->next; + } + + return NULL; +} //// --- End LibAFL code --- void libafl_flush_jit(void) diff --git a/system/cpus.c b/system/cpus.c index 7137dd49bb..66561ab390 100644 --- a/system/cpus.c +++ b/system/cpus.c @@ -313,7 +313,10 @@ void cpu_handle_guest_debug(CPUState *cpu) cpu_single_step(cpu, 0); } } else { - gdb_set_stop_cpu(cpu); + /* Begin LibAFL changes */ + // With LibAFL Breakpoints there is no gdb attached. + // gdb_set_stop_cpu(cpu); + /* End LibAFL changes */ qemu_system_debug_request(); cpu->stopped = true; }