void symcache_init(const char *symcache_dir_in, size_t modsize_cache_threshold) { 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(); } } } }
static void exit_event(void) { dr_fprintf(STDERR, "Aborting in client exit event\n"); /* we want to also test end-to-end w/ core dump being generated but * that's hard to do in a test suite so we abort here: but that can * mask errors. */ dr_abort(); }
void drmemory_abort(void) { if (op_pause_at_assert) { char buf[64]; /* very useful to have the pid */ dr_snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), "Dr. Memory is paused at an assert in pid=%d", dr_get_process_id()); wait_for_user(buf); } dr_abort(); }
static void my_abort(ptr_uint_t arg0, ptr_int_t arg1, ptr_int_t arg2) { ptr_uint_t *p0 = &arg0; ptr_int_t *p1 = &arg1; ptr_int_t *p2 = &arg2; if (*p0 != global_var || *p1 != -1 || *p2 != 1) dr_fprintf(STDERR, "Error on push_imm\n"); if (var0 != *p0 || var1 != *p1 || var2 != *p2) dr_fprintf(STDERR, "Error on mov_imm\n"); dr_fprintf(STDERR, "aborting now\n"); dr_abort(); }
DR_EXPORT void dr_init(client_id_t id) { dr_set_client_name("DynamoRIO Sample Client 'MF_moduledb'", "http://dynamorio.org/issues"); VDISPLAY_FUNC(NAME" initializing."); /* register the events we wish to handle */ dr_register_security_event(event_security_violation); dr_register_nudge_event(event_nudge, id); dr_register_exit_event(event_exit); /* read the client options */ table_def_file_name = dr_get_options(id); if (table_def_file_name == NULL || table_def_file_name[0] == '\0') { DISPLAY_FUNC(NAME" requires the table name as parameter\n"); dr_abort(); } /* initialize structures */ table_lock = dr_mutex_create(); read_table(); }
/* prints out the operands / populates the operands in the instrace mode */ static void output_populator_printer(void * drcontext, opnd_t opnd, instr_t * instr, uint64 addr, uint mem_type, operand_t * output){ int value; float float_value; uint width; int i; per_thread_t * data = drmgr_get_tls_field(drcontext,tls_index); if(opnd_is_reg(opnd)){ value = opnd_get_reg(opnd); if (value != DR_REG_NULL){ width = opnd_size_in_bytes(reg_get_size(value)); } else{ width = 0; } #ifdef READABLE_TRACE dr_fprintf(data->outfile,",%u,%u,%u",REG_TYPE, width, value); #else output->type = REG_TYPE; output->width = width; output->value = value; #endif } else if(opnd_is_immed(opnd)){ //DR_ASSERT(opnd_is_immed_float(opnd) == false); if(opnd_is_immed_float(opnd)){ width = opnd_size_in_bytes(opnd_get_size(opnd)); if (instr_get_opcode(instr) == OP_fld1){ dr_fprintf(data->outfile, ",%u,%u,1", IMM_FLOAT_TYPE, width); } else if (instr_get_opcode(instr) == OP_fldz){ dr_fprintf(data->outfile, ",%u,%u,0", IMM_FLOAT_TYPE, width); } else{ dr_messagebox("immediate float unknown\n"); dr_abort(); } //float_value = opnd_get_immed_float(opnd); #ifdef READABLE_TRACE //dr_fprintf(data->outfile,",%u,%u,%.4f",IMM_FLOAT_TYPE,width,float_value); #else output->type = IMM_FLOAT_TYPE; output->width = width; output->float_value = float_value; #endif } if(opnd_is_immed_int(opnd)){ width = opnd_size_in_bytes(opnd_get_size(opnd)); value = opnd_get_immed_int(opnd); #ifdef READABLE_TRACE dr_fprintf(data->outfile,",%u,%u,%d",IMM_INT_TYPE,width,value); #else output->type = IMM_INT_TYPE; output->width = width; output->value = value; #endif } } else if(opnd_is_memory_reference(opnd)){ width = drutil_opnd_mem_size_in_bytes(opnd,instr); #ifdef READABLE_TRACE dr_fprintf(data->outfile, ",%u,%u,%llu",mem_type,width,addr); #else output->type = mem_type; output->width = width; output->float_value = addr; #endif } }
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; }
/* If an entry already exists and is 0, replaces it; else adds a new * offset for that symbol. * * If symtable is visible outside of this thread, the caller must hold symcache_lock. */ static bool symcache_symbol_add(const char *modname, hashtable_t *symtable, const char *symbol, size_t offs) { offset_list_t *olist; offset_entry_t *e; olist = (offset_list_t *) hashtable_lookup(symtable, (void *)symbol); if (olist != NULL) { if (olist->num == 1 && olist->list->offs == 0) { /* replace a single 0 entry */ if (olist->table != NULL) { ASSERT(olist->num >= OFFSET_LIST_MIN_TABLE, "table should be NULL"); hashtable_remove(olist->table, (void *)(olist->list->offs + 1)); hashtable_add(olist->table, (void *)(offs + 1), (void *)(offs + 1)); } olist->list->offs = offs; return true; } else if (olist->num == 1 && offs == 0) { /* XXX i#1465: temporary fatal error sanity check as we try to diagnose * our symbol cache errors. */ NOTIFY_ERROR("SYMCACHE ERROR: appending 0 to non-0 for %s!%s"NL, modname, symbol); dr_abort(); /* make sure we see this on bots */ } if (olist->table != NULL) { if (hashtable_lookup(olist->table, (void *)(offs + 1)) != NULL) { LOG(2, "%s: ignoring dup entry %s\n", __FUNCTION__, symbol); return false; } } else { for (e = olist->list; e != NULL; e = e->next) { if (e->offs == offs) { LOG(2, "%s: ignoring dup entry %s\n", __FUNCTION__, symbol); return false; } } } } else { olist = (offset_list_t *) global_alloc(sizeof(*olist), HEAPSTAT_HASHTABLE); olist->num = 0; olist->list = NULL; olist->list_last = NULL; olist->table = NULL; } LOG(2, "%s: %s \"%s\" @ "PIFX"\n", __FUNCTION__, modname, symbol, offs); /* we could verify by an addr lookup but we still need consistency info * in the file for the negative entries so we don't bother */ e = (offset_entry_t *) global_alloc(sizeof(*e), HEAPSTAT_HASHTABLE); e->offs = offs; e->next = NULL; /* append to avoid affecting iteration */ if (olist->list_last == NULL) { ASSERT(olist->list == NULL, "last not set"); olist->list = e; olist->list_last = e; } else { olist->list_last->next = e; olist->list_last = e; } olist->num++; if (olist->num >= OFFSET_LIST_MIN_TABLE) { if (olist->table == NULL) { /* enough entries that a table is worthwhile */ olist->table = (hashtable_t *) global_alloc(sizeof(*olist->table), HEAPSTAT_HASHTABLE); hashtable_init(olist->table, SYMCACHE_OLIST_TABLE_HASH_BITS, HASH_INTPTR, false/*strdup*/); for (e = olist->list; e != NULL; e = e->next) hashtable_add(olist->table, (void *)(e->offs + 1), (void *)(e->offs + 1)); } else hashtable_add(olist->table, (void *)(offs + 1), (void *)(offs + 1)); } hashtable_add(symtable, (void *)symbol, (void *)olist); /* clear any cached values */ olist->iter_idx = 0; olist->iter_entry = NULL; return true; }