static void wrap_post(void *wrapcxt, void *user_data) { bool ok; CHECK(wrapcxt != NULL, "invalid arg"); if (drwrap_get_func(wrapcxt) == addr_level0) { dr_fprintf(STDERR, " <post-level0>\n"); /* not preserved for no-frills */ CHECK(load_count == 2 || user_data == (void *)99, "user_data not preserved"); CHECK(drwrap_get_retval(wrapcxt) == (void *) 42, "get_retval error"); } else if (drwrap_get_func(wrapcxt) == addr_level1) { dr_fprintf(STDERR, " <post-level1>\n"); ok = drwrap_set_retval(wrapcxt, (void *) -4); CHECK(ok, "set_retval error"); } else if (drwrap_get_func(wrapcxt) == addr_tailcall) { dr_fprintf(STDERR, " <post-makes_tailcall>\n"); } else if (drwrap_get_func(wrapcxt) == addr_level2) { dr_fprintf(STDERR, " <post-level2>\n"); } else if (drwrap_get_func(wrapcxt) == addr_skipme) { CHECK(false, "should have skipped!"); } else if (drwrap_get_func(wrapcxt) == addr_repeat) { dr_fprintf(STDERR, " <post-repeat#%d>\n", repeated ? 2 : 1); if (!repeated) { dr_mcontext_t *mc = drwrap_get_mcontext(wrapcxt); mc->pc = addr_repeat; mc->xsp = repeat_xsp; #ifdef ARM mc->lr = repeat_link; #endif CHECK(drwrap_redirect_execution(wrapcxt) == DREXT_SUCCESS, "redirect rejected"); CHECK(drwrap_redirect_execution(wrapcxt) != DREXT_SUCCESS, "allowed duplicate redirect"); } repeated = !repeated; } else if (drwrap_get_func(wrapcxt) == addr_postonly) { dr_fprintf(STDERR, " <post-postonly>\n"); drwrap_unwrap(addr_skipme, wrap_pre, wrap_post); CHECK(!drwrap_is_wrapped(addr_skipme, wrap_pre, wrap_post), "drwrap_is_wrapped query failed"); drwrap_unwrap(addr_postonly, NULL, wrap_post); CHECK(!drwrap_is_wrapped(addr_postonly, NULL, wrap_post), "drwrap_is_wrapped query failed"); drwrap_unwrap(addr_runlots, NULL, wrap_post); CHECK(!drwrap_is_wrapped(addr_runlots, NULL, wrap_post), "drwrap_is_wrapped query failed"); } else if (drwrap_get_func(wrapcxt) == addr_runlots) { dr_fprintf(STDERR, " <post-runlots>\n"); } else CHECK(false, "invalid wrap"); }
static void wrap_unwindtest_pre(void *wrapcxt, OUT void **user_data) { if (drwrap_get_func(wrapcxt) != addr_longdone) { void *drcontext = dr_get_current_drcontext(); ptr_uint_t val = (ptr_uint_t) drmgr_get_tls_field(drcontext, tls_idx); dr_fprintf(STDERR, " <pre-long%d>\n", val); /* increment per level of regular calls on way up */ val++; drmgr_set_tls_field(drcontext, tls_idx, (void *)val); } }
/** Wrapper pre-callback. */ static void wrapperPre( void* ctx, void** data ) { dr_mutex_lock( outMutex ); uint64 currentTimeMillis = dr_get_milliseconds(); if( currentTimeMillis > nextTimestampMillis ) { dr_fprintf( outFile, "T 0x%.16llx\n", currentTimeMillis ); nextTimestampMillis = currentTimeMillis + timestampIntervalMillis; } dr_fprintf( outFile, "X %p %p\n", (void*)drwrap_get_func( ctx ), drwrap_get_arg( ctx, 0 ) ); dr_mutex_unlock( outMutex ); }
static void wrap_unwindtest_post(void *wrapcxt, void *user_data) { void *drcontext = dr_get_current_drcontext(); ptr_uint_t val = (ptr_uint_t) drmgr_get_tls_field(drcontext, tls_idx); if (drwrap_get_func(wrapcxt) == addr_longdone) { /* ensure our post-calls were all called and we got back to 0 */ CHECK(val == 0, "post-calls were bypassed"); } else { /* decrement on way down */ val--; dr_fprintf(STDERR, " <post-long%d%s>\n", val, wrapcxt == NULL ? " abnormal" : ""); drmgr_set_tls_field(drcontext, tls_idx, (void *)val); } }
static void wrap_pre(void *wrapcxt, OUT void **user_data) { bool ok; CHECK(wrapcxt != NULL && user_data != NULL, "invalid arg"); if (drwrap_get_func(wrapcxt) == addr_skip_flags) { CHECK(drwrap_get_arg(wrapcxt, 0) == (void *) 1, "get_arg wrong"); CHECK(drwrap_get_arg(wrapcxt, 1) == (void *) 2, "get_arg wrong"); } else if (drwrap_get_func(wrapcxt) == addr_level0) { dr_fprintf(STDERR, " <pre-level0>\n"); CHECK(drwrap_get_arg(wrapcxt, 0) == (void *) 37, "get_arg wrong"); ok = drwrap_set_arg(wrapcxt, 0, (void *) 42); CHECK(ok, "set_arg error"); *user_data = (void *) 99; } else if (drwrap_get_func(wrapcxt) == addr_level1) { dr_fprintf(STDERR, " <pre-level1>\n"); ok = drwrap_set_arg(wrapcxt, 1, (void *) 1111); CHECK(ok, "set_arg error"); } else if (drwrap_get_func(wrapcxt) == addr_tailcall) { dr_fprintf(STDERR, " <pre-makes_tailcall>\n"); } else if (drwrap_get_func(wrapcxt) == addr_level2) { dr_fprintf(STDERR, " <pre-level2>\n"); } else if (drwrap_get_func(wrapcxt) == addr_skipme) { dr_fprintf(STDERR, " <pre-skipme>\n"); drwrap_skip_call(wrapcxt, (void *) 7, 0); } else if (drwrap_get_func(wrapcxt) == addr_repeat) { dr_mcontext_t *mc = drwrap_get_mcontext(wrapcxt); dr_fprintf(STDERR, " <pre-repeat#%d>\n", repeated ? 2 : 1); repeat_xsp = mc->xsp; #ifdef ARM repeat_link = mc->lr; #endif if (repeated) /* test changing the arg value on the second pass */ drwrap_set_arg(wrapcxt, 0, (void *)2); CHECK(drwrap_redirect_execution(NULL) != DREXT_SUCCESS, "allowed redirect with NULL wrapcxt"); CHECK(drwrap_redirect_execution(wrapcxt) != DREXT_SUCCESS, "allowed redirect in pre-wrap"); } else if (drwrap_get_func(wrapcxt) == addr_preonly) { dr_fprintf(STDERR, " <pre-preonly>\n"); } else CHECK(false, "invalid wrap"); }
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; }