/* We transform string loops into regular loops so we can more easily * monitor every memory reference they make. */ static dr_emit_flags_t event_bb_app2app(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) { if (!drutil_expand_rep_string(drcontext, bb)) { DR_ASSERT(false); /* in release build, carry on: we'll just miss per-iter refs */ } drx_tail_pad_block(drcontext, bb); return DR_EMIT_DEFAULT; }
static void event_exit(void) { #ifdef SHOW_RESULTS /* Display the results! */ char msg[512]; int len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "Inlining results:\n" " Number of traces: %d\n" " Number of complete inlines: %d\n", num_traces, num_complete_inlines); DR_ASSERT(len > 0); msg[sizeof(msg)/sizeof(msg[0])-1] = '\0'; DISPLAY_STRING(msg); #endif hashtable_delete(&head_table); if (!drmgr_unregister_bb_instrumentation_event(event_analyze_bb)) DR_ASSERT(false); drmgr_exit(); }
app_pc table_alloc_bytes(umbra_info_t *info, int size) { app_pc ptr; DR_ASSERT(size >= 0 && (info->table.bytes_ptr + size) < (info->table.bytes_table + MAX_BYTES_TABLE_SIZE)); ptr = info->table.bytes_ptr; info->table.bytes_ptr += size; return ptr; }
static void event_exit(void) { if (!drmgr_unregister_thread_init_event(event_thread_init) || !drmgr_unregister_bb_insertion_event(event_app_instruction) || drreg_exit() != DRREG_SUCCESS) DR_ASSERT(false); drx_buf_free(buf); drmgr_exit(); drx_exit(); }
static void event_exit(void) { show_results(); if (!drmgr_unregister_cls_field(event_thread_context_init, event_thread_context_exit, tcls_idx) || !drmgr_unregister_pre_syscall_event(event_pre_syscall) || !drmgr_unregister_post_syscall_event(event_post_syscall)) DR_ASSERT(false && "failed to unregister"); drmgr_exit(); }
static void event_exit(void) { char msg[512]; int len; len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "Instrumentation results: %llu instructions executed\n", global_count); DR_ASSERT(len > 0); NULL_TERMINATE(msg); DISPLAY_STRING(msg); }
static void wrap_post(void *wrapcxt, void *user_data) { size_t sz = (size_t) user_data; /* test out-of-memory by having a random moderately-large alloc fail */ if (sz > 1024 && dr_get_random_value(1000) < 10) { bool ok = drwrap_set_retval(wrapcxt, NULL); DR_ASSERT(ok); dr_mutex_lock(max_lock); malloc_oom++; dr_mutex_unlock(max_lock); } }
file_t umbra_open_proc_log(process_id_t pid) { #ifdef LINUX_KERNEL return our_stdout; #else char name[128]; int len; file_t logfile; /* XXX: Windows need a absolute path */ name[0] = '\0'; len = dr_snprintf(name, sizeof(name)/sizeof(name[0]), "umbra.%s.%d.proc.log", dr_get_application_name(), pid); DR_ASSERT(len > 0); name[sizeof(name)/sizeof(name[0])-1] = '\0'; logfile = dr_open_file(name, DR_FILE_READ | DR_FILE_WRITE_APPEND); DR_ASSERT(logfile != INVALID_FILE); return logfile; #endif }
static void post_func_cb(void * wrapcxt, void ** user_data){ DEBUG_PRINT("funcwrap - post_func_cb\n"); per_thread_t * data = drmgr_get_tls_field(dr_get_current_drcontext(), tls_index); data->nesting--; //dr_unlink_flush_region(0, ~((ptr_uint_t)0)); DR_ASSERT(data->nesting >= 0); if (data->nesting == 0){ data->filter_func = false; } DEBUG_PRINT("funcwrap - post_func_cb done \n"); }
static void event_thread_init(void *drcontext) { file_t log; log = log_file_open(client_id, drcontext, NULL /* using client lib path */, "cbrtrace", #ifndef WINDOWS DR_FILE_CLOSE_ON_FORK | #endif DR_FILE_ALLOW_LARGE); DR_ASSERT(log != INVALID_FILE); dr_set_tls_field(drcontext, (void *)(ptr_uint_t)log); }
static void module_load_event(void *drcontext, const module_data_t *mod, bool loaded) { app_pc towrap = (app_pc)dr_get_proc_address(mod->handle, "SSL_write"); if (towrap != NULL) { bool ok = drwrap_wrap(towrap, wrap_pre_SSL_write, NULL); if (!ok) { dr_fprintf(STDERR, "Couldn’t wrap SSL_write\n"); DR_ASSERT(ok); } } towrap = (app_pc)dr_get_proc_address(mod->handle, "SSL_read"); if (towrap != NULL) { bool ok = drwrap_wrap(towrap, wrap_pre_SSL_read, wrap_post_SSL_read); if (!ok) { dr_fprintf(STDERR, "Couldn’t wrap SSL_read\n"); DR_ASSERT(ok); } } towrap = (app_pc)dr_get_proc_address(mod->handle, "gnutls_record_send"); if (towrap != NULL) { bool ok = drwrap_wrap(towrap, wrap_pre_SSL_write, NULL); if (!ok) { dr_fprintf(STDERR, "Couldn’t wrap gnutls_record_send\n"); DR_ASSERT(ok); } } towrap = (app_pc)dr_get_proc_address(mod->handle, "gnutls_record_recv"); if (towrap != NULL) { bool ok = drwrap_wrap(towrap, wrap_pre_SSL_read, wrap_post_SSL_read); if (!ok) { dr_fprintf(STDERR, "Couldn’t wrap gnutls_record_recv\n"); DR_ASSERT(ok); } } }
static dr_emit_flags_t event_app_analysis(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating, void **user_data) { per_thread_t *data = drmgr_get_tls_field(drcontext, tls_idx); *user_data = (void *)&data->reg_addr; /* If we have an outstanding write, that means we did not correctly handle a case * where there was a write but no fall-through NOP or terminating instruction in * the previous basic block. */ DR_ASSERT(data->reg_addr == DR_REG_NULL); return DR_EMIT_DEFAULT; }
static void insert_save_addr(void *drcontext, instrlist_t *ilist, instr_t *where, opnd_t ref, reg_id_t reg_ptr, reg_id_t reg_addr) { bool ok; /* we use reg_ptr as scratch to get addr */ ok = drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg_addr, reg_ptr); DR_ASSERT(ok); insert_load_buf_ptr(drcontext, ilist, where, reg_ptr); MINSERT(ilist, where, XINST_CREATE_store(drcontext, OPND_CREATE_MEMPTR(reg_ptr, offsetof(mem_ref_t, addr)), opnd_create_reg(reg_addr))); }
static void event_exit() { char msg[512]; int len; len = snprintf(msg, sizeof(msg) / sizeof(msg[0]), "Number of basi blocks built : %"UINT64_FORMAT_CODE"\n" " Average size : %5.2lf instructions\n", counts_as_built.blocks, counts_as_built.total_size / (double)counts_as_built.blocks); DR_ASSERT(len > 0); msg[sizeof(msg)/sizeof(msg[0])-1] = '\0'; /*NULL Terminate */ DISPLAY_STRING(msg); /* Free mutex */ dr_mutex_destroy(as_built_lock); }
void memtrace_init(client_id_t id,const char * name, const char * arguments) { char logfilename[MAX_STRING_LENGTH]; file_t in_file; drmgr_init(); drutil_init(); client_id = id; mutex = dr_mutex_create(); DR_ASSERT(parse_commandline_args(arguments) == true); head = md_initialize(); if(client_arg->filter_mode != FILTER_NONE){ in_file = dr_open_file(client_arg->filter_filename,DR_FILE_READ); DR_ASSERT(in_file != INVALID_FILE); md_read_from_file(head,in_file,false); dr_close_file(in_file); } tls_index = drmgr_register_tls_field(); DR_ASSERT(tls_index != -1); code_cache_init(); if (log_mode){ populate_conv_filename(logfilename, logdir, name, NULL); logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE); } strncpy(ins_pass_name, name, MAX_STRING_LENGTH); }
static instr_t * static_info_instrumentation(void * drcontext, instr_t* instr){ /* for each src and dest add the information accordingly this should return canonicalized static info about an instruction; breaking down any complex instructions if necessary 1) check whether this instruction needs to be instrumented 2) if yes, then get a location and then proceed to instrument -> return the struct 3) if no, return null */ /* main variables */ per_thread_t * data = drmgr_get_tls_field(drcontext,tls_index); /* helper variables */ int opcode; instr_t * ret; /* loop variables */ int i; /* 1) */ opcode = instr_get_opcode(instr); if (client_arg->instrace_mode == OPCODE_TRACE){ opcodes_visited[opcode] = true; return NULL; } if ( (client_arg->instrace_mode == OPERAND_TRACE) || (client_arg->instrace_mode == INS_DISASM_TRACE) ){ operand_trace(instr, drcontext); return NULL; } /* check whether this instr needs instrumentation - check for ones to skip and skip if */ /*switch(opcode){ case OP_jecxz: return NULL; }*/ /* 2) */ data->static_array[data->static_ptr++] = instr_clone(drcontext,instr); DR_ASSERT(data->static_ptr < data->static_array_size); return data->static_array[data->static_ptr - 1]; }
DR_EXPORT void dr_init(client_id_t id) { /* register events */ dr_register_thread_init_event(event_thread_init); dr_register_thread_exit_event(event_thread_exit); dr_register_exit_event(event_exit); dr_register_bb_event(event_basic_block); /* The TLS field provided by DR cannot be directly accessed from code cache. * For better performance, we allocate raw TLS so that we can directly * access and update it with a single instruction. */ if(!dr_raw_tls_calloc(&tls_seg, &tls_offs, 1, 0)) DR_ASSERT(false); }
void writeCallgrind(int thread_id){ char logname[MAXIMUM_PATH]; char *dirsep; int len; char * tmp = process_path; len = dr_snprintf(logname, sizeof(logname)/sizeof(logname[0]), "%s", tmp); DR_ASSERT(len > 0); for (dirsep = logname + len; *dirsep != '/'; dirsep--) DR_ASSERT(dirsep > logname); len = dr_snprintf(dirsep + 1, (sizeof(logname) - (dirsep - logname))/sizeof(logname[0]), "callgrind.%d.out", thread_id); DR_ASSERT(len > 0); NULL_TERMINATE(logname); logOut = dr_open_file(logname, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); DR_ASSERT(logOut != INVALID_FILE); // dr_log(drcontext, LOG_ALL, 1, // "floating point: log for thread %d is fp.%03d\n",thread_id, thread_id); #ifdef SHOW_RESULTS if (dr_is_notify_on()) { // dr_fprintf(STDERR, "<floating point instruction operands for thread %d in %s>\n", // dr_get_thread_id(drcontext), logname); } #endif dr_fprintf(logOut, "version: 1\n"); dr_fprintf(logOut, "creator: callgrind-3.6.1-Debian\n"); dr_fprintf(logOut, "positions: instr line\n"); dr_fprintf(logOut, "events: Average Max\n\n\n"); }
static void wrap_post(void *wrapcxt, void *user_data) { #ifdef SHOW_RESULTS /* we want determinism in our test suite */ size_t sz = (size_t) user_data; /* test out-of-memory by having a random moderately-large alloc fail */ if (sz > 1024 && dr_get_random_value(1000) < 10) { bool ok = drwrap_set_retval(wrapcxt, NULL); DR_ASSERT(ok); dr_mutex_lock(max_lock); malloc_oom++; dr_mutex_unlock(max_lock); } #endif }
DR_EXPORT void dr_init(client_id_t id) { drreg_options_t ops = { sizeof(ops), 2 /*max slots needed*/, false }; drreg_status_t res; bool ok = drmgr_init(); CHECK(ok, "drmgr_init failed"); ok = drx_init(); CHECK(ok, "drx_init failed"); res = drreg_init(&ops); CHECK(res == DRREG_SUCCESS, "drreg_init failed"); dr_register_exit_event(event_exit); if (!drmgr_register_bb_instrumentation_event(NULL, event_app_instruction, NULL)) DR_ASSERT(false); }
static void do_mem_dump(file_t file, uint base_pc,uint size){ uint read; bool ok; byte * mem_values = dr_global_alloc(sizeof(byte) * size); ssize_t written; ok = dr_safe_read(base_pc, size, mem_values, &read); DR_ASSERT(ok); written = dr_write_file(file, mem_values, size); DEBUG_PRINT("read %d from %x of size %d and written %d\n", read, base_pc, size, written); dr_global_free(mem_values, sizeof(byte) * size); }
/* * Helper function for bulk use of drwrap. */ static void try_wrap_fn(const module_data_t *module, const char *name, prewrapper_t pre, postwrapper_t post, bool *done) { if (*done) return; size_t offset; drsym_error_t status = drsym_lookup_symbol( module->full_path, name, &offset, DRSYM_DEFAULT_FLAGS); if (status == DRSYM_SUCCESS) { app_pc notify_fn = module->start + offset; bool ok = drwrap_wrap(notify_fn, pre, post); DR_ASSERT(ok); *done = true; } }
static void show_results(void) { #ifdef SHOW_RESULTS char msg[512]; int len; /* Note that using %f with dr_printf or dr_fprintf on Windows will print * garbage as they use ntdll._vsnprintf, so we must use dr_snprintf. */ len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "<Number of system calls seen: %d>", num_syscalls); DR_ASSERT(len > 0); msg[sizeof(msg)/sizeof(msg[0])-1] = '\0'; DISPLAY_STRING(msg); #endif /* SHOW_RESULTS */ }
trace_type_t offline_instru_t::get_entry_type(byte *buf_ptr) const { offline_entry_t *entry = (offline_entry_t *) buf_ptr; switch (entry->addr.type) { case OFFLINE_TYPE_MEMREF: return TRACE_TYPE_READ; case OFFLINE_TYPE_MEMREF_HIGH: return TRACE_TYPE_READ; case OFFLINE_TYPE_PC: return TRACE_TYPE_INSTR; case OFFLINE_TYPE_THREAD: return TRACE_TYPE_THREAD; case OFFLINE_TYPE_PID: return TRACE_TYPE_PID; case OFFLINE_TYPE_TIMESTAMP: return TRACE_TYPE_THREAD; // Closest. case OFFLINE_TYPE_IFLUSH: return TRACE_TYPE_INSTR_FLUSH; } DR_ASSERT(false); return TRACE_TYPE_THREAD_EXIT; // Unknown: returning rarest entry. }
static void event_exit(void) { if (!drmgr_unregister_tls_field(tls_idx) || !drmgr_unregister_thread_init_event(event_thread_init) || !drmgr_unregister_thread_exit_event(event_thread_exit) || !drmgr_unregister_bb_app2app_event(event_bb_app2app) || !drmgr_unregister_bb_insertion_event(event_app_instruction)) DR_ASSERT(false); drx_buf_free(write_buffer); drx_buf_free(trace_buffer); drutil_exit(); drreg_exit(); drmgr_exit(); drx_exit(); }
static void event_exit(void) { #ifdef SHOW_RESULTS char msg[256]; int len; len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "<Largest malloc request: %d>\n<OOM simulations: %d>\n", max_malloc, malloc_oom); DR_ASSERT(len > 0); NULL_TERMINATE(msg); DISPLAY_STRING(msg); #endif /* SHOW_RESULTS */ dr_mutex_destroy(max_lock); drwrap_exit(); }
static inline void ordered_lock(ipc_channel_t *channel, uint tid) { dr_mutex_lock(channel->queue_lock); ticket_queue_t *q = &channel->ticket_queue; if (q->locked) { ticket_node_t *node = dr_global_alloc(sizeof(ticket_node_t)); if (node == NULL) DR_ABORT_MSG("Failed to allocate ticket node\n"); node->next = NULL; node->dr_event = dr_event_create(); node->waiting = true; node->thread_id = tid; DR_ASSERT(q->tail->next == NULL); q->tail = q->tail->next = node; SGL_DEBUG("Sleeping Thread :%d\n", tid); dr_mutex_unlock(channel->queue_lock); /* MDL20170425 TODO(soonish) * how likely is it that we'll miss a wakeup here? */ while (node->waiting) dr_event_wait(node->dr_event); dr_mutex_lock(channel->queue_lock); q->head->next = node->next; if (q->tail == node) q->tail = q->head; dr_event_destroy(node->dr_event); dr_global_free(node, sizeof(ticket_node_t)); SGL_DEBUG("Awakened Thread :%d\n", tid); } else { q->locked = true; } dr_mutex_unlock(channel->queue_lock); }
/* save reg before where in ilist */ void umbra_save_reg(void *drcontext, umbra_info_t *info, instrlist_t *ilist, instr_t *where, reg_id_t reg) { int slot; instr_t *instr; DR_ASSERT(reg >= REG_SPILL_START && reg <= REG_SPILL_STOP); slot = reg - REG_SPILL_START; instr = INSTR_CREATE_mov_st(drcontext, OPND_CREATE_ABSMEM(&info->spill_regs[slot], OPSZ_PTR), opnd_create_reg(reg)); instrlist_meta_preinsert(ilist, where, instr); }
static void display_results(per_thread_t *data, char *thread_note) { #ifdef SHOW_RESULTS char msg[512]; int len; len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "%sInstrumentation results:\n" " saw %d direct calls\n" " saw %d indirect calls\n" " saw %d returns\n", thread_note, data->num_direct_calls, data->num_indirect_calls, data->num_returns); DR_ASSERT(len > 0); NULL_TERMINATE(msg); DISPLAY_STRING(msg); #endif /* SHOW_RESULTS */ }
static void event_thread_exit(void *drcontext) { per_thread_t *data = (per_thread_t *) dr_get_tls_field(drcontext); char msg[512]; int len; len = dr_snprintf(msg, sizeof(msg)/sizeof(msg[0]), "Thread %d exited - ", dr_get_thread_id(drcontext)); DR_ASSERT(len > 0); NULL_TERMINATE(msg); /* display thread private counts data */ display_results(data, msg); /* clean up memory */ dr_thread_free(drcontext, data, sizeof(per_thread_t)); }