static void kernel_xfer_event(void *drcontext, const dr_kernel_xfer_info_t *info) { /* Test kernel xfer on dr_redirect_execution */ dr_fprintf(STDERR, "%s: type %d\n", __FUNCTION__, info->type); ASSERT(info->source_mcontext != NULL); dr_mcontext_t mc = {sizeof(mc)}; mc.flags = DR_MC_CONTROL; bool ok = dr_get_mcontext(drcontext, &mc); ASSERT(ok); ASSERT(mc.pc == info->target_pc); ASSERT(mc.xsp == info->target_xsp); mc.flags = DR_MC_ALL; ok = dr_get_mcontext(drcontext, &mc); ASSERT(ok); }
static void at_not_taken(app_pc src, app_pc fall) { dr_mcontext_t mcontext = { sizeof(mcontext), DR_MC_ALL, }; void *drcontext = dr_get_current_drcontext(); /* * Record the fact that we've seen the fallthrough case. */ elem_t *elem = lookup(table, src); ASSERT(elem != NULL); elem->state |= CBR_NOT_TAKEN; dr_fprintf(STDERR, "cbr not taken\n"); /* * Remove the bb from the cache so it will be re-built the next * time it is executed. Since the flush will remove the fragment * we're already in, redirect execution to the target. */ dr_flush_region(src, 1); dr_get_mcontext(drcontext, &mcontext); mcontext.pc = fall; dr_redirect_execution(&mcontext); }
void memory_write(void *pc, void *prev_pc) { void *drcontext = dr_get_current_drcontext(); instr_t *instr = instr_create(drcontext); dr_mcontext_t mctx; opnd_t dst; ctx_t ctx; pc = dr_app_pc_for_decoding(pc); mctx.flags = DR_MC_CONTROL|DR_MC_INTEGER; mctx.size = sizeof(mctx); dr_get_mcontext(drcontext, &mctx); instr_init(drcontext, instr); if (!decode(drcontext, pc, instr)) { dr_printf("Decode of instruction at %p failed\n", pc); return; } ctx.addr = prev_pc; ctx.dr_addr = prev_pc; for (int i = 0; i < instr_num_dsts(instr); i++) { dst = instr_get_dst(instr, i); check_opnd(dst, pc, 0, drcontext, &mctx, &ctx); } instr_destroy(drcontext, instr); }
static void callback(void *tag, app_pc next_pc) { callback_count++; /* Flush all fragments containing this tag twice every hundred calls alternating * between a sync_all and delay flush (if available) and an unlink and delay flush * (if available). */ if (callback_count % 100 == 0) { if (callback_count % 200 == 0) { /* For windows test dr_flush_region() half the time */ dr_mcontext_t mcontext = {sizeof(mcontext),DR_MC_ALL,}; dr_delay_flush_region((app_pc)tag - 20, 30, callback_count, flush_event); dr_get_mcontext(dr_get_current_drcontext(), &mcontext); mcontext.pc = next_pc; dr_flush_region(tag, 1); dr_redirect_execution(&mcontext); *(volatile uint *)NULL = 0; /* ASSERT_NOT_REACHED() */ } else if (use_unlink) { /* Test dr_unlink_flush_region() half the time (if available). * FIXME - extend once we add unlink callback. */ delay_flush_at_next_build = true; dr_unlink_flush_region(tag, 1); } } }
static void at_taken(app_pc src, app_pc targ) { int app_errno; dr_mcontext_t mcontext; void *drcontext = dr_get_current_drcontext(); /* * Record the fact that we've seen the taken case. */ elem_t *elem = lookup(table, src); ASSERT(elem != NULL); elem->state |= CBR_TAKEN; dr_fprintf(STDERR, "cbr taken\n"); /* * Remove the bb from the cache so it will be re-built the next * time it is executed. Since the flush will remove the fragment * we're already in, redirect execution to the target. */ dr_flush_region(src, 1); dr_get_mcontext(drcontext, &mcontext, &app_errno); mcontext.xip = targ; dr_redirect_execution(&mcontext, app_errno); }
static void at_syscall() { if (monitoring) { dr_mcontext_t mcontext = {sizeof(mcontext),DR_MC_ALL,}; void *drcontext = dr_get_current_drcontext(); dr_get_mcontext(drcontext, &mcontext); dr_fprintf(STDERR, PFX"\n", mcontext.xax); } }
static void event_post_syscall(void *drcontext, int sysnum) { #ifdef SHOW_RESULTS dr_syscall_result_info_t info = { sizeof(info), }; dr_syscall_get_result_ex(drcontext, &info); if (!info.succeeded) { /* XXX: we could use the "drsyscall" Extension from the Dr. Memory * Framework (DRMF) to obtain the name of the system call (as well as * the number of arguments and the type of each). Please see the strace * sample and drstrace tool within DRMF for further information. */ dr_fprintf(STDERR, "<---- syscall %d failed (returned "PFX" == "SZFMT") ---->\n", sysnum, info.value, (ptr_int_t)info.value); } #endif if (sysnum == write_sysnum) { per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, tcls_idx); /* we repeat a write originally to stdout that we redirected to * stderr: on the repeat we use stdout */ if (data->repeat) { /* repeat syscall with stdout */ int i; #ifdef SHOW_RESULTS dr_fprintf(STDERR, "<---- repeating write ---->\n"); #endif dr_syscall_set_sysnum(drcontext, write_sysnum); dr_syscall_set_param(drcontext, 0, (reg_t) STDOUT); for (i = 1; i < SYS_MAX_ARGS; i++) dr_syscall_set_param(drcontext, i, data->param[i]); #ifdef WINDOWS if (dr_is_wow64()) { /* Set the xcx emulation parameter for wow64: since * we're executing the same system call again we can * use that same parameter. For new system calls we'd * need to determine the parameter from the ntdll * wrapper. */ dr_mcontext_t mc = {sizeof(mc),DR_MC_INTEGER/*only need xcx*/}; dr_get_mcontext(drcontext, &mc); mc.xcx = data->xcx; dr_set_mcontext(drcontext, &mc); } #endif dr_syscall_invoke_another(drcontext); } } }
static void at_call(app_pc instr_addr, app_pc target_addr) { file_t f = (file_t)(ptr_uint_t) dr_get_tls_field(dr_get_current_drcontext()); dr_mcontext_t mc = {sizeof(mc),DR_MC_CONTROL/*only need xsp*/}; dr_get_mcontext(dr_get_current_drcontext(), &mc); #ifdef SHOW_SYMBOLS print_address(f, instr_addr, "CALL @ "); print_address(f, target_addr, "\t to "); dr_fprintf(f, "\tTOS is "PFX"\n", mc.xsp); #else dr_fprintf(f, "CALL @ "PFX" to "PFX", TOS is "PFX"\n", instr_addr, target_addr, mc.xsp); #endif }
static void clean_call_print_regvalues(){ uint regvalue; dr_mcontext_t mc = { sizeof(mc), DR_MC_ALL }; void * drcontext = dr_get_current_drcontext(); dr_get_mcontext(drcontext, &mc); dr_printf("---------\n"); regvalue = reg_get_value(DR_REG_XAX, &mc); dr_printf("xax - %x\n", regvalue); regvalue = reg_get_value(DR_REG_XBX, &mc); dr_printf("xbx - %x\n", regvalue); regvalue = reg_get_value(DR_REG_XCX, &mc); dr_printf("xcx - %x\n", regvalue); regvalue = reg_get_value(DR_REG_XDX, &mc); dr_printf("xdx - %x\n", regvalue); }
static void clean_call(uint pc){ //DEBUG_PRINT("funcwrap - entered the pre-call clean call\n"); dr_mcontext_t mc = { sizeof(mc), DR_MC_ALL }; dr_get_mcontext(dr_get_current_drcontext(), &mc); mc.pc = pc; if (dumped == 0){ dumped = 1; dr_flush_region(0, ~((ptr_uint_t)0)); dr_redirect_execution(&mc); } //DEBUG_PRINT("funcwrap - entered the pre-call done\n"); }
static void event_post_syscall(void *drcontext, int sysnum) { #ifdef SHOW_RESULTS dr_fprintf(STDERR, " [%d] => "PFX" ("SZFMT")\n", sysnum, dr_syscall_get_result(drcontext), (ptr_int_t)dr_syscall_get_result(drcontext)); #endif if (sysnum == write_sysnum) { per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, tcls_idx); /* we repeat a write originally to stdout that we redirected to * stderr: on the repeat we use stdout */ if (data->repeat) { /* repeat syscall with stdout */ int i; #ifdef SHOW_RESULTS dr_fprintf(STDERR, " [%d] => repeating\n", sysnum); #endif dr_syscall_set_sysnum(drcontext, write_sysnum); dr_syscall_set_param(drcontext, 0, (reg_t) STDOUT); for (i = 1; i < SYS_MAX_ARGS; i++) dr_syscall_set_param(drcontext, i, data->param[i]); #ifdef WINDOWS if (dr_is_wow64()) { /* Set the xcx emulation parameter for wow64: since * we're executing the same system call again we can * use that same parameter. For new system calls we'd * need to determine the parameter from the ntdll * wrapper. */ dr_mcontext_t mc = {sizeof(mc),DR_MC_INTEGER/*only need xcx*/}; dr_get_mcontext(drcontext, &mc); mc.xcx = data->xcx; dr_set_mcontext(drcontext, &mc); } #endif dr_syscall_invoke_another(drcontext); } } }
static void check_mcontext(void *drcontext) { dr_mcontext_t *mc; dr_mcontext_t mc_DR; if (drsys_get_mcontext(drcontext, &mc) != DRMF_SUCCESS) ASSERT(false, "drsys_get_mcontext failed"); mc_DR.size = sizeof(mc_DR); mc_DR.flags = DR_MC_INTEGER|DR_MC_CONTROL; dr_get_mcontext(drcontext, &mc_DR); ASSERT(mc->IF_ARM_ELSE(r7,xdi) == mc_DR.IF_ARM_ELSE(r7,xdi), "mc check"); ASSERT(mc->IF_ARM_ELSE(r6,xsi) == mc_DR.IF_ARM_ELSE(r6,xsi), "mc check"); ASSERT(mc->IF_ARM_ELSE(r5,xbp) == mc_DR.IF_ARM_ELSE(r5,xbp), "mc check"); ASSERT(mc->IF_ARM_ELSE(r4,xsp) == mc_DR.IF_ARM_ELSE(r4,xsp), "mc check"); ASSERT(mc->IF_ARM_ELSE(r3,xbx) == mc_DR.IF_ARM_ELSE(r3,xbx), "mc check"); ASSERT(mc->IF_ARM_ELSE(r2,xdx) == mc_DR.IF_ARM_ELSE(r2,xdx), "mc check"); ASSERT(mc->IF_ARM_ELSE(r1,xcx) == mc_DR.IF_ARM_ELSE(r1,xcx), "mc check"); ASSERT(mc->IF_ARM_ELSE(r0,xax) == mc_DR.IF_ARM_ELSE(r0,xax), "mc check"); ASSERT(mc->xflags == mc_DR.xflags, "mc check"); }
/* Clean call for the 'taken' case */ static void at_taken(app_pc src, app_pc targ) { dr_mcontext_t mcontext = {sizeof(mcontext),DR_MC_ALL,}; void *drcontext = dr_get_current_drcontext(); /* * Record the fact that we've seen the taken case. */ elem_t *elem = lookup(table, src); ASSERT(elem != NULL); elem->state |= CBR_TAKEN; /* Remove the bb from the cache so it will be re-built the next * time it executes. */ /* Since the flush will remove the fragment we're already in, * redirect execution to the target address. */ dr_flush_region(src, 1); dr_get_mcontext(drcontext, &mcontext); mcontext.pc = targ; dr_redirect_execution(&mcontext); }
static void getRegReg(reg_id_t r1, reg_id_t r2, int opcode, app_pc addr){ const char * r1Name = get_register_name(r1); const char * r2Name = get_register_name(r2); int s1 = atoi(r1Name + 3 * sizeof(char)); int s2 = atoi(r2Name + 3 * sizeof(char)); dr_mcontext_t mcontext; memset(&mcontext, 0, sizeof(dr_mcontext_t)); mcontext.flags = DR_MC_MULTIMEDIA; mcontext.size = sizeof(dr_mcontext_t); bool result = dr_get_mcontext(dr_get_current_drcontext(), &mcontext); int r, s; int bits = 0; double loss = 0; double lossD = 0; if(is_single_precision_instr(opcode)){ float op1, op2; // for(r=0; r<16; ++r) // for(s=0; s<4; ++s) // printf("reg %i.%i: %f\n", r, s, // *((float*) &mcontext.ymm[r].u32[s])); op1 = *((float*) &mcontext.ymm[s1].u32[0]); op2 = *((float*) &mcontext.ymm[s2].u32[0]); // dr_fprintf(logF, "%d: %f %f\n",opcode, op1, op2); int exp1, exp2; float mant1, mant2; mant1 = frexpf(op1, &exp1); mant2 = frexpf(op2, &exp2); bits = abs(exp1-exp2); double dop1 = op1; double dop2 = op2; if(opcode == OP_addss){ double dadd = dop1 + dop2; float fadd = op1 + op2; lossD = dadd - fadd; // printf("double %.13lf float %.13f\n", dadd, fadd); } else{ double dsub = dop1 - dop2; float fsub = op1 - op2; lossD = dsub - fsub; } // printf("diff of double and float is %.13lf\n", lossD); } else{ double op1, op2; // for(r=0; r<16; ++r) // for(s=0; s<2; ++s) // printf("reg %i.%i: %f\n", r, s, // *((double*) &mcontext.ymm[r].u64[s])); op1 = *((double*) &mcontext.ymm[s1].u64[0]); op2 = *((double*) &mcontext.ymm[s2].u64[0]); // dr_fprintf(logF, "%d: %.13lf %.13lf\n",opcode, op1, op2); int exp1, exp2; double mant1, mant2; mant1 = frexp(op1, &exp1); mant2 = frexp(op2, &exp2); bits = abs(exp1-exp2); printf("op1 %.13lf mantissa %.13lf exp %d\n", op1, mant1, exp1); printf("op2 %.13lf mantissa %.13lf exp %d\n", op2, mant2, exp2); } print_address(addr, bits, loss, lossD); }
static void callback(reg_id_t reg, int displacement, reg_id_t destReg, int opcode, app_pc addr){ int r, s; const char * destRegName = get_register_name(destReg); int regId = atoi(destRegName + 3 * sizeof(char)); dr_mcontext_t mcontext; memset(&mcontext, 0, sizeof(dr_mcontext_t)); mcontext.flags = DR_MC_ALL; mcontext.size = sizeof(dr_mcontext_t); bool result = dr_get_mcontext(dr_get_current_drcontext(), &mcontext); reg_t mem_reg; if(reg == DR_REG_RAX) mem_reg = mcontext.rax; else if(reg == DR_REG_RBP) mem_reg = mcontext.rbp; else if(reg == DR_REG_RBX) mem_reg = mcontext.rbx; else if(reg == DR_REG_RCX) mem_reg = mcontext.rcx; else if(reg == DR_REG_RDI) mem_reg = mcontext.rdi; else if(reg == DR_REG_RDX) mem_reg = mcontext.rdx; else if(reg == DR_REG_RSI) mem_reg = mcontext.rsi; else if(reg == DR_REG_RSP) mem_reg = mcontext.rsp; else mem_reg = NULL; //deal with a null case, rip enum doesn't exist int bits = 0; double loss = 0; double lossD = 0; if(is_single_precision_instr(opcode)){ float op1, op2; // printf("Mem reg contents: %f\n", *(float*)(mem_reg + displacement)); op2 = *(float*)(mem_reg + displacement); // for(r=0; r<16; ++r) // for(s=0; s<4; ++s) // printf("reg %i.%i: %f\n", r, s, // *((float*) &mcontext.ymm[r].u32[s])); op1 = *((float*) &mcontext.ymm[regId].u32[0]); // dr_fprintf(logF, "%d: %f %f\n",opcode, op1, op2); int exp1, exp2; float mant1, mant2; mant1 = frexpf(op1, &exp1); mant2 = frexpf(op2, &exp2); bits = abs(exp1-exp2); double dop1 = op1; double dop2 = op2; if(opcode == OP_addss){ double dadd = dop1 + dop2; float fadd = op1 + op2; lossD = dadd - fadd; //printf("double %.13lf float %.13f\n", dadd, fadd); } else{ double dsub = dop1 - dop2; float fsub = op1 - op2; lossD = dsub - fsub; } // printf("diff of double and float is %.13lf\n", lossD); } else{ double op1, op2; printf("Mem reg contents: %.13lf\n", *(double*)(mem_reg + displacement)); op2 = *(double*)(mem_reg + displacement); // for(r=0; r<16; ++r) // for(s=0; s<2; ++s) // printf("reg %i.%i: %lf\n", r, s, // *((double*) &mcontext.ymm[r].u64[s])); op1 = *((double*) &mcontext.ymm[regId].u64[0]); // dr_fprintf(logF, "%d: %.13lf %.13lf\n",opcode, op1, op2); int exp1, exp2; double mant1, mant2; mant1 = frexp(op1, &exp1); mant2 = frexp(op2, &exp2); bits = abs(exp1-exp2); printf("op1 %.13lf mantissa %.13lf exp %d\n", op1, mant1, exp1); printf("op2 %.13lf mantissa %.13lf exp %d\n", op2, mant2, exp2); } print_address(addr, bits, loss, lossD); }
static bool event_pre_syscall(void *drcontext, int sysnum) { ATOMIC_INC(num_syscalls); #ifdef LINUX if (sysnum == SYS_execve) { /* our stats will be re-set post-execve so display now */ show_results(); # ifdef SHOW_RESULTS dr_fprintf(STDERR, "<---- execve ---->\n"); # endif } #endif #ifdef SHOW_RESULTS dr_fprintf(STDERR, "[%d] "PFX" "PFX" "PFX"\n", sysnum, dr_syscall_get_param(drcontext, 0), dr_syscall_get_param(drcontext, 1), dr_syscall_get_param(drcontext, 2)); #endif if (sysnum == write_sysnum) { /* store params for access post-syscall */ int i; per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, tcls_idx); #ifdef WINDOWS /* stderr and stdout are identical in our cygwin rxvt shell so for * our example we suppress output starting with 'H' instead */ byte *output = (byte *) dr_syscall_get_param(drcontext, 5); byte first; size_t read; bool ok = dr_safe_read(output, 1, &first, &read); if (!ok || read != 1) return true; /* data unreadable: execute normally */ if (dr_is_wow64()) { /* store the xcx emulation parameter for wow64 */ dr_mcontext_t mc = {sizeof(mc),DR_MC_INTEGER/*only need xcx*/}; dr_get_mcontext(drcontext, &mc); data->xcx = mc.xcx; } #endif for (i = 0; i < SYS_MAX_ARGS; i++) data->param[i] = dr_syscall_get_param(drcontext, i); /* suppress stderr */ if (dr_syscall_get_param(drcontext, 0) == (reg_t) STDERR #ifdef WINDOWS && first == 'H' #endif ) { /* pretend it succeeded */ #ifdef LINUX /* return the #bytes == 3rd param */ dr_syscall_set_result(drcontext, dr_syscall_get_param(drcontext, 2)); #else /* we should also set the IO_STATUS_BLOCK.Information field */ dr_syscall_set_result(drcontext, 0); #endif #ifdef SHOW_RESULTS dr_fprintf(STDERR, " [%d] => skipped\n", sysnum); #endif return false; /* skip syscall */ } else if (dr_syscall_get_param(drcontext, 0) == (reg_t) STDOUT) { if (!data->repeat) { /* redirect stdout to stderr (unless it's our repeat) */ #ifdef SHOW_RESULTS dr_fprintf(STDERR, " [%d] STDOUT => STDERR\n", sysnum); #endif dr_syscall_set_param(drcontext, 0, (reg_t) STDERR); } /* we're going to repeat this syscall once */ data->repeat = !data->repeat; } } return true; /* execute normally */ }
static bool event_pre_syscall(void *drcontext, int sysnum) { bool modify_write = (sysnum == write_sysnum); dr_atomic_add32_return_sum(&num_syscalls, 1); #ifdef UNIX if (sysnum == SYS_execve) { /* our stats will be re-set post-execve so display now */ show_results(); # ifdef SHOW_RESULTS dr_fprintf(STDERR, "<---- execve ---->\n"); # endif } #endif #ifndef SHOW_RESULTS /* for sanity tests that don't show results we don't change the app's output */ modify_write = false; #endif if (modify_write) { /* store params for access post-syscall */ int i; per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, tcls_idx); #ifdef WINDOWS /* stderr and stdout are identical in our cygwin rxvt shell so for * our example we suppress output starting with 'H' instead */ byte *output = (byte *) dr_syscall_get_param(drcontext, 5); byte first; size_t read; bool ok = dr_safe_read(output, 1, &first, &read); if (!ok || read != 1) return true; /* data unreadable: execute normally */ if (dr_is_wow64()) { /* store the xcx emulation parameter for wow64 */ dr_mcontext_t mc = {sizeof(mc),DR_MC_INTEGER/*only need xcx*/}; dr_get_mcontext(drcontext, &mc); data->xcx = mc.xcx; } #endif for (i = 0; i < SYS_MAX_ARGS; i++) data->param[i] = dr_syscall_get_param(drcontext, i); /* suppress stderr */ if (dr_syscall_get_param(drcontext, 0) == (reg_t) STDERR #ifdef WINDOWS && first == 'H' #endif ) { /* pretend it succeeded */ #ifdef UNIX /* return the #bytes == 3rd param */ dr_syscall_result_info_t info = { sizeof(info), }; info.succeeded = true; info.value = dr_syscall_get_param(drcontext, 2); dr_syscall_set_result_ex(drcontext, &info); #else /* XXX: we should also set the IO_STATUS_BLOCK.Information field */ dr_syscall_set_result(drcontext, 0); #endif #ifdef SHOW_RESULTS dr_fprintf(STDERR, "<---- skipping write to stderr ---->\n"); #endif return false; /* skip syscall */ } else if (dr_syscall_get_param(drcontext, 0) == (reg_t) STDOUT) { if (!data->repeat) { /* redirect stdout to stderr (unless it's our repeat) */ #ifdef SHOW_RESULTS dr_fprintf(STDERR, "<---- changing stdout to stderr ---->\n"); #endif dr_syscall_set_param(drcontext, 0, (reg_t) STDERR); } /* we're going to repeat this syscall once */ data->repeat = !data->repeat; } } return true; /* execute normally */ }