libafl: breakpoints and regs r/w

This commit is contained in:
Andrea Fioraldi 2021-05-05 17:53:24 +02:00
parent 53c5433e84
commit 7fce6835b0
9 changed files with 220 additions and 2 deletions

View File

@ -487,6 +487,18 @@ static inline void cpu_handle_debug_exception(CPUState *cpu)
static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
{
//// --- Begin LibAFL code ---
#define EXCP_LIBAFL_BP 0xf4775747
if (cpu->exception_index == EXCP_LIBAFL_BP) {
*ret = cpu->exception_index;
cpu->exception_index = -1;
return true;
}
//// --- End LibAFL code ---
if (cpu->exception_index < 0) {
#ifndef CONFIG_USER_ONLY
if (replay_has_exception()

View File

@ -32,6 +32,19 @@
#include "tcg/tcg.h"
#include "exec/tb-lookup.h"
//// --- Begin LibAFL code ---
#define EXCP_LIBAFL_BP 0xf4775747
void HELPER(libafl_qemu_handle_breakpoint)(CPUArchState *env)
{
CPUState* cpu = env_cpu(env);
cpu->exception_index = EXCP_LIBAFL_BP;
cpu_loop_exit(cpu);
}
//// --- End LibAFL code ---
/* 32-bit helpers */
int32_t HELPER(div_i32)(int32_t arg1, int32_t arg2)

View File

@ -331,3 +331,9 @@ DEF_HELPER_FLAGS_4(gvec_leu32, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(gvec_leu64, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_5(gvec_bitsel, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
//// --- Begin LibAFL code ---
DEF_HELPER_FLAGS_1(libafl_qemu_handle_breakpoint, TCG_CALL_NO_RWG, void, env)
//// --- End LibAFL code ---

View File

@ -19,6 +19,17 @@
#include "exec/plugin-gen.h"
#include "sysemu/replay.h"
//// --- Begin LibAFL code ---
struct libafl_breakpoint {
target_ulong addr;
struct libafl_breakpoint* next;
};
extern struct libafl_breakpoint* libafl_qemu_breakpoints;
//// --- End LibAFL code ---
/* Pairs with tcg_clear_temp_count.
To be called by #TranslatorOps.{translate_insn,tb_stop} if
(1) the target is sufficiently clean to support reporting,
@ -91,6 +102,18 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
}
}
//// --- Begin LibAFL code ---
struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
while (bp) {
if (bp->addr == db->pc_next) {
gen_helper_libafl_qemu_handle_breakpoint(cpu_env);
}
bp = bp->next;
}
//// --- End LibAFL code ---
/* Disassemble one instruction. The translate_insn hook should
update db->pc_next and db->is_jmp to indicate what should be
done next -- either exiting this loop or locate the start of

104
cpu.c
View File

@ -37,6 +37,110 @@
#include "exec/translate-all.h"
#include "exec/log.h"
//// --- Begin LibAFL code ---
struct libafl_breakpoint {
target_ulong addr;
struct libafl_breakpoint* next;
};
struct libafl_breakpoint* libafl_qemu_breakpoints = NULL;
static GByteArray *libafl_qemu_mem_buf = NULL;
int libafl_qemu_write_reg(int reg, uint8_t* val);
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_write_reg(int reg, uint8_t* val)
{
CPUState *cpu = current_cpu;
if (!cpu) {
return 0;
}
if (libafl_qemu_mem_buf == NULL) {
libafl_qemu_mem_buf = g_byte_array_sized_new(64);
}
CPUClass *cc = CPU_GET_CLASS(cpu);
if (reg < cc->gdb_num_core_regs) {
return cc->gdb_write_register(cpu, val, reg);
}
return 0;
}
int libafl_qemu_read_reg(int reg, uint8_t* val)
{
CPUState *cpu = current_cpu;
if (!cpu) {
return 0;
}
CPUClass *cc = CPU_GET_CLASS(cpu);
if (reg < cc->gdb_num_core_regs) {
int len = cc->gdb_read_register(cpu, libafl_qemu_mem_buf, reg);
if (len > 0) {
memcpy(val, libafl_qemu_mem_buf->data, len);
}
return len;
}
return 0;
}
int libafl_qemu_num_regs(void)
{
CPUState *cpu = current_cpu;
if (!cpu) {
return 0;
}
CPUClass *cc = CPU_GET_CLASS(cpu);
return cc->gdb_num_core_regs;
}
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc);
int libafl_qemu_set_breakpoint(uint64_t addr)
{
CPUState *cpu;
target_ulong pc = (target_ulong) addr;
CPU_FOREACH(cpu) {
breakpoint_invalidate(cpu, pc);
}
struct libafl_breakpoint* bp = malloc(sizeof(struct libafl_breakpoint));
bp->addr = pc;
bp->next = libafl_qemu_breakpoints;
libafl_qemu_breakpoints = bp;
return 1;
}
int libafl_qemu_remove_breakpoint(uint64_t addr)
{
CPUState *cpu;
target_ulong pc = (target_ulong) addr;
struct libafl_breakpoint** bp = &libafl_qemu_breakpoints;
while (*bp) {
if ((*bp)->addr == pc) {
CPU_FOREACH(cpu) {
breakpoint_invalidate(cpu, pc);
}
*bp = (*bp)->next;
return 1;
}
bp = &(*bp)->next;
}
return 0;
}
//// --- End LibAFL code ---
uintptr_t qemu_host_page_size;
intptr_t qemu_host_page_mask;

View File

@ -88,6 +88,16 @@ void cpu_loop(CPUARMState *env)
process_queued_cpu_work(cs);
switch (trapnr) {
//// --- Begin LibAFL code ---
#define EXCP_LIBAFL_BP 0xf4775747
case EXCP_LIBAFL_BP:
return;
//// --- End LibAFL code ---
case EXCP_SWI:
ret = do_syscall(env,
env->xregs[8],

View File

@ -240,6 +240,16 @@ void cpu_loop(CPUARMState *env)
process_queued_cpu_work(cs);
switch(trapnr) {
//// --- Begin LibAFL code ---
#define EXCP_LIBAFL_BP 0xf4775747
case EXCP_LIBAFL_BP:
return;
//// --- End LibAFL code ---
case EXCP_UDEF:
case EXCP_NOCP:
case EXCP_INVSTATE:

View File

@ -209,6 +209,16 @@ void cpu_loop(CPUX86State *env)
process_queued_cpu_work(cs);
switch(trapnr) {
//// --- Begin LibAFL code ---
#define EXCP_LIBAFL_BP 0xf4775747
case EXCP_LIBAFL_BP:
return;
//// --- End LibAFL code ---
case 0x80:
/* linux syscall from int $0x80 */
ret = do_syscall(env,

View File

@ -621,6 +621,27 @@ static int parse_args(int argc, char **argv)
return optind;
}
//// --- Begin LibAFL code ---
int libafl_qemu_main(void);
int libafl_qemu_run(void);
static CPUArchState *libafl_qemu_env;
__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 ---
int main(int argc, char **argv, char **envp)
{
struct target_pt_regs regs1, *regs = &regs1;
@ -886,7 +907,16 @@ int main(int argc, char **argv, char **envp)
}
gdb_handlesig(cpu, 0);
}
cpu_loop(env);
// cpu_loop(env);
//// --- Begin LibAFL code ---
libafl_qemu_env = env;
return libafl_qemu_main();
//// --- End LibAFL code ---
/* never exits */
return 0;
// return 0;
}