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 */ }
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 */ }