static dr_signal_action_t signal_event_redirect(void *dcontext, dr_siginfo_t *info) { if (info->sig == SIGSEGV) { app_pc addr; module_data_t *data = dr_lookup_module_by_name("client."EVENTS); dr_fprintf(STDERR, "signal event redirect\n"); if (data == NULL) { dr_fprintf(STDERR, "couldn't find client."EVENTS" module\n"); return DR_SIGNAL_DELIVER; } addr = (app_pc)dr_get_proc_address(data->handle, "redirect"); dr_free_module_data(data); if (addr == NULL) { dr_fprintf(STDERR, "Couldn't find function redirect in client."EVENTS"\n"); return DR_SIGNAL_DELIVER; } #ifdef X64 /* align properly in case redirect function relies on conventions (i#384) */ info->mcontext->xsp = ALIGN_BACKWARD(info->mcontext->xsp, 16) - sizeof(void*); #endif info->mcontext->pc = addr; return DR_SIGNAL_REDIRECT; } return DR_SIGNAL_DELIVER; }
static bool exception_event_redirect(void *dcontext, dr_exception_t *excpt) { app_pc addr; dr_mcontext_t mcontext = {sizeof(mcontext),DR_MC_ALL,}; module_data_t *data = dr_lookup_module_by_name("client."EVENTS".exe"); dr_fprintf(STDERR, "exception event redirect\n"); if (data == NULL) { dr_fprintf(STDERR, "couldn't find "EVENTS".exe module\n"); return true; } addr = (app_pc)dr_get_proc_address(data->handle, "redirect"); dr_free_module_data(data); mcontext = *excpt->mcontext; mcontext.pc = addr; if (addr == NULL) { dr_fprintf(STDERR, "Couldn't find function redirect in "EVENTS".exe\n"); return true; } #ifdef X64 /* align properly in case redirect function relies on conventions (i#419) */ mcontext.xsp = ALIGN_BACKWARD(mcontext.xsp, 16) - sizeof(void*); #endif dr_redirect_execution(&mcontext); dr_fprintf(STDERR, "should not be reached, dr_redirect_execution() should not return\n"); return true; }
static int get_sysnum(const char *wrapper) { byte *entry; module_data_t *data = dr_lookup_module_by_name("ntdll.dll"); ASSERT(data != NULL); entry = (byte *) dr_get_proc_address(data->handle, wrapper); dr_free_module_data(data); if (entry == NULL) return -1; return drmgr_decode_sysnum_from_wrapper(entry); }
app_pc get_ntdll_base(void) { static app_pc ntdll_base; /* cached value */ if (ntdll_base == NULL) { module_data_t *data = dr_lookup_module_by_name("ntdll.dll"); ASSERT(data != NULL, "cannot find ntdll.dll"); ntdll_base = data->start; dr_free_module_data(data); ASSERT(ntdll_base != NULL, "internal error finding ntdll.dll base"); } return ntdll_base; }
static int get_write_sysnum(void) { #ifdef LINUX return SYS_write; #else byte *entry; module_data_t *data = dr_lookup_module_by_name("ntdll.dll"); DR_ASSERT(data != NULL); entry = (byte *) dr_get_proc_address(data->handle, "NtWriteFile"); DR_ASSERT(entry != NULL); dr_free_module_data(data); return drmgr_decode_sysnum_from_wrapper(entry); #endif }
DR_EXPORT void dr_init(client_id_t id) { module_data_t *data; dr_fprintf(STDERR, "thank you for testing the client interface\n"); dr_register_bb_event(bb_event); data = dr_lookup_module_by_name("kernel32.dll"); if (data != NULL) { exit_proc_addr = (void *)dr_get_proc_address(data->handle, "ExitProcess"); if (exit_proc_addr == NULL) dr_fprintf(STDERR, "ERROR: unable to find kernel32!ExitProcess\n"); dr_free_module_data(data); } else { dr_fprintf(STDERR, "ERROR: unable to find ntdll.dll\n"); } }
static bool drmgr_cls_init(void) { /* For callback init we watch for KiUserCallbackDispatcher. * For callback exit we watch for NtCallbackReturn or int 0x2b. */ static int cls_initialized; /* 0=not tried; >0=success; <0=failure */ module_data_t *data; module_handle_t ntdll_lib; app_pc addr_cbret; drmgr_priority_t priority = {sizeof(priority), "drmgr_cls", NULL, NULL, 0}; if (cls_initialized > 0) return true; else if (cls_initialized < 0) return false; cls_initialized = -1; if (!drmgr_register_bb_instrumentation_event(drmgr_event_bb_analysis, drmgr_event_bb_insert, &priority)) return false; dr_register_filter_syscall_event(drmgr_event_filter_syscall); data = dr_lookup_module_by_name("ntdll.dll"); if (data == NULL) { /* fatal error: something is really wrong w/ underlying DR */ return false; } ntdll_lib = data->handle; dr_free_module_data(data); addr_KiCallback = (app_pc) dr_get_proc_address(ntdll_lib, "KiUserCallbackDispatcher"); if (addr_KiCallback == NULL) return false; /* should not happen */ /* the wrapper is not good enough for two reasons: one, we want to swap * contexts at the last possible moment, not prior to executing a few * instrs; second, we'll miss hand-rolled syscalls */ addr_cbret = (app_pc) dr_get_proc_address(ntdll_lib, "NtCallbackReturn"); if (addr_cbret == NULL) return false; /* should not happen */ sysnum_NtCallbackReturn = drmgr_decode_sysnum_from_wrapper(addr_cbret); if (sysnum_NtCallbackReturn == -1) return false; /* should not happen */ cls_initialized = 1; return true; }
static int get_write_sysnum(void) { /* XXX: we could use the "drsyscall" Extension from the Dr. Memory Framework * (DRMF) to obtain the number of any system call from the name. */ #ifdef UNIX return SYS_write; #else byte *entry; module_data_t *data = dr_lookup_module_by_name("ntdll.dll"); DR_ASSERT(data != NULL); entry = (byte *) dr_get_proc_address(data->handle, "NtWriteFile"); DR_ASSERT(entry != NULL); dr_free_module_data(data); return drmgr_decode_sysnum_from_wrapper(entry); #endif }
DR_EXPORT void dr_init(client_id_t id) { /* Look up start_instrument() and stop_instrument() in the app. * These functions are markers that tell us when to start and stop * instrumenting. */ module_data_t *prog = dr_lookup_module_by_name("client.cbr4.exe"); ASSERT(prog != NULL); start_pc = (app_pc)dr_get_proc_address(prog->handle, "start_instrument"); stop_pc = (app_pc)dr_get_proc_address(prog->handle, "stop_instrument"); ASSERT(start_pc != NULL && stop_pc != NULL); dr_free_module_data(prog); table = new_table(); dr_register_bb_event(bb_event); dr_register_exit_event(dr_exit); }
static dr_signal_action_t signal_event_redirect(void *dcontext, dr_siginfo_t *info) { if (info->sig == SIGSEGV) { app_pc addr; module_data_t *data = dr_lookup_module_by_name("client.events"); dr_fprintf(STDERR, "signal event redirect\n"); if (data == NULL) { dr_fprintf(STDERR, "couldn't find client.events module\n"); return DR_SIGNAL_DELIVER; } addr = (app_pc)dr_get_proc_address(data->handle, "redirect"); dr_free_module_data(data); if (addr == NULL) { dr_fprintf(STDERR, "Couldn't find function redirect in client.events\n"); return DR_SIGNAL_DELIVER; } info->mcontext->pc = addr; return DR_SIGNAL_REDIRECT; } return DR_SIGNAL_DELIVER; }
DR_EXPORT drmf_status_t drsymcache_init(client_id_t client_id, const char *symcache_dir_in, size_t modsize_cache_threshold) { #ifdef WINDOWS module_data_t *mod; #endif drmf_status_t res; drmgr_priority_t pri_mod_load_cache = {sizeof(pri_mod_load_cache), DRMGR_PRIORITY_NAME_DRSYMCACHE, NULL, NULL, DRMGR_PRIORITY_MODLOAD_DRSYMCACHE_READ}; drmgr_priority_t pri_mod_unload_cache = {sizeof(pri_mod_unload_cache), DRMGR_PRIORITY_NAME_DRSYMCACHE, NULL, NULL, DRMGR_PRIORITY_MODUNLOAD_DRSYMCACHE}; drmgr_priority_t pri_mod_save_cache = {sizeof(pri_mod_save_cache), DRMGR_PRIORITY_NAME_DRSYMCACHE_SAVE, NULL, NULL, DRMGR_PRIORITY_MODLOAD_DRSYMCACHE_SAVE}; /* handle multiple sets of init/exit calls */ int count = dr_atomic_add32_return_sum(&symcache_init_count, 1); if (count > 1) return DRMF_WARNING_ALREADY_INITIALIZED; res = drmf_check_version(client_id); if (res != DRMF_SUCCESS) return res; drmgr_init(); drmgr_register_module_load_event_ex(symcache_module_load, &pri_mod_load_cache); drmgr_register_module_unload_event_ex(symcache_module_unload, &pri_mod_unload_cache); drmgr_register_module_load_event_ex(symcache_module_load_save, &pri_mod_save_cache); initialized = true; op_modsize_cache_threshold = modsize_cache_threshold; hashtable_init_ex(&symcache_table, SYMCACHE_MASTER_TABLE_HASH_BITS, IF_WINDOWS_ELSE(HASH_STRING_NOCASE, HASH_STRING), true/*strdup*/, false/*!synch*/, symcache_free_entry, NULL, NULL); symcache_lock = dr_mutex_create(); dr_snprintf(symcache_dir, BUFFER_SIZE_ELEMENTS(symcache_dir), "%s", symcache_dir_in); NULL_TERMINATE_BUFFER(symcache_dir); if (!dr_directory_exists(symcache_dir)) { if (!dr_create_dir(symcache_dir)) { /* check again in case of a race (i#616) */ if (!dr_directory_exists(symcache_dir)) { NOTIFY_ERROR("Unable to create symcache dir %s"NL, symcache_dir); ASSERT(false, "unable to create symcache dir"); dr_abort(); } } } #ifdef WINDOWS /* It's common for tools to query ntdll in their init routines so we add it * early here */ mod = dr_lookup_module_by_name("ntdll.dll"); if (mod != NULL) { symcache_module_load(dr_get_current_drcontext(), mod, true); dr_free_module_data(mod); } #endif return DRMF_SUCCESS; }