diff options
Diffstat (limited to 'qemu_mode/patches')
-rw-r--r-- | qemu_mode/patches/afl-qemu-common.h | 22 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-cpu-inl.h | 70 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-cpu-translate-inl.h | 273 | ||||
-rw-r--r-- | qemu_mode/patches/arm-translate-a64.diff | 64 | ||||
-rw-r--r-- | qemu_mode/patches/arm-translate.diff | 20 | ||||
-rw-r--r-- | qemu_mode/patches/configure.diff | 26 | ||||
-rw-r--r-- | qemu_mode/patches/i386-translate.diff | 2 |
7 files changed, 402 insertions, 75 deletions
diff --git a/qemu_mode/patches/afl-qemu-common.h b/qemu_mode/patches/afl-qemu-common.h index 4d651385..4303a5e6 100644 --- a/qemu_mode/patches/afl-qemu-common.h +++ b/qemu_mode/patches/afl-qemu-common.h @@ -35,11 +35,18 @@ #define __AFL_QEMU_COMMON #include "../../config.h" +#include "../../include/cmplog.h" -#ifndef CPU_NB_REGS -#define AFL_REGS_NUM 1000 -#else +#define PERSISTENT_DEFAULT_MAX_CNT 1000 + +#ifdef CPU_NB_REGS #define AFL_REGS_NUM CPU_NB_REGS +#elif TARGET_ARM +#define AFL_REGS_NUM 32 +#elif TARGET_AARCH64 +#define AFL_REGS_NUM 32 +#else +#define AFL_REGS_NUM 100 #endif /* NeverZero */ @@ -56,6 +63,8 @@ #define INC_AFL_AREA(loc) afl_area_ptr[loc]++ #endif +typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base); + /* Declared in afl-qemu-cpu-inl.h */ extern unsigned char *afl_area_ptr; @@ -69,11 +78,16 @@ extern unsigned char is_persistent; extern target_long persistent_stack_offset; extern unsigned char persistent_first_pass; extern unsigned char persistent_save_gpr; -extern target_ulong persistent_saved_gpr[AFL_REGS_NUM]; +extern uint64_t persistent_saved_gpr[AFL_REGS_NUM]; extern int persisent_retaddr_offset; +extern afl_persistent_hook_fn afl_persistent_hook_ptr; + extern __thread abi_ulong afl_prev_loc; +extern struct cmp_map *__afl_cmp_map; +extern __thread u32 __afl_cmp_counter; + void afl_debug_dump_saved_regs(); void afl_persistent_loop(); diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index ac847371..5e155c74 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -32,10 +32,11 @@ */ #include <sys/shm.h> -#include "../../config.h" #include "afl-qemu-common.h" -#define PERSISTENT_DEFAULT_MAX_CNT 1000 +#ifndef AFL_QEMU_STATIC_BUILD +#include <dlfcn.h> +#endif /*************************** * VARIOUS AUXILIARY STUFF * @@ -81,6 +82,9 @@ u8 afl_compcov_level; __thread abi_ulong afl_prev_loc; +struct cmp_map *__afl_cmp_map; +__thread u32 __afl_cmp_counter; + /* Set in the child process in forkserver mode: */ static int forkserver_installed = 0; @@ -95,6 +99,8 @@ unsigned char persistent_save_gpr; target_ulong persistent_saved_gpr[AFL_REGS_NUM]; int persisent_retaddr_offset; +afl_persistent_hook_fn afl_persistent_hook_ptr; + /* Instrumentation ratio: */ unsigned int afl_inst_rms = MAP_SIZE; /* Exported for afl_gen_trace */ @@ -182,6 +188,22 @@ static void afl_setup(void) { } + if (getenv("___AFL_EINS_ZWEI_POLIZEI___")) { // CmpLog forkserver + + id_str = getenv(CMPLOG_SHM_ENV_VAR); + + if (id_str) { + + u32 shm_id = atoi(id_str); + + __afl_cmp_map = shmat(shm_id, NULL, 0); + + if (__afl_cmp_map == (void *)-1) exit(1); + + } + + } + if (getenv("AFL_INST_LIBS")) { afl_start_code = 0; @@ -224,6 +246,43 @@ static void afl_setup(void) { if (getenv("AFL_QEMU_PERSISTENT_GPR")) persistent_save_gpr = 1; + if (getenv("AFL_QEMU_PERSISTENT_HOOK")) { + +#ifdef AFL_QEMU_STATIC_BUILD + + fprintf(stderr, + "[AFL] ERROR: you cannot use AFL_QEMU_PERSISTENT_HOOK when " + "afl-qemu-trace is static\n"); + exit(1); + +#else + + persistent_save_gpr = 1; + + void *plib = dlopen(getenv("AFL_QEMU_PERSISTENT_HOOK"), RTLD_NOW); + if (!plib) { + + fprintf(stderr, "[AFL] ERROR: invalid AFL_QEMU_PERSISTENT_HOOK=%s\n", + getenv("AFL_QEMU_PERSISTENT_HOOK")); + exit(1); + + } + + afl_persistent_hook_ptr = dlsym(plib, "afl_persistent_hook"); + if (!afl_persistent_hook_ptr) { + + fprintf(stderr, + "[AFL] ERROR: failed to find the function " + "\"afl_persistent_hook\" in %s\n", + getenv("AFL_QEMU_PERSISTENT_HOOK")); + exit(1); + + } + +#endif + + } + if (getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET")) persisent_retaddr_offset = strtoll(getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"), NULL, 0); @@ -352,8 +411,13 @@ static void afl_forkserver(CPUState *cpu) { if (WIFSTOPPED(status)) child_stopped = 1; - else if (unlikely(first_run && is_persistent)) + else if (unlikely(first_run && is_persistent)) { + + fprintf(stderr, "[AFL] ERROR: no persistent iteration executed\n"); exit(12); // Persistent is wrong + + } + first_run = 0; if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7); diff --git a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h index 6d42bf3d..6f526d92 100644 --- a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h @@ -102,31 +102,101 @@ static void afl_compcov_log_64(target_ulong cur_loc, target_ulong arg1, } +static void afl_cmplog_16(target_ulong cur_loc, target_ulong arg1, + target_ulong arg2) { + + register uintptr_t k = (uintptr_t)cur_loc; + + u32 hits = __afl_cmp_map->headers[k].hits; + __afl_cmp_map->headers[k].hits = hits + 1; + // if (!__afl_cmp_map->headers[k].cnt) + // __afl_cmp_map->headers[k].cnt = __afl_cmp_counter++; + + __afl_cmp_map->headers[k].shape = 1; + //__afl_cmp_map->headers[k].type = CMP_TYPE_INS; + + hits &= CMP_MAP_H - 1; + __afl_cmp_map->log[k][hits].v0 = arg1; + __afl_cmp_map->log[k][hits].v1 = arg2; + +} + +static void afl_cmplog_32(target_ulong cur_loc, target_ulong arg1, + target_ulong arg2) { + + register uintptr_t k = (uintptr_t)cur_loc; + + u32 hits = __afl_cmp_map->headers[k].hits; + __afl_cmp_map->headers[k].hits = hits + 1; + + __afl_cmp_map->headers[k].shape = 3; + + hits &= CMP_MAP_H - 1; + __afl_cmp_map->log[k][hits].v0 = arg1; + __afl_cmp_map->log[k][hits].v1 = arg2; + +} + +static void afl_cmplog_64(target_ulong cur_loc, target_ulong arg1, + target_ulong arg2) { + + register uintptr_t k = (uintptr_t)cur_loc; + + u32 hits = __afl_cmp_map->headers[k].hits; + __afl_cmp_map->headers[k].hits = hits + 1; + + __afl_cmp_map->headers[k].shape = 7; + + hits &= CMP_MAP_H - 1; + __afl_cmp_map->log[k][hits].v0 = arg1; + __afl_cmp_map->log[k][hits].v1 = arg2; + +} + static void afl_gen_compcov(target_ulong cur_loc, TCGv_i64 arg1, TCGv_i64 arg2, TCGMemOp ot, int is_imm) { void *func; - if (!afl_compcov_level || cur_loc > afl_end_code || cur_loc < afl_start_code) - return; + if (cur_loc > afl_end_code || cur_loc < afl_start_code) return; - if (!is_imm && afl_compcov_level < 2) return; + if (__afl_cmp_map) { - switch (ot) { + cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); + cur_loc &= CMP_MAP_W - 1; - case MO_64: func = &afl_compcov_log_64; break; - case MO_32: func = &afl_compcov_log_32; break; - case MO_16: func = &afl_compcov_log_16; break; - default: return; + switch (ot) { - } + case MO_64: func = &afl_cmplog_64; break; + case MO_32: func = &afl_cmplog_32; break; + case MO_16: func = &afl_cmplog_16; break; + default: return; - cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); - cur_loc &= MAP_SIZE - 7; + } + + tcg_gen_afl_compcov_log_call(func, cur_loc, arg1, arg2); + + } else if (afl_compcov_level) { + + if (!is_imm && afl_compcov_level < 2) return; + + cur_loc = (cur_loc >> 4) ^ (cur_loc << 8); + cur_loc &= MAP_SIZE - 7; + + if (cur_loc >= afl_inst_rms) return; - if (cur_loc >= afl_inst_rms) return; + switch (ot) { - tcg_gen_afl_compcov_log_call(func, cur_loc, arg1, arg2); + case MO_64: func = &afl_compcov_log_64; break; + case MO_32: func = &afl_compcov_log_32; break; + case MO_16: func = &afl_compcov_log_16; break; + default: return; + + } + + tcg_gen_afl_compcov_log_call(func, cur_loc, arg1, arg2); + + } } @@ -182,62 +252,77 @@ static void log_x86_sp_content(void) { }*/ -#define I386_RESTORE_STATE_FOR_PERSISTENT \ - do { \ - \ - if (persistent_save_gpr) { \ - \ - int i; \ - TCGv_ptr gpr_sv; \ - \ - TCGv_ptr first_pass_ptr = tcg_const_ptr(&persistent_first_pass); \ - TCGv first_pass = tcg_temp_local_new(); \ - TCGv one = tcg_const_tl(1); \ - tcg_gen_ld8u_tl(first_pass, first_pass_ptr, 0); \ - \ - TCGLabel *lbl_save_gpr = gen_new_label(); \ - TCGLabel *lbl_finish_restore_gpr = gen_new_label(); \ - tcg_gen_brcond_tl(TCG_COND_EQ, first_pass, one, lbl_save_gpr); \ - \ - for (i = 0; i < CPU_NB_REGS; ++i) { \ - \ - gpr_sv = tcg_const_ptr(&persistent_saved_gpr[i]); \ - tcg_gen_ld_tl(cpu_regs[i], gpr_sv, 0); \ - \ - } \ - \ - tcg_gen_br(lbl_finish_restore_gpr); \ - \ - gen_set_label(lbl_save_gpr); \ - \ - for (i = 0; i < CPU_NB_REGS; ++i) { \ - \ - gpr_sv = tcg_const_ptr(&persistent_saved_gpr[i]); \ - tcg_gen_st_tl(cpu_regs[i], gpr_sv, 0); \ - \ - } \ - \ - gen_set_label(lbl_finish_restore_gpr); \ - tcg_temp_free(first_pass); \ - \ - } else if (afl_persistent_ret_addr == 0) { \ - \ - TCGv_ptr stack_off_ptr = tcg_const_ptr(&persistent_stack_offset); \ - TCGv stack_off = tcg_temp_new(); \ - tcg_gen_ld_tl(stack_off, stack_off_ptr, 0); \ - tcg_gen_sub_tl(cpu_regs[R_ESP], cpu_regs[R_ESP], stack_off); \ - tcg_temp_free(stack_off); \ - \ - } \ - \ - } while (0) - -#define AFL_QEMU_TARGET_i386_SNIPPET \ +static void callback_to_persistent_hook(void) { + + afl_persistent_hook_ptr(persistent_saved_gpr, guest_base); + +} + +static void gpr_saving(TCGv *cpu_regs, int regs_num) { + + int i; + TCGv_ptr gpr_sv; + + TCGv_ptr first_pass_ptr = tcg_const_ptr(&persistent_first_pass); + TCGv first_pass = tcg_temp_local_new(); + TCGv one = tcg_const_tl(1); + tcg_gen_ld8u_tl(first_pass, first_pass_ptr, 0); + + TCGLabel *lbl_restore_gpr = gen_new_label(); + tcg_gen_brcond_tl(TCG_COND_NE, first_pass, one, lbl_restore_gpr); + + // save GPR registers + for (i = 0; i < regs_num; ++i) { + + gpr_sv = tcg_const_ptr(&persistent_saved_gpr[i]); + tcg_gen_st_tl(cpu_regs[i], gpr_sv, 0); + + } + + gen_set_label(lbl_restore_gpr); + + tcg_gen_afl_call0(&afl_persistent_loop); + + if (afl_persistent_hook_ptr) tcg_gen_afl_call0(callback_to_persistent_hook); + + // restore GPR registers + for (i = 0; i < regs_num; ++i) { + + gpr_sv = tcg_const_ptr(&persistent_saved_gpr[i]); + tcg_gen_ld_tl(cpu_regs[i], gpr_sv, 0); + + } + + tcg_temp_free_ptr(first_pass_ptr); + tcg_temp_free(first_pass); + tcg_temp_free(one); + +} + +static void restore_state_for_persistent(TCGv *cpu_regs, int regs_num, int sp) { + + if (persistent_save_gpr) { + + gpr_saving(cpu_regs, regs_num); + + } else if (afl_persistent_ret_addr == 0) { + + TCGv_ptr stack_off_ptr = tcg_const_ptr(&persistent_stack_offset); + TCGv stack_off = tcg_temp_new(); + tcg_gen_ld_tl(stack_off, stack_off_ptr, 0); + tcg_gen_sub_tl(cpu_regs[sp], cpu_regs[sp], stack_off); + tcg_temp_free(stack_off); + + } + +} + +#define AFL_QEMU_TARGET_I386_SNIPPET \ if (is_persistent) { \ \ if (s->pc == afl_persistent_addr) { \ \ - I386_RESTORE_STATE_FOR_PERSISTENT; \ + restore_state_for_persistent(cpu_regs, AFL_REGS_NUM, R_ESP); \ /*tcg_gen_afl_call0(log_x86_saved_gpr); \ tcg_gen_afl_call0(log_x86_sp_content);*/ \ \ @@ -245,9 +330,11 @@ static void log_x86_sp_content(void) { \ TCGv_ptr paddr = tcg_const_ptr(afl_persistent_addr); \ tcg_gen_st_tl(paddr, cpu_regs[R_ESP], persisent_retaddr_offset); \ + tcg_temp_free_ptr(paddr); \ \ } \ - tcg_gen_afl_call0(&afl_persistent_loop); \ + \ + if (!persistent_save_gpr) tcg_gen_afl_call0(&afl_persistent_loop); \ /*tcg_gen_afl_call0(log_x86_sp_content);*/ \ \ } else if (afl_persistent_ret_addr && s->pc == afl_persistent_ret_addr) { \ @@ -259,3 +346,57 @@ static void log_x86_sp_content(void) { \ } +// SP = 13, LINK = 14 + +#define AFL_QEMU_TARGET_ARM_SNIPPET \ + if (is_persistent) { \ + \ + if (dc->pc == afl_persistent_addr) { \ + \ + if (persistent_save_gpr) gpr_saving(cpu_R, AFL_REGS_NUM); \ + \ + if (afl_persistent_ret_addr == 0) { \ + \ + TCGv_ptr paddr = tcg_const_ptr(afl_persistent_addr); \ + tcg_gen_mov_i32(cpu_R[14], paddr); \ + tcg_temp_free_ptr(paddr); \ + \ + } \ + \ + if (!persistent_save_gpr) tcg_gen_afl_call0(&afl_persistent_loop); \ + \ + } else if (afl_persistent_ret_addr && dc->pc == afl_persistent_ret_addr) { \ + \ + gen_bx_im(dc, afl_persistent_addr); \ + \ + } \ + \ + } + +// SP = 31, LINK = 30 + +#define AFL_QEMU_TARGET_ARM64_SNIPPET \ + if (is_persistent) { \ + \ + if (s->pc == afl_persistent_addr) { \ + \ + if (persistent_save_gpr) gpr_saving(cpu_X, AFL_REGS_NUM); \ + \ + if (afl_persistent_ret_addr == 0) { \ + \ + TCGv_ptr paddr = tcg_const_ptr(afl_persistent_addr); \ + tcg_gen_mov_i32(cpu_X[30], paddr); \ + tcg_temp_free_ptr(paddr); \ + \ + } \ + \ + if (!persistent_save_gpr) tcg_gen_afl_call0(&afl_persistent_loop); \ + \ + } else if (afl_persistent_ret_addr && s->pc == afl_persistent_ret_addr) { \ + \ + gen_goto_tb(s, 0, afl_persistent_addr); \ + \ + } \ + \ + } + diff --git a/qemu_mode/patches/arm-translate-a64.diff b/qemu_mode/patches/arm-translate-a64.diff new file mode 100644 index 00000000..83856217 --- /dev/null +++ b/qemu_mode/patches/arm-translate-a64.diff @@ -0,0 +1,64 @@ +diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c +index fd36425..992bf17 100644 +--- a/target/arm/translate-a64.c ++++ b/target/arm/translate-a64.c +@@ -39,6 +39,8 @@ + #include "translate-a64.h" + #include "qemu/atomic128.h" + ++#include "../patches/afl-qemu-cpu-translate-inl.h" ++ + static TCGv_i64 cpu_X[32]; + static TCGv_i64 cpu_pc; + +@@ -3365,6 +3367,12 @@ static void disas_add_sub_imm(DisasContext *s, uint32_t insn) + return; + } + ++ if (rd == 31 && sub_op) { // cmp xX, imm ++ TCGv_i64 tcg_imm = tcg_const_i64(imm); ++ afl_gen_compcov(s->pc, tcg_rn, tcg_imm, is_64bit ? MO_64 : MO_32, 1); ++ tcg_temp_free_i64(tcg_imm); ++ } ++ + tcg_result = tcg_temp_new_i64(); + if (!setflags) { + if (sub_op) { +@@ -3972,6 +3980,9 @@ static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn) + + tcg_rm = read_cpu_reg(s, rm, sf); + ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3); ++ ++ if (rd == 31 && sub_op) // cmp xX, xY ++ afl_gen_compcov(s->pc, tcg_rn, tcg_rm, sf ? MO_64 : MO_32, 0); + + tcg_result = tcg_temp_new_i64(); + +@@ -4037,6 +4048,9 @@ static void disas_add_sub_reg(DisasContext *s, uint32_t insn) + + shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6); + ++ if (rd == 31 && sub_op) // cmp xX, xY ++ afl_gen_compcov(s->pc, tcg_rn, tcg_rm, sf ? MO_64 : MO_32, 0); ++ + tcg_result = tcg_temp_new_i64(); + + if (!setflags) { +@@ -4246,6 +4260,8 @@ static void disas_cc(DisasContext *s, uint32_t insn) + tcg_y = cpu_reg(s, y); + } + tcg_rn = cpu_reg(s, rn); ++ ++ afl_gen_compcov(s->pc, tcg_rn, tcg_y, sf ? MO_64 : MO_32, is_imm); + + /* Set the flags for the new comparison. */ + tcg_tmp = tcg_temp_new_i64(); +@@ -13317,6 +13333,8 @@ static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn) + static void disas_a64_insn(CPUARMState *env, DisasContext *s) + { + uint32_t insn; ++ ++ AFL_QEMU_TARGET_ARM64_SNIPPET + + insn = arm_ldl_code(env, s->pc, s->sctlr_b); + s->insn = insn; diff --git a/qemu_mode/patches/arm-translate.diff b/qemu_mode/patches/arm-translate.diff index 58b4a873..daa5d43b 100644 --- a/qemu_mode/patches/arm-translate.diff +++ b/qemu_mode/patches/arm-translate.diff @@ -1,5 +1,5 @@ diff --git a/target/arm/translate.c b/target/arm/translate.c -index 7c4675ff..0f0928b6 100644 +index 7c4675f..e3d999a 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -59,6 +59,8 @@ @@ -132,3 +132,21 @@ index 7c4675ff..0f0928b6 100644 rd = 16; break; case 0xb: /* cmn */ +@@ -13233,6 +13247,8 @@ static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) + return; + } + ++ AFL_QEMU_TARGET_ARM_SNIPPET ++ + insn = arm_ldl_code(env, dc->pc, dc->sctlr_b); + dc->insn = insn; + dc->pc += 4; +@@ -13301,6 +13317,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) + return; + } + ++ AFL_QEMU_TARGET_ARM_SNIPPET ++ + insn = arm_lduw_code(env, dc->pc, dc->sctlr_b); + is_16bit = thumb_insn_is_16bit(dc, insn); + dc->pc += 2; diff --git a/qemu_mode/patches/configure.diff b/qemu_mode/patches/configure.diff new file mode 100644 index 00000000..acb96294 --- /dev/null +++ b/qemu_mode/patches/configure.diff @@ -0,0 +1,26 @@ +diff --git a/configure b/configure +index 1c9f609..3edc9a7 100755 +--- a/configure ++++ b/configure +@@ -4603,6 +4603,21 @@ if test "$darwin" != "yes" -a "$mingw32" != "yes" -a "$solaris" != yes -a \ + libs_softmmu="-lutil $libs_softmmu" + fi + ++########################################## ++cat > $TMPC << EOF ++#include <dlfcn.h> ++#include <stdlib.h> ++int main(int argc, char **argv) { return dlopen("libc.so", RTLD_NOW) != NULL; } ++EOF ++if compile_prog "" "" ; then ++ : ++elif compile_prog "" "-ldl" ; then ++ LIBS="-ldl $LIBS" ++ libs_qga="-ldl $libs_qga" ++else ++ error_exit "libdl check failed" ++fi ++ + ########################################## + # spice probe + if test "$spice" != "no" ; then diff --git a/qemu_mode/patches/i386-translate.diff b/qemu_mode/patches/i386-translate.diff index 00337e2c..8ccd6f4e 100644 --- a/qemu_mode/patches/i386-translate.diff +++ b/qemu_mode/patches/i386-translate.diff @@ -35,7 +35,7 @@ index 0dd5fbe4..a23da128 100644 rex_w = -1; rex_r = 0; -+ AFL_QEMU_TARGET_i386_SNIPPET ++ AFL_QEMU_TARGET_I386_SNIPPET + next_byte: b = x86_ldub_code(env, s); |