void writeLog(void* drcontext){ char logname[MAXIMUM_PATH]; char *dirsep; int len; len = dr_snprintf(logname, sizeof(logname)/sizeof(logname[0]), "%s", dr_get_client_path(client_id)); 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]), "floatingpoint.%d.log", dr_get_thread_id(drcontext)); DR_ASSERT(len > 0); NULL_TERMINATE(logname); logF = dr_open_file(logname, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); DR_ASSERT(logF != INVALID_FILE); dr_log(drcontext, LOG_ALL, 1, "floating point: log for thread %d is fp.%03d\n", dr_get_thread_id(drcontext), dr_get_thread_id(drcontext)); #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 thread_id_for_log = dr_get_thread_id(drcontext); }
static void event_thread_init(void *drcontext) { if (main_thread == 0) main_thread = dr_get_thread_id(drcontext); drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_int_t)dr_get_thread_id(drcontext)); }
<client_name>_thread_exit(void *drcontext){ per_thread_t * data; data = drmgr_get_tls_field(drcontext, tls_index); dr_thread_free(drcontext, data, sizeof(per_thread_t)); DEBUG_PRINT("%s - exiting thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
void instrace_thread_exit(void *drcontext) { per_thread_t *data; int i; if (client_arg->instrace_mode == INS_TRACE){ ins_trace(drcontext); } data = drmgr_get_tls_field(drcontext, tls_index); dr_mutex_lock(mutex); num_refs += data->num_refs; dr_mutex_unlock(mutex); dr_close_file(data->outfile); if (log_mode){ dr_close_file(data->logfile); } dr_thread_free(drcontext, data->buf_base, INSTR_BUF_SIZE); dr_thread_free(drcontext, data->output_array, OUTPUT_BUF_SIZE); DEBUG_PRINT("%s - thread id : %d, cloned instructions freeing now - %d\n",ins_pass_name, dr_get_thread_id(drcontext),data->static_ptr); for(i=0 ; i<data->static_ptr; i++){ instr_destroy(dr_get_current_drcontext(),data->static_array[i]); } dr_thread_free(drcontext, data->static_array, sizeof(instr_t *)*client_arg->static_info_size); dr_thread_free(drcontext, data, sizeof(per_thread_t)); DEBUG_PRINT("%s - exiting thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
static void event_thread_context_exit(void *drcontext, bool thread_exit) { if (!thread_exit && dr_get_thread_id(drcontext) != main_thread) { #if VERBOSE dr_fprintf(STDERR, " non-main thread exiting callback depth=%d cls=%d\n", cb_depth, (int)(ptr_int_t) drmgr_get_cls_field(drcontext, cls_idx)); #endif CHECK(drmgr_get_cls_field(drcontext, cls_idx) == (void *)(ptr_int_t)cb_depth, "cls not preserved"); cb_depth--; CHECK(drmgr_get_tls_field(drcontext, tls_idx) == (void *)(ptr_int_t)dr_get_thread_id(drcontext), "tls not preserved"); } }
static void event_thread_init(void *drcontext) { if (main_thread == 0) main_thread = dr_get_thread_id(drcontext); drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_int_t)dr_get_thread_id(drcontext)); if (!in_event_thread_init) { dr_mutex_lock(threadlock); if (!in_event_thread_init) { dr_fprintf(STDERR, "in event_thread_init\n"); in_event_thread_init = true; } dr_mutex_unlock(threadlock); } }
/* event_bb_insert calls necessary functions to fill up the static info about an instruction and to instrument memory instructions to get its runtime address using dynamic instrumentation */ dr_emit_flags_t instrace_bb_instrumentation(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { /* algorithm 1. First we need to filter the instructions to instrument 2. call the static info filler function to get a slot at the global instruction array 3. send the data appropriately to instrumentation function */ instr_t * instr_info; module_data_t * md; uint offset = 0; per_thread_t * data; /* these are for the use of the caller - instrlist_first(bb) */ if(filter_from_list(head,instr,client_arg->filter_mode) && should_filter_thread(dr_get_thread_id(drcontext))){ //dr_printf("entering static instrumentation\n"); instr_info = static_info_instrumentation(drcontext, instr); if(instr_info != NULL){ //can only be entered in the DISASSEMBLY_TRACE or INS_TRACE DR_ASSERT(client_arg->instrace_mode == INS_TRACE || client_arg->instrace_mode == DISASSEMBLY_TRACE); dynamic_info_instrumentation(drcontext, bb, instr, instr_info); } //instrlist_disassemble(drcontext, tag, bb, logfile); } return DR_EMIT_DEFAULT; }
static void event_thread_exit(void *drcontext) { CHECK(drmgr_get_tls_field(drcontext, tls_idx) == (void *)(ptr_int_t)dr_get_thread_id(drcontext), "tls not preserved"); }
/* callbacks for threads */ void <client_name>_thread_init(void *drcontext){ per_thread_t * data; DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext)); data = dr_thread_alloc(drcontext, sizeof(per_thread_t)); drmgr_set_tls_field(drcontext, tls_index, data); }
static void event_thread_context_init(void *drcontext, bool new_depth) { if (dr_get_thread_id(drcontext) != main_thread) { cb_depth++; #if VERBOSE /* # cbs differs on xp vs win7 so not part of output */ dr_fprintf(STDERR, "non-main thread entering callback depth=%d\n", cb_depth); #endif CHECK(new_depth || drmgr_get_cls_field(drcontext, cls_idx) == (void *)(ptr_int_t)cb_depth, "not re-using prior callback value"); drmgr_set_cls_field(drcontext, cls_idx, (void *)(ptr_int_t)cb_depth); CHECK(drmgr_get_tls_field(drcontext, tls_idx) == (void *)(ptr_int_t)dr_get_thread_id(drcontext), "tls not preserved"); } }
static void event_thread_init(void *drcontext) { per_thread_t *data; static volatile int thread_count; if (options.native_until_thread > 0) { int local_count = dr_atomic_add32_return_sum(&thread_count, 1); NOTIFY(1, "@@@@@@@@@@@@@ new thread #%d "TIDFMT"\n", local_count, dr_get_thread_id(drcontext)); if (go_native && local_count == options.native_until_thread) { void **drcontexts = NULL; uint num_threads, i; go_native = false; NOTIFY(1, "thread "TIDFMT" suspending all threads\n", dr_get_thread_id(drcontext)); if (dr_suspend_all_other_threads_ex(&drcontexts, &num_threads, NULL, DR_SUSPEND_NATIVE)) { NOTIFY(1, "suspended %d threads\n", num_threads); for (i = 0; i < num_threads; i++) { if (dr_is_thread_native(drcontexts[i])) { NOTIFY(2, "\txxx taking over thread #%d "TIDFMT"\n", i, dr_get_thread_id(drcontexts[i])); dr_retakeover_suspended_native_thread(drcontexts[i]); } else { NOTIFY(2, "\tthread #%d "TIDFMT" under DR\n", i, dr_get_thread_id(drcontexts[i])); } } if (!dr_resume_all_other_threads(drcontexts, num_threads)) { ASSERT(false, "failed to resume threads"); } } else { ASSERT(false, "failed to suspend threads"); } } } /* allocate thread private data for per-thread cache */ if (drcov_per_thread) data = thread_data_create(drcontext); else data = thread_data_copy(drcontext); drmgr_set_tls_field(drcontext, tls_idx, data); }
static void umbra_client_thread_init(void *drcontext, umbra_info_t *umbra_info) { client_tls_data_t *tls_data; /* allocate client tls data */ tls_data = dr_thread_alloc(drcontext, sizeof(client_tls_data_t)); umbra_info->client_tls_data = tls_data; tls_data->tid = dr_get_thread_id(drcontext); }
static void check_tls_write_from_cache(void) { void *drcontext = dr_get_current_drcontext(); CHECK(drmgr_get_tls_field(drcontext, tls_idx) == (void *) MAGIC_NUMBER_FROM_CACHE, "cls write from cache incorrect"); /* now restore */ drmgr_set_tls_field(drcontext, tls_idx, (void *)(ptr_int_t)dr_get_thread_id(drcontext)); checked_tls_write_from_cache = true; }
void funcwrap_thread_exit(void *drcontext){ per_thread_t * data; data = drmgr_get_tls_field(drcontext, tls_index); if (log_mode){ dr_close_file(data->logfile); } dr_thread_free(drcontext, data, sizeof(per_thread_t)); DEBUG_PRINT("%s - exiting thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
dr_emit_flags_t funcwrap_bb_instrumentation(void *drcontext, void *tag, instrlist_t *bb, instr_t *instr, bool for_trace, bool translating, void *user_data) { instr_t * first = instrlist_first(bb); app_pc pc = instr_get_app_pc(first); module_data_t * module_data; per_thread_t * data = drmgr_get_tls_field(dr_get_current_drcontext(), tls_index); module_t * md; app_pc offset; if (instr != first || data->nesting != 0){ return DR_EMIT_DEFAULT; } module_data = dr_lookup_module(pc); data = drmgr_get_tls_field(drcontext, tls_index); if (module_data != NULL){ md = md_lookup_module(head, module_data->full_path); if (md != NULL){ offset = pc - module_data->start; for (int i = 1; i <= md->bbs[0].start_addr; i++){ if (offset == md->bbs[i].start_addr){ DEBUG_PRINT("bb instrumenting function\n"); data->filter_func = true; dr_insert_clean_call(drcontext, bb, instr, clean_call, false, 1, OPND_CREATE_INTPTR(instr_get_app_pc(instr))); wrap_thread_id = dr_get_thread_id(drcontext); DEBUG_PRINT("done bb instrumenting function\n"); } } } } /*if (data->filter_func){ instrlist_disassemble(drcontext, instr_get_app_pc(instrlist_first(bb)), bb, logfile); }*/ dr_free_module_data(module_data); return DR_EMIT_DEFAULT; }
void handle_thread_exit(void* ctx) { thread_id_t thread_id; struct trace_buffer_t* tb; check_ctx(ctx, "handle_thread_exit"); thread_id = dr_get_thread_id(ctx); dr_fprintf(STDERR, "info: cleaning up thread 0x%" PRIx64 "..\n", (uint64_t)thread_id); tb = dr_get_tls_field(ctx); tb_delete(tb); dr_set_tls_field(ctx, NULL); }
static void event_thread_init(void *drcontext) { /* create an instance of our data structure for this thread */ per_thread_t *data = (per_thread_t *)dr_thread_alloc(drcontext, sizeof(per_thread_t)); /* store it in the slot provided in the drcontext */ drmgr_set_tls_field(drcontext, tls_idx, data); data->num_direct_calls = 0; data->num_indirect_calls = 0; data->num_returns = 0; dr_log(drcontext, DR_LOG_ALL, 1, "countcalls: set up for thread " TIDFMT "\n", dr_get_thread_id(drcontext)); }
static void event_thread_context_exit(void *drcontext, bool thread_exit) { #ifdef SHOW_RESULTS dr_fprintf(STDERR, "resuming prior thread context id="TIDFMT"\n", dr_get_thread_id(drcontext)); #endif if (thread_exit) { per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, tcls_idx); dr_thread_free(drcontext, data, sizeof(per_thread_t)); } /* else, nothing to do: we leave the struct for re-use on next context */ }
void handle_thread_init(void* ctx) { thread_id_t thread_id; struct trace_buffer_t* tb; check_ctx(ctx, "handle_thread_init"); thread_id = dr_get_thread_id(ctx); dr_fprintf(STDERR, "info: initializing thread 0x%" PRIx64 "..\n", (uint64_t)thread_id); tb = tb_create(thread_id); dr_set_tls_field(ctx, tb); tb_tlv(tb, TYPE_TRACE); }
static void event_thread_exit(void *drcontext) { CHECK(drmgr_get_tls_field(drcontext, tls_idx) == (void *)(ptr_int_t)dr_get_thread_id(drcontext), "tls not preserved"); if (!in_event_thread_exit) { dr_mutex_lock(threadlock); if (!in_event_thread_exit) { dr_fprintf(STDERR, "in event_thread_exit\n"); in_event_thread_exit = true; } dr_mutex_unlock(threadlock); } }
/* callbacks for threads */ void funcwrap_thread_init(void *drcontext){ per_thread_t * data; char logfilename[MAX_STRING_LENGTH]; char thread_id[MAX_STRING_LENGTH]; DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext)); data = dr_thread_alloc(drcontext, sizeof(per_thread_t)); if (log_mode){ dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext)); populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id); data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE); } data->filter_func = false; data->nesting = 0; drmgr_set_tls_field(drcontext, tls_index, data); DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
static void event_thread_context_init(void *drcontext, bool new_depth) { /* create an instance of our data structure for this thread context */ per_thread_t *data; #ifdef SHOW_RESULTS dr_fprintf(STDERR, "new thread context id="TIDFMT"%s\n", dr_get_thread_id(drcontext), new_depth ? " new depth" : ""); #endif if (new_depth) { data = (per_thread_t *) dr_thread_alloc(drcontext, sizeof(per_thread_t)); drmgr_set_cls_field(drcontext, tcls_idx, data); } else data = (per_thread_t *) drmgr_get_cls_field(drcontext, tcls_idx); memset(data, 0, sizeof(*data)); }
void tb_flush(struct trace_buffer_t* tb) { size_t size; int64 pos; size_t written; void* aligned_current; tb_tlv_complete(tb); // Align current position to block boundary. aligned_current = aligned_block(tb->current); memset(tb->current, 'X', aligned_current - tb->current); tb->current = aligned_current; size = tb->current - (void*)&tb->block; if(size == sizeof(struct block_t)) { // Nothing to do. return; } tb->block.length = (uint32_t)size; tb->block.crc32 = 0; tb->block.crc32 = crc32((char*)&tb->block, size); // Write data. dr_mutex_lock(tb->mutex); pos = dr_file_tell(tb->file); if(pos == -1) { dr_fprintf(STDERR, "fatal: dr_file_tell() failed\n"); dr_exit_process(1); } dr_fprintf(STDERR, "info: flushing tb=%p file-offset=%" PRId64 " size=%u" " tb-thread=0x%" PRIx64 " current-thread=0x%" PRIx64 "\n", tb, pos, (unsigned int)size, tb->block.thread_id, (uint64_t)dr_get_thread_id(dr_get_current_drcontext())); written = dr_write_file(tb->file, &tb->block, size); dr_mutex_unlock(tb->mutex); if(written != size) { dr_fprintf(STDERR, "fatal: dr_write_file() failed\n"); dr_exit_process(1); } // Reset position. tb->current = tb + 1; }
void memtrace_thread_exit(void *drcontext) { per_thread_t *data; memtrace(drcontext); data = drmgr_get_tls_field(drcontext, tls_index); dr_mutex_lock(mutex); num_refs += data->num_refs; dr_mutex_unlock(mutex); if (log_mode){ dr_close_file(data->logfile); } dr_close_file(data->outfile); dr_thread_free(drcontext, data->buf_base, MEM_BUF_SIZE); dr_thread_free(drcontext, data, sizeof(per_thread_t)); DEBUG_PRINT("%s - exiting thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
/**************************************************************************** * Utility Functions */ static file_t log_file_create_helper(void *drcontext, const char *suffix, char *buf, size_t buf_els) { file_t log = drx_open_unique_appid_file(options.logdir, drcontext == NULL ? dr_get_process_id() : dr_get_thread_id(drcontext), "drcov", suffix, #ifndef WINDOWS DR_FILE_CLOSE_ON_FORK | #endif DR_FILE_ALLOW_LARGE, buf, buf_els); if (log != INVALID_FILE) { dr_log(drcontext, DR_LOG_ALL, 1, "drcov: log file is %s\n", buf); NOTIFY(1, "<created log file %s>\n", buf); } return log; }
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)); }
void instrace_thread_init(void *drcontext) { char outfilename[MAX_STRING_LENGTH]; char logfilename[MAX_STRING_LENGTH]; char thread_id[MAX_STRING_LENGTH]; char extra_info[MAX_STRING_LENGTH]; char *dirsep; int len; per_thread_t *data; char * mode; uint * stack_base; uint * deallocation_stack; DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext)); /* allocate thread private data */ data = dr_thread_alloc(drcontext, sizeof(per_thread_t)); drmgr_set_tls_field(drcontext, tls_index, data); data->buf_base = dr_thread_alloc(drcontext, INSTR_BUF_SIZE); data->buf_ptr = data->buf_base; /* set buf_end to be negative of address of buffer end for the lea later */ data->buf_end = -(ptr_int_t)(data->buf_base + INSTR_BUF_SIZE); data->num_refs = 0; /* We're going to dump our data to a per-thread file. * On Windows we need an absolute path so we place it in * the same directory as our library. We could also pass * in a path and retrieve with dr_get_options(). */ dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext)); if (log_mode){ populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id); data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); } /* instrace types */ if (client_arg->instrace_mode == OPERAND_TRACE){ mode = "opnd"; } else if (client_arg->instrace_mode == OPCODE_TRACE){ mode = "opcode"; } else if (client_arg->instrace_mode == DISASSEMBLY_TRACE){ mode = "disasm"; } else if (client_arg->instrace_mode == INS_DISASM_TRACE){ mode = "asm_instr"; } else{ mode = "instr"; } dr_snprintf(extra_info, MAX_STRING_LENGTH, "%s_%s_%s", client_arg->extra_info, mode, thread_id); populate_conv_filename(outfilename, client_arg->output_folder, ins_pass_name, extra_info); data->outfile = dr_open_file(outfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); DR_ASSERT(data->outfile != INVALID_FILE); DEBUG_PRINT("%s - thread id : %d, new thread logging at - %s\n",ins_pass_name, dr_get_thread_id(drcontext),logfilename); data->static_array = (instr_t **)dr_thread_alloc(drcontext,sizeof(instr_t *)*client_arg->static_info_size); data->static_array_size = client_arg->static_info_size; data->static_ptr = 0; data->output_array = (output_t *)dr_thread_alloc(drcontext,OUTPUT_BUF_SIZE); deallocation_stack = &data->deallocation_stack; stack_base = &data->stack_base; __asm{ mov EAX, FS : [0x04] mov EBX, stack_base mov [EBX], EAX mov EAX, FS : [0xE0C] mov EBX, deallocation_stack mov [EBX], EAX } DEBUG_PRINT("%s - thread %d stack information - stack_base %x stack_reserve %x\n", ins_pass_name, dr_get_thread_id(drcontext), data->stack_base, data->deallocation_stack); DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }
void memtrace_thread_init(void *drcontext) { char logfilename[MAX_STRING_LENGTH]; char outfilename[MAX_STRING_LENGTH]; char thread_id[MAX_STRING_LENGTH]; char extra_info[MAX_STRING_LENGTH]; char *dirsep; int len; per_thread_t *data; uint * stack_base; uint * deallocation_stack; int i = 0; DEBUG_PRINT("%s - initializing thread %d\n", ins_pass_name, dr_get_thread_id(drcontext)); /* allocate thread private data */ data = dr_thread_alloc(drcontext, sizeof(per_thread_t)); drmgr_set_tls_field(drcontext, tls_index, data); data->buf_base = dr_thread_alloc(drcontext, MEM_BUF_SIZE); data->buf_ptr = data->buf_base; /* set buf_end to be negative of address of buffer end for the lea later */ data->buf_end = -(ptr_int_t)(data->buf_base + MEM_BUF_SIZE); data->num_refs = 0; /* We're going to dump our data to a per-thread file. * On Windows we need an absolute path so we place it in * the same directory as our library. We could also pass * in a path and retrieve with dr_get_options(). */ dr_snprintf(thread_id, MAX_STRING_LENGTH, "%d", dr_get_thread_id(drcontext)); if (log_mode){ populate_conv_filename(logfilename, logdir, ins_pass_name, thread_id); data->logfile = dr_open_file(logfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); } dr_snprintf(extra_info, MAX_STRING_LENGTH, "%s_%s", client_arg->extra_info, thread_id); populate_conv_filename(outfilename, client_arg->output_folder, ins_pass_name, extra_info); data->outfile = dr_open_file(outfilename, DR_FILE_WRITE_OVERWRITE | DR_FILE_ALLOW_LARGE); DR_ASSERT(data->outfile != INVALID_FILE); /* this is done for 32 bit applications */ deallocation_stack = &data->stack_limit; stack_base = &data->stack_base; __asm{ mov EAX, FS : [0x04] mov EBX, stack_base mov[EBX], EAX mov EAX, FS : [0xE0C] mov EBX, deallocation_stack mov[EBX], EAX } DEBUG_PRINT("%s - stack boundaries - %x,%x\n", ins_pass_name, data->stack_base, data->stack_limit); DEBUG_PRINT("%s - initializing thread done %d\n", ins_pass_name, dr_get_thread_id(drcontext)); }