static void module_unload_event(void *drcontext, const module_data_t *mod) { if (strstr(dr_module_preferred_name(mod), "client.drwrap-test.appdll.") != NULL) { bool ok; ok = drwrap_replace(addr_replace, NULL, true); CHECK(ok, "un-replace failed"); ok = drwrap_replace_native(addr_replace2, NULL, true, 0, NULL, true); CHECK(ok, "un-replace_native failed"); ok = drwrap_replace_native(addr_replace_callsite, NULL, false, 0, NULL, true); CHECK(ok, "un-replace_native failed"); unwrap_addr(addr_skip_flags, "skip_flags", mod, true, false); unwrap_addr(addr_level0, "level0", mod, true, true); unwrap_addr(addr_level1, "level1", mod, true, true); unwrap_addr(addr_level2, "level2", mod, true, true); unwrap_addr(addr_tailcall, "makes_tailcall", mod, true, true); unwrap_addr(addr_preonly, "preonly", mod, true, false); /* skipme, postonly, and runlots were already unwrapped */ /* test longjmp */ unwrap_unwindtest_addr(addr_long0, "long0", mod); unwrap_unwindtest_addr(addr_long1, "long1", mod); unwrap_unwindtest_addr(addr_long2, "long2", mod); unwrap_unwindtest_addr(addr_long3, "long3", mod); unwrap_unwindtest_addr(addr_longdone, "longdone", mod); drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_uint_t)0); #ifdef WINDOWS /* test SEH */ if (load_count == 1) { ok = drwrap_unwrap(addr_long0, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post); CHECK(ok, "unwrap failed"); ok = drwrap_unwrap(addr_long1, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post); CHECK(ok, "unwrap failed"); ok = drwrap_unwrap(addr_long2, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post); CHECK(ok, "unwrap failed"); ok = drwrap_unwrap(addr_long3, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post); CHECK(ok, "unwrap failed"); ok = drwrap_unwrap(addr_longdone, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post); } CHECK(ok, "unwrap failed"); #endif } }
void replace_init(void) { if (options.replace_libc) { app_pc addr; int i; char *s; /* replace_module_load will be called for each module to populate the hashtable */ ASSERT(PAGE_START(get_function_entry((app_pc)replace_memset)) == PAGE_START(get_function_entry((app_pc)replace_memmove)), "replace_ routines taking up more than one page"); ASSERT(sizeof(int) >= sizeof(wchar_t), "wchar_t replacement functions assume wchar_t is not larger than int"); replace_routine_start = (app_pc) PAGE_START(get_function_entry((app_pc)replace_memset)); /* PR 485412: we support passing in addresses of libc routines to * be replaced if statically included in the executable and if * we have no symbols available */ s = options.libc_addrs; i = 0; while (s != NULL) { if (sscanf(s, PIFX, (ptr_uint_t *)&addr) == 1 || /* we save option space by having no 0x prefix but assuming hex */ sscanf(s, PIFMT, (ptr_uint_t *)&addr) == 1) { LOG(2, "replacing %s @"PFX" in executable from options\n", replace_routine_name[i], addr); if (!drwrap_replace((app_pc)addr, (app_pc)replace_routine_addr[i], false)) ASSERT(false, "failed to replace"); } s = strchr(s, ','); if (s != NULL) s++; i++; } #ifdef USE_DRSYMS hashtable_init(&replace_name_table, REPLACE_NAME_TABLE_HASH_BITS, HASH_STRING, false/*!strdup*/); for (i=0; i<REPLACE_NUM; i++) { hashtable_add(&replace_name_table, (void *) replace_routine_name[i], (void *)(ptr_int_t)(i+1)/*since 0 is "not found"*/); } #endif } }
static void module_load_event(void *drcontext, const module_data_t *mod, bool loaded) { if (strstr(dr_module_preferred_name(mod), "client.drwrap-test.appdll.") != NULL) { bool ok; instr_t inst; app_pc init_pc, pc, next_pc; load_count++; if (load_count == 2) { /* test no-frills */ drwrap_set_global_flags(DRWRAP_NO_FRILLS); } addr_replace = (app_pc) dr_get_proc_address(mod->handle, "replaceme"); CHECK(addr_replace != NULL, "cannot find lib export"); ok = drwrap_replace(addr_replace, (app_pc) replacewith, false); CHECK(ok, "replace failed"); addr_replace2 = (app_pc) dr_get_proc_address(mod->handle, "replaceme2"); CHECK(addr_replace2 != NULL, "cannot find lib export"); ok = drwrap_replace_native(addr_replace2, (app_pc) replacewith2, true/*at entry*/, 0, (void *)(ptr_int_t)DRWRAP_NATIVE_PARAM, false); CHECK(ok, "replace_native failed"); init_pc = (app_pc) dr_get_proc_address(mod->handle, "replace_callsite"); CHECK(init_pc != NULL, "cannot find lib export"); /* Find callsite: we assume we'll linearly hit a ret. We take final call * to skip any PIC call. */ instr_init(drcontext, &inst); pc = init_pc; do { instr_reset(drcontext, &inst); next_pc = decode(drcontext, pc, &inst); if (!instr_valid(&inst)) break; /* if initial jmp, follow it to handle ILT-indirection */ if (pc == init_pc && instr_is_ubr(&inst)) next_pc = opnd_get_pc(instr_get_target(&inst)); else if (instr_is_call(&inst)) addr_replace_callsite = pc; pc = next_pc; } while (instr_valid(&inst) && !instr_is_return(&inst)); CHECK(addr_replace_callsite != NULL, "cannot find lib export"); ok = drwrap_replace_native(addr_replace_callsite, (app_pc) replace_callsite, false/*!at entry*/, 0, (void *)(ptr_int_t)DRWRAP_NATIVE_PARAM, false); CHECK(ok, "replace_native failed"); instr_free(drcontext, &inst); wrap_addr(&addr_level0, "level0", mod, true, true); wrap_addr(&addr_level1, "level1", mod, true, true); wrap_addr(&addr_level2, "level2", mod, true, true); wrap_addr(&addr_tailcall, "makes_tailcall", mod, true, true); wrap_addr(&addr_skipme, "skipme", mod, true, true); wrap_addr(&addr_repeat, "repeatme", mod, true, true); wrap_addr(&addr_preonly, "preonly", mod, true, false); wrap_addr(&addr_postonly, "postonly", mod, false, true); wrap_addr(&addr_runlots, "runlots", mod, false, true); /* test longjmp */ wrap_unwindtest_addr(&addr_long0, "long0", mod); wrap_unwindtest_addr(&addr_long1, "long1", mod); wrap_unwindtest_addr(&addr_long2, "long2", mod); wrap_unwindtest_addr(&addr_long3, "long3", mod); wrap_unwindtest_addr(&addr_longdone, "longdone", mod); drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_uint_t)0); #ifdef WINDOWS /* test SEH */ /* we can't do this test for no-frills b/c only one wrap per addr */ if (load_count == 1) { ok = drwrap_wrap_ex(addr_long0, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_long1, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_long2, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_long3, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); ok = drwrap_wrap_ex(addr_longdone, wrap_unwindtest_seh_pre, wrap_unwindtest_seh_post, NULL, DRWRAP_UNWIND_ON_EXCEPTION); CHECK(ok, "wrap failed"); } #endif /* test leaner wrapping */ if (load_count == 2) drwrap_set_global_flags(DRWRAP_NO_FRILLS | DRWRAP_FAST_CLEANCALLS); wrap_addr(&addr_skip_flags, "skip_flags", mod, true, false); } }