static dr_emit_flags_t bb_event(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { fuzz_pass_context_t *fp; pass_target_t *live; if (for_trace || translating) return DR_EMIT_DEFAULT; /* It is ok to be racy, so hold no locks for updating. */ /* update global num_bbs */ num_total_bbs++; /* update num_bbs for each live target */ fp = (fuzz_pass_context_t *) drmgr_get_tls_field(drcontext, tls_idx_fuzzer); live = fp->live_targets; if (live != NULL) { /* XXX: the function entry basic block is not counted because the live target * is only added on its first execution after bb_event. */ live->target->num_bbs++; DRFUZZ_LOG(3, "basic block "UINT64_FORMAT_STRING" @"PFX" during fuzzing "PFX"\n", live->target->num_bbs, tag, live->target->func_pc); } return DR_EMIT_DEFAULT; }
static void post_fuzz_handler(void *wrapcxt, void *user_data) { fuzz_pass_context_t *fp = (fuzz_pass_context_t *) user_data; pass_target_t *live = fp->live_targets; bool repeat = live->target->post_fuzz_cb(fp, (generic_func_t) live->target->func_pc); DRFUZZ_LOG(3, "post_fuzz() for target "PFX" (%s)\n", live->target->func_pc, repeat ? "repeat" : "stop"); if (repeat) { dr_mcontext_t *mc = drwrap_get_mcontext(wrapcxt); IF_DEBUG(drext_status_t redirect_status;); /* restore the original xsp before repeating */ DRFUZZ_LOG(4, "fuzz target "PFX": restoring xsp to "PFX"\n", live->target->func_pc, live->xsp); mc->xsp = live->xsp; mc->pc = live->target->func_pc; IF_DEBUG(redirect_status =) drwrap_redirect_execution(wrapcxt); DRFUZZ_LOG(4, "fuzz target "PFX" requesting redirect to self entry; result: %d\n", live->target->func_pc, live->target->func_pc, redirect_status); } else { /* the current target is finished, so pop from live stack and cache it */
static void pre_fuzz_handler(void *wrapcxt, INOUT void **user_data) { void *dcontext = drwrap_get_drcontext(wrapcxt); app_pc target_to_fuzz = drwrap_get_func(wrapcxt); fuzz_target_t *target = hashtable_lookup(&fuzz_target_htable, target_to_fuzz); fuzz_pass_context_t *fp = (fuzz_pass_context_t *) drmgr_get_tls_field(dcontext, tls_idx_fuzzer); bool is_target_entry = false; pass_target_t *live = NULL; dr_mcontext_t *mc; uint i; ASSERT(target != NULL, "pre_fuzz must be associated with a fuzz target"); DRFUZZ_LOG(3, "pre_fuzz() for target "PFX" with %d args\n", target_to_fuzz, target->arg_count); /* XXX i#1734: this heuristic may be incorrect when a handled fault occurs during * the very last iteration of the last fuzz pass on any thread. */ clear_thread_state(fp); /* Stop the target iterator that was captured at the last critical fault, because * the fact that we are in pre-fuzz implies the fault was handled and doesn't matter. */ if (fp->thread_state->targets != NULL) drfuzz_target_iterator_stop(fp->thread_state->targets); /* XXX: assumes the fuzz target is never called recursively */ if (fp->live_targets != NULL && fp->live_targets->target->func_pc == target_to_fuzz) { live = fp->live_targets; /* this is a repetition of the last live target */ } else { is_target_entry = true; /* this is a new invocation of a target */ live = activate_cached_target(fp, target_to_fuzz); /* check the cache */ if (live == NULL) live = create_pass_target(dcontext, wrapcxt); live->next = fp->live_targets; /* push to live stack */ fp->live_targets = live; } /* required by dr_redirect_execution() (avoids having to merge the mcontext) */ mc = drwrap_get_mcontext_ex(wrapcxt, DR_MC_ALL); /* XXX: can we relax this? */ if (is_target_entry) { live->xsp = mc->xsp; #ifdef X86 live->unclobber.retaddr_loc = (reg_t *) mc->xsp; /* see retaddr_unclobber_t */ #endif live->unclobber.retaddr = (reg_t) drwrap_get_retaddr(wrapcxt); DRFUZZ_LOG(4, "fuzz target "PFX": saving stack pointer "PFX"\n", target_to_fuzz, mc->xsp); for (i = 0; i < target->arg_count; i++) { /* store the original arg values */ live->original_args[i] = (reg_t) drwrap_get_arg(wrapcxt, i); /* copy original args to current args for the first iteration of the fuzz */ live->current_args[i] = live->original_args[i]; DRFUZZ_LOG(4, "fuzz target "PFX": saving original arg #%d: "PFX"\n", target_to_fuzz, i, live->original_args[i]); } } /* restore the original arg values before calling the client */ for (i = 0; i < target->arg_count; i++) { DRFUZZ_LOG(4, "fuzz target "PFX": restoring original arg #%d: "PFX"\n", target_to_fuzz, i, live->original_args[i]); drwrap_set_arg(wrapcxt, i, (void *) live->original_args[i]); } #ifdef ARM mc->lr = live->unclobber.retaddr; /* restore retaddr to link register */ #else /* X86 */ *live->unclobber.retaddr_loc = live->unclobber.retaddr; /* restore retaddr to stack */ #endif target->pre_fuzz_cb(fp, (generic_func_t) target_to_fuzz, mc); drwrap_set_mcontext(wrapcxt); for (i = 0; i < target->arg_count; i++) live->current_args[i] = (reg_t) drwrap_get_arg(wrapcxt, i); *user_data = fp; }