/* this is only called when the instrace mode is operand trace (this happens at the instrumentation time) */ static void operand_trace(instr_t * instr, void * drcontext){ int i; char stringop[MAX_STRING_LENGTH]; int pc = 0; per_thread_t * data = drmgr_get_tls_field(drcontext, tls_index); module_data_t * module_data = dr_lookup_module(instr_get_app_pc(instr)); if (module_data != NULL){ pc = instr_get_app_pc(instr) - module_data->start; } instr_disassemble_to_buffer(drcontext, instr, stringop, MAX_STRING_LENGTH); if (client_arg->instrace_mode == OPERAND_TRACE){ dr_fprintf(data->outfile, "%s\n", stringop); for (i = 0; i < instr_num_dsts(instr); i++){ opnd_disassemble_to_buffer(drcontext, instr_get_dst(instr, i), stringop, MAX_STRING_LENGTH); if ((instr_get_opcode(instr) == OP_lea) && opnd_is_base_disp(instr_get_dst(instr,i))){ dr_fprintf(data->outfile, "dst-\n"); print_base_disp_for_lea(data->outfile, instr_get_dst(instr, i)); } else{ dr_fprintf(data->outfile, "dst-%d-%s\n", i, stringop); } } for (i = 0; i < instr_num_srcs(instr); i++){ opnd_disassemble_to_buffer(drcontext, instr_get_src(instr, i), stringop, MAX_STRING_LENGTH); if ((instr_get_opcode(instr) == OP_lea) && opnd_is_base_disp(instr_get_src(instr, i))){ dr_fprintf(data->outfile, "src-\n"); print_base_disp_for_lea(data->outfile, instr_get_src(instr, i)); } else{ dr_fprintf(data->outfile, "src-%d-%s\n", i, stringop); } } if (module_data != NULL){ dr_fprintf(data->outfile, "app_pc-%d\n", pc); } } else if (client_arg->instrace_mode == INS_DISASM_TRACE){ if (module_data != NULL){ if (md_get_module_position(instrace_head, module_data->full_path) == -1){ md_add_module(instrace_head, module_data->full_path, MAX_BBS_PER_MODULE); } dr_fprintf(data->outfile, "%d,%d,%s\n", md_get_module_position(instrace_head, module_data->full_path), pc, stringop); } else{ dr_fprintf(data->outfile, "%d,%d,%s\n",0, 0, stringop); } } dr_free_module_data(module_data); }
static void print_address(app_pc addr, int bits, double loss, double lossD) { testarr[testcount] = lossD; testcount++; char key_string[KEY_MAX_LENGTH]; snprintf(key_string, KEY_MAX_LENGTH, "%s", "main");//sym->name); const char* prefix = "PRINT ADDRESS: "; drsym_error_t symres; drsym_info_t *sym; char sbuf[sizeof(*sym) + MAX_SYM_RESULT]; module_data_t *data; data = dr_lookup_module(addr); if (data == NULL) { // dr_fprintf(logF, "%s data is null "PFX" \n", prefix, addr); return; } snprintf(process_path, MAXIMUM_PATH,"%s",data->full_path); if(!callgrind_log_created){ writeCallgrind(thread_id_for_log); callgrind_log_created = true; } sym = (drsym_info_t *) sbuf; sym->struct_size = sizeof(*sym); sym->name_size = MAX_SYM_RESULT; symres = drsym_lookup_address(data->full_path, addr - data->start, sym, DRSYM_DEFAULT_FLAGS); /* if (symres == DRSYM_SUCCESS || symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) { const char *modname = dr_module_preferred_name(data); if (modname == NULL) modname = "<noname>"; //dr_fprintf(logF, "%s "PFX" %s, function name is: %s, "PIFX", line off "PFX" \n", prefix, addr, //modname, sym->name, addr - data->start - sym->start_offs, sym->line_offs); //printf("test ins %d\n", testcount); //add check for line not available if (symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) { // dr_fprintf(logF, "%s Line is not available\n", prefix); } else { // dr_fprintf(logF, "Line number is %s:%"UINT64_FORMAT_CODE" %d\n", // sym->file, sym->line, sym->line_offs); } } else // dr_fprintf(logF, "%s some error "PFX" \n", prefix, addr); */ dr_free_module_data(data); }
void clean_call_mem_information(instr_t * instr, app_pc mem_val, uint write){ void * drcontext = dr_get_current_drcontext(); module_data_t * data = dr_lookup_module(instr_get_app_pc(instr)); uint offset; app_pc base_pc; size_t size; uint prot; file_t dump_file; char * dump_filename; DR_ASSERT(data != NULL); offset = instr_get_app_pc(instr) - data->start; dr_mutex_lock(mutex); //if (!md_lookup_bb_in_module(done_head, data->full_path, offset)){ //md_add_bb_to_module(done_head, data->full_path, offset, MAX_BBS_PER_MODULE, false); dr_query_memory(mem_val, &base_pc, &size, &prot); //DEBUG_PRINT("base pc - %x, size - %u, write - %u\n", base_pc, size, write); if (write){ /* postpone till the end of the function */ if (!is_mem_region_present(write_regions, base_pc, size, write_region_size)){ DEBUG_PRINT("write registered - offset - %x memval %x\n", offset, mem_val); add_to_mem_region(write_regions, base_pc, size, &write_region_size); DEBUG_PRINT("base pc %x, size %d\n", base_pc, size); } } else{ if (!is_mem_region_present(read_regions, base_pc, size, read_region_size)){ add_to_mem_region(read_regions, base_pc, size, &read_region_size); //DEBUG_PRINT("size - %d\n", read_region_size); //DEBUG_PRINT("present - %d\n", is_mem_region_present(read_regions, base_pc, size, read_region_size)); //dr_abort(); DEBUG_PRINT("read registered - offset - %x memval %x\n", offset, mem_val); DEBUG_PRINT("base pc %x, size %d\n", base_pc, size); dump_filename = get_mem_dump_filename(base_pc, size, write,0); dump_file = dr_open_file(dump_filename, DR_FILE_WRITE_OVERWRITE); DEBUG_PRINT("%s dumping file\n", dump_filename); do_mem_dump(dump_file, base_pc, size); DEBUG_PRINT("file dumped\n"); dr_global_free(dump_filename, sizeof(char) * MAX_STRING_LENGTH); dr_close_file(dump_file); } } //} dr_mutex_unlock(mutex); dr_free_module_data(data); }
static bool is_in_known_module(app_pc pc, bool *found_section, IMAGE_SECTION_HEADER *section) { bool found = false; module_data_t *data = dr_lookup_module(pc); if (data != NULL) { found = true; *found_section = dr_lookup_module_section(data->handle, pc, section); } dr_free_module_data(data); return found; }
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; }
app_pc get_heap_start(void) { static app_pc heap_start; /* cached value */ if (heap_start == NULL) { app_pc cur_brk = get_brk(true/*pre-us*/); dr_mem_info_t info; module_data_t *data; /* Locate the heap */ if (!dr_query_memory_ex(cur_brk - 1, &info)) { ASSERT(false, "cannot find heap region"); return NULL; } if (info.type == DR_MEMTYPE_FREE || info.type == DR_MEMTYPE_IMAGE || !TEST(DR_MEMPROT_WRITE, info.prot)) { /* Heap is empty */ heap_start = cur_brk; } else { ASSERT(!dr_memory_is_dr_internal(info.base_pc), "heap location error"); /* we no longer assert that these are equal b/c -replace_malloc * has extended the brk already */ ASSERT(info.base_pc + info.size >= cur_brk, "heap location error"); heap_start = info.base_pc; /* workaround for PR 618178 where /proc/maps is wrong on suse * and lists last 2 pages of executable as heap! */ /* On some old Linux kernel, the heap might be right after the bss * segment. DR's map iterator used by dr_query_memory_ex cannot * split bss out of heap. * We use dr_lookup_module to find the right bounds of bss so that * we can check whether the base is bss, existing heap, or merge of * the two. */ /* XXX: we still cannot handle the case that the application creates * memory right before the heap. */ data = dr_lookup_module(info.base_pc); if (data != NULL) { if (data->start < heap_start && data->end > heap_start) { heap_start = (byte *) ALIGN_FORWARD(data->end, PAGE_SIZE); LOG(1, "WARNING: workaround for invalid heap_start "PFX" => "PFX"\n", info.base_pc, heap_start); } dr_free_module_data(data); } } } return heap_start; }
/* Lookup the module containing addr and see if we have a table entry for it */ static table_entry_t * get_entry_for_address(app_pc addr) { module_data_t *data = dr_lookup_module(addr); table_entry_t *entry = NULL; if (data != NULL) { entry = table; while (entry != NULL && _stricmp(dr_module_preferred_name(data), entry->value.module_name) != 0) { entry = entry->next; } dr_free_module_data(data); } return entry; }
/* * Make a string representation of the address of an instruction, * including a function name and/or a file+line combination if * possible. These will be logged alongside every act of interest * where we can make one. */ static void instr_format_location(instr_t *instr, char **outloc) { app_pc addr = (app_pc)instr_get_app_pc(instr); char location[2048], symbol[512], fileline[1024]; bool got_sym = false, got_line = false; if (*outloc) return; symbol[0] = '\0'; fileline[0] = '\0'; module_data_t *data = dr_lookup_module(addr); if (data) { drsym_info_t sym; char file[MAXIMUM_PATH]; sym.struct_size = sizeof(sym); sym.name = symbol; sym.name_size = sizeof(symbol); sym.file = file; sym.file_size = sizeof(file); drsym_error_t status = drsym_lookup_address( data->full_path, addr - data->start, &sym, DRSYM_DEFAULT_FLAGS); got_line = (status == DRSYM_SUCCESS); got_sym = got_line || status == DRSYM_ERROR_LINE_NOT_AVAILABLE; if (got_line) snprintf(fileline, sizeof(fileline), " = %s:%"PRIu64, file, (uint64_t)sym.line); } snprintf(location, sizeof(location), "%"PRIx64"%s%s%s", (uint64_t)addr, got_sym ? " = " : "", got_sym ? symbol : "", fileline); size_t len = strlen(location) + 1; char *loc = dr_global_alloc(len); memcpy(loc, location, len); *outloc = loc; }
static void memtrace(void *drcontext) { per_thread_t *data; int num_refs; mem_ref_t *mem_ref; #ifdef READABLE_TRACE int i; #endif module_data_t * mdata; data = drmgr_get_tls_field(drcontext, tls_index); mem_ref = (mem_ref_t *)data->buf_base; num_refs = (int)((mem_ref_t *)data->buf_ptr - mem_ref); #ifdef READABLE_TRACE /*dr_fprintf(data->log, "Format: <instr address>,<(r)ead/(w)rite>,<data size>,<data address>\n");*/ for (i = 0; i < num_refs; i++) { mdata = dr_lookup_module(mem_ref->pc); if (mdata != NULL){ if (((uint)mem_ref->addr > data->stack_base) || ((uint)mem_ref->addr < data->stack_limit)){ dr_fprintf(data->outfile, "%x,%x,%d,%d,"PFX"\n", mdata->start, mem_ref->pc - mdata->start , mem_ref->write ? 1 : 0 , mem_ref->size, mem_ref->addr); } dr_free_module_data(mdata); } ++mem_ref; } #else dr_write_file(data->log, data->buf_base, (size_t)(data->buf_ptr - data->buf_base)); #endif memset(data->buf_base, 0, MEM_BUF_SIZE); data->num_refs += num_refs; data->buf_ptr = data->buf_base; }
/* this is only called when the instrace mode is disassembly trace (this happens at the analysis time)*/ static void clean_call_disassembly_trace(){ char disassembly[SHORT_STRING_LENGTH]; per_thread_t * data = drmgr_get_tls_field(dr_get_current_drcontext(), tls_index); instr_trace_t * trace = (instr_trace_t *)data->buf_ptr; module_data_t * md; md = dr_lookup_module(instr_get_app_pc(trace->static_info_instr)); instr_disassemble_to_buffer(dr_get_current_drcontext(), trace->static_info_instr, disassembly, SHORT_STRING_LENGTH); dr_fprintf(data->outfile, "%s ", disassembly); if (md != NULL){ dr_fprintf(data->outfile, "%x", instr_get_app_pc(trace->static_info_instr) - md->start); dr_free_module_data(md); } dr_fprintf(data->outfile, "\n"); }
static void print_address(file_t f, app_pc addr, const char *prefix) { drsym_error_t symres; drsym_info_t sym; char name[MAX_SYM_RESULT]; char file[MAXIMUM_PATH]; module_data_t *data; data = dr_lookup_module(addr); if (data == NULL) { dr_fprintf(f, "%s "PFX" ? ??:0\n", prefix, addr); return; } sym.struct_size = sizeof(sym); sym.name = name; sym.name_size = MAX_SYM_RESULT; sym.file = file; sym.file_size = MAXIMUM_PATH; symres = drsym_lookup_address(data->full_path, addr - data->start, &sym, DRSYM_DEFAULT_FLAGS); if (symres == DRSYM_SUCCESS || symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) { const char *modname = dr_module_preferred_name(data); if (modname == NULL) modname = "<noname>"; dr_fprintf(f, "%s "PFX" %s!%s+"PIFX, prefix, addr, modname, sym.name, addr - data->start - sym.start_offs); if (symres == DRSYM_ERROR_LINE_NOT_AVAILABLE) { dr_fprintf(f, " ??:0\n"); } else { dr_fprintf(f, " %s:%"UINT64_FORMAT_CODE"+"PIFX"\n", sym.file, sym.line, sym.line_offs); } } else dr_fprintf(f, "%s "PFX" ? ??:0\n", prefix, addr); dr_free_module_data(data); }
static void dynamic_info_instrumentation(void *drcontext, instrlist_t *ilist, instr_t *where, instr_t * static_info) { /* issues that may arise 1. pc and eflags is uint but in 64 bit mode 8 byte transfers are done -> so far no problem (need to see this) need to see whether there is a better way 2. double check all the printing */ /* this function does the acutal instrumentation arguments - we get a filled pointer here about the operand types for a given instruction (srcs and dests) 1) increment the pointer to the instr_trace buffers 2) add this pointer to instr_trace_t wrapper 3) check whether any of the srcs and dests have memory operations; if so add a lea instruction and get the dynamic address Add this address to instr_trace_t structure 4) if the buffer is full call a function to dump it to the file and restore the head ptr of the buffer (lean function is used utilizing a code cache to limit code bloat needed for a clean call before every instruction.) */ instr_t *instr, *call, *restore, *first, *second; opnd_t ref, opnd1, opnd2; reg_id_t reg1 = DR_REG_XBX; /* We can optimize it by picking dead reg */ reg_id_t reg2 = DR_REG_XCX; /* reg2 must be ECX or RCX for jecxz */ reg_id_t reg3 = DR_REG_XAX; per_thread_t *data; uint pc; uint i; module_data_t * module_data; if (client_arg->instrace_mode == DISASSEMBLY_TRACE){ dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0); return; } data = drmgr_get_tls_field(drcontext, tls_index); /* Steal the register for memory reference address * * We can optimize away the unnecessary register save and restore * by analyzing the code and finding the register is dead. */ dr_save_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_save_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); dr_save_reg(drcontext, ilist, where, reg3, SPILL_SLOT_4); drmgr_insert_read_tls_field(drcontext, tls_index, ilist, where, reg2); /* Load data->buf_ptr into reg2 */ opnd1 = opnd_create_reg(reg2); opnd2 = OPND_CREATE_MEMPTR(reg2, offsetof(per_thread_t, buf_ptr)); instr = INSTR_CREATE_mov_ld(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* buf_ptr->static_info_instr = static_info; */ /* Move static_info to static_info_instr field of buf (which is a instr_trace_t *) */ opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, static_info_instr)); instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)static_info, opnd1, ilist, where, &first, &second); /* buf_ptr->num_mem = 0; */ opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, num_mem)); instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)0, opnd1, ilist, where, &first, &second); for (i = 0; i<instr_num_dsts(where); i++){ if (opnd_is_memory_reference(instr_get_dst(where, i))){ ref = instr_get_dst(where, i); DR_ASSERT(opnd_is_null(ref) == false); dr_restore_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_restore_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); #ifdef DEBUG_MEM_REGS dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0); dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0); #endif drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg1, reg2); #ifdef DEBUG_MEM_REGS dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0); #endif #ifdef DEBUG_MEM_STATS dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0); dr_insert_clean_call(drcontext, ilist, where, clean_call_mem_stats, false, 1, opnd_create_reg(reg1)); #endif dr_insert_clean_call(drcontext, ilist, where, clean_call_populate_mem, false, 3, opnd_create_reg(reg1), OPND_CREATE_INT32(i), OPND_CREATE_INT32(DST_TYPE)); } } for (i = 0; i<instr_num_srcs(where); i++){ if (opnd_is_memory_reference(instr_get_src(where, i))){ ref = instr_get_src(where, i); DR_ASSERT(opnd_is_null(ref) == false); dr_restore_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_restore_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); #ifdef DEBUG_MEM_REGS dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0); dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0); #endif drutil_insert_get_mem_addr(drcontext, ilist, where, ref, reg1, reg2); #ifdef DEBUG_MEM_REGS dr_insert_clean_call(drcontext, ilist, where, clean_call_print_regvalues, false, 0); #endif #ifdef DEBUG_MEM_STATS dr_insert_clean_call(drcontext, ilist, where, clean_call_disassembly_trace, false, 0); dr_insert_clean_call(drcontext, ilist, where, clean_call_mem_stats, false, 1, opnd_create_reg(reg1)); #endif dr_insert_clean_call(drcontext, ilist, where, clean_call_populate_mem, false, 3, opnd_create_reg(reg1), OPND_CREATE_INT32(i), OPND_CREATE_INT32(SRC_TYPE)); } } drmgr_insert_read_tls_field(drcontext, tls_index, ilist, where, reg2); /* Load data->buf_ptr into reg2 */ opnd1 = opnd_create_reg(reg2); opnd2 = OPND_CREATE_MEMPTR(reg2, offsetof(per_thread_t, buf_ptr)); instr = INSTR_CREATE_mov_ld(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* arithmetic flags are saved here for buf_ptr->eflags filling */ dr_save_arith_flags_to_xax(drcontext, ilist, where); /* load the eflags */ opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, eflags)); opnd2 = opnd_create_reg(reg3); instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* load the app_pc */ opnd1 = OPND_CREATE_MEMPTR(reg2, offsetof(instr_trace_t, pc)); module_data = dr_lookup_module(instr_get_app_pc(where)); //dynamically generated code - module information not available - then just store 0 at the pc slot of the instr_trace data if (module_data != NULL){ pc = instr_get_app_pc(where) - module_data->start; dr_free_module_data(module_data); } else{ pc = 0; } instrlist_insert_mov_immed_ptrsz(drcontext, (ptr_int_t)pc, opnd1, ilist, where, &first, &second); /* buf_ptr++; */ /* Increment reg value by pointer size using lea instr */ opnd1 = opnd_create_reg(reg2); opnd2 = opnd_create_base_disp(reg2, DR_REG_NULL, 0, sizeof(instr_trace_t), OPSZ_lea); instr = INSTR_CREATE_lea(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* Update the data->buf_ptr */ drmgr_insert_read_tls_field(drcontext, tls_index, ilist, where, reg1); opnd1 = OPND_CREATE_MEMPTR(reg1, offsetof(per_thread_t, buf_ptr)); opnd2 = opnd_create_reg(reg2); instr = INSTR_CREATE_mov_st(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* we use lea + jecxz trick for better performance * lea and jecxz won't disturb the eflags, so we won't insert * code to save and restore application's eflags. */ /* lea [reg2 - buf_end] => reg2 */ opnd1 = opnd_create_reg(reg1); opnd2 = OPND_CREATE_MEMPTR(reg1, offsetof(per_thread_t, buf_end)); instr = INSTR_CREATE_mov_ld(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); opnd1 = opnd_create_reg(reg2); opnd2 = opnd_create_base_disp(reg1, reg2, 1, 0, OPSZ_lea); instr = INSTR_CREATE_lea(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* jecxz call */ call = INSTR_CREATE_label(drcontext); opnd1 = opnd_create_instr(call); instr = INSTR_CREATE_jecxz(drcontext, opnd1); instrlist_meta_preinsert(ilist, where, instr); /* jump restore to skip clean call */ restore = INSTR_CREATE_label(drcontext); opnd1 = opnd_create_instr(restore); instr = INSTR_CREATE_jmp(drcontext, opnd1); instrlist_meta_preinsert(ilist, where, instr); /* clean call */ /* We jump to lean procedure which performs full context switch and * clean call invocation. This is to reduce the code cache size. */ instrlist_meta_preinsert(ilist, where, call); /* mov restore DR_REG_XCX */ opnd1 = opnd_create_reg(reg2); /* this is the return address for jumping back from lean procedure */ opnd2 = opnd_create_instr(restore); /* We could use instrlist_insert_mov_instr_addr(), but with a register * destination we know we can use a 64-bit immediate. */ instr = INSTR_CREATE_mov_imm(drcontext, opnd1, opnd2); instrlist_meta_preinsert(ilist, where, instr); /* jmp code_cache */ opnd1 = opnd_create_pc(code_cache); instr = INSTR_CREATE_jmp(drcontext, opnd1); instrlist_meta_preinsert(ilist, where, instr); /* restore %reg */ instrlist_meta_preinsert(ilist, where, restore); //dr_restore_arith_flags_from_xax(drcontext, ilist, where); dr_restore_reg(drcontext, ilist, where, reg1, SPILL_SLOT_2); dr_restore_reg(drcontext, ilist, where, reg2, SPILL_SLOT_3); dr_restore_reg(drcontext, ilist, where, reg3, SPILL_SLOT_4); //instrlist_disassemble(drcontext, instr_get_app_pc(instrlist_first(ilist)), ilist, logfile); }
static dr_emit_flags_t event_bb_analysis(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating, void **user_data) { instr_t *instr; uint num_instrs; #ifdef VERBOSE dr_printf("in dynamorio_basic_block(tag=" PFX ")\n", tag); # ifdef VERBOSE_VERBOSE instrlist_disassemble(drcontext, tag, bb, STDOUT); # endif #endif /* Only count in app BBs */ if (only_from_app.get_value()) { module_data_t *mod = dr_lookup_module(dr_fragment_app_pc(tag)); if (mod != NULL) { bool from_exe = (mod->start == exe_start); dr_free_module_data(mod); if (!from_exe) { *user_data = NULL; return DR_EMIT_DEFAULT; } } } /* Count instructions. If an emulation client is running with this client, * we want to count all the original native instructions and the emulated * instruction but NOT the introduced native instructions used for emulation. */ bool is_emulation = false; for (instr = instrlist_first(bb), num_instrs = 0; instr != NULL; instr = instr_get_next(instr)) { if (drmgr_is_emulation_start(instr)) { /* Each emulated instruction is replaced by a series of native * instructions delimited by labels indicating when the emulation * sequence begins and ends. It is the responsibility of the * emulation client to place the start/stop labels correctly. */ num_instrs++; is_emulation = true; /* Data about the emulated instruction can be extracted from the * start label using the accessor function: * drmgr_get_emulated_instr_data() */ continue; } if (drmgr_is_emulation_end(instr)) { is_emulation = false; continue; } if (is_emulation) continue; if (!instr_is_app(instr)) continue; num_instrs++; } *user_data = (void *)(ptr_uint_t)num_instrs; #if defined(VERBOSE) && defined(VERBOSE_VERBOSE) dr_printf("Finished counting for dynamorio_basic_block(tag=" PFX ")\n", tag); instrlist_disassemble(drcontext, tag, bb, STDOUT); #endif return DR_EMIT_DEFAULT; }