/* for tasks unrelated to shadowing that are common to all tools */ void os_shared_post_syscall(void *drcontext, cls_syscall_t *pt, drsys_sysnum_t sysnum, dr_mcontext_t *mc, drsys_syscall_t *syscall) { switch (sysnum.number) { case SYS_clone: { uint flags = (uint) syscall_get_param(drcontext, 0); if (TEST(CLONE_VM, flags)) { thread_id_t child = dr_syscall_get_result(drcontext); report_child_thread(drcontext, child); break; } /* else, fall through */ } case SYS_fork: { #ifndef USE_DRSYMS /* PR 453867: tell postprocess.pl to not exit until it sees a message * from the child starting up. */ process_id_t child = dr_syscall_get_result(drcontext); if (child != 0) ELOGF(0, f_fork, "FORK child=%d\n", child); #endif break; } } }
/* Caller should check for success and only call if syscall is successful (for !pre) */ static void syscall_check_gdi(bool pre, void *drcontext, drsys_sysnum_t sysnum, cls_syscall_t *pt, dr_mcontext_t *mc) { app_loc_t loc; ASSERT(options.check_gdi, "shouldn't be called"); if (drsys_sysnums_equal(&sysnum, &sysnum_UserGetDC) || drsys_sysnums_equal(&sysnum, &sysnum_UserGetDCEx) || drsys_sysnums_equal(&sysnum, &sysnum_UserGetWindowDC) || drsys_sysnums_equal(&sysnum, &sysnum_UserBeginPaint) || drsys_sysnums_equal(&sysnum, &sysnum_GdiGetDCforBitmap) || drsys_sysnums_equal(&sysnum, &sysnum_GdiDdGetDC)) { if (!pre) { HDC hdc = (HDC) dr_syscall_get_result(drcontext); /* i#1192: NtGdiGetDCforBitmap does not allocate a new DC * that needs to be freed. We leave it enabled as an * "allocation" to have more DC's in our table (presumably * adding in those created before we took over). */ uint flags = 0; if (!drsys_sysnums_equal(&sysnum, &sysnum_GdiGetDCforBitmap)) flags |= GDI_DC_ALLOC_GET; syscall_to_loc(&loc, sysnum, ""); gdicheck_dc_alloc(hdc, flags, sysnum, mc, &loc); if (drsys_sysnums_equal(&sysnum, &sysnum_UserBeginPaint)) { /* we store the hdc for access in EndPaint */ pt->paintDC = hdc; } } } else if (drsys_sysnums_equal(&sysnum, &sysnum_GdiCreateMetafileDC) || drsys_sysnums_equal(&sysnum, &sysnum_GdiCreateCompatibleDC) || drsys_sysnums_equal(&sysnum, &sysnum_GdiOpenDCW)) { if (!pre) { HDC hdc = (HDC) dr_syscall_get_result(drcontext); uint flags = GDI_DC_ALLOC_CREATE; if (drsys_sysnums_equal(&sysnum, &sysnum_GdiCreateCompatibleDC) && syscall_get_param(drcontext, 0) == 0) flags |= GDI_DC_ALLOC_DUP_NULL; syscall_to_loc(&loc, sysnum, ""); gdicheck_dc_alloc(hdc, flags, sysnum, mc, &loc); } } else if (drsys_sysnums_equal(&sysnum, &sysnum_UserReleaseDC) || drsys_sysnums_equal(&sysnum, &sysnum_UserEndPaint)) { if (pre) { HDC hdc; if (drsys_sysnums_equal(&sysnum, &sysnum_UserReleaseDC)) hdc = (HDC)syscall_get_param(drcontext, 0); else { hdc = pt->paintDC; pt->paintDC = NULL; } gdicheck_dc_free(hdc, false/*Get not Create*/, sysnum, mc); } } else if (drsys_sysnums_equal(&sysnum, &sysnum_GdiDeleteObjectApp)) { if (pre) gdicheck_obj_free((HANDLE)syscall_get_param(drcontext, 0), sysnum, mc); } }
static void event_post_syscall(void *drcontext, int sysnum) { unsigned long ret; per_thread_t *data = drmgr_get_tls_field(drcontext, tls_index); // dr_fprintf(STDERR, "post sysnum %d\n", sysnum); switch (sysnum) { case BRK_SYSCALL : ret = dr_syscall_get_result(drcontext); if (!data->param[0]) { global_range.upper = ret; global_range.upper_addr = (void *)ret; heap_range.lower = ret; heap_range.lower_addr = (void *)ret; } else { heap_range.upper = ret; heap_range.upper_addr = (void *)ret; markAlloc(heap_range.lower, heap_range.upper - heap_range.lower); } // dr_printf("brk %u ret %x\n", data->param[0], ret); // dr_fprintf(STDERR, " ret %x\n", ret); break; case MMAP_SYSCALL : ret = dr_syscall_get_result(drcontext); // dr_printf("mmap %u %x\n", data->param[1], ret); // dr_fprintf(STDERR, " ret %x\n", ret); markAlloc(ret, data->param[1]); break; case MUNMAP_SYSCALL : // dr_printf("unmap %x %u\n", data->param[0], data->param[1]); ret = dr_syscall_get_result(drcontext); // dr_fprintf(STDERR, "ret %u\n", ret); unmarkAlloc(data->param[0], data->param[1]); break; } }
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 event_post_syscall(void *drcontext, int sysnum) { drsys_syscall_t *syscall; bool success = false; if (drsys_cur_syscall(drcontext, &syscall) != DRMF_SUCCESS) ASSERT(false, "drsys_cur_syscall failed"); if (drsys_syscall_succeeded(syscall, dr_syscall_get_result(drcontext), &success) != DRMF_SUCCESS) ASSERT(false, "drsys_syscall_succeeded failed"); OUTPUT(" %s =>\n", success ? "succeeded" : "failed"); if (drsys_iterate_args(drcontext, drsys_iter_arg_cb, NULL) != DRMF_SUCCESS) ASSERT(false, "drsys_iterate_args failed"); }
static bool drsys_iter_arg_cb(drsys_arg_t *arg, void *user_data) { ptr_uint_t val; uint64 val64; ASSERT(arg->valid, "no args should be invalid in this app"); ASSERT(arg->mc != NULL, "mc check"); ASSERT(arg->drcontext == dr_get_current_drcontext(), "dc check"); if (arg->reg == DR_REG_NULL && !TEST(DRSYS_PARAM_RETVAL, arg->mode)) { ASSERT((byte *)arg->start_addr >= (byte *)arg->mc->xsp && (byte *)arg->start_addr < (byte *)arg->mc->xsp + PAGE_SIZE, "mem args should be on stack"); } if (TEST(DRSYS_PARAM_RETVAL, arg->mode)) { ASSERT(arg->pre || arg->value == dr_syscall_get_result(dr_get_current_drcontext()), "return val wrong"); } else { if (drsys_pre_syscall_arg(arg->drcontext, arg->ordinal, &val) != DRMF_SUCCESS) ASSERT(false, "drsys_pre_syscall_arg failed"); if (drsys_pre_syscall_arg64(arg->drcontext, arg->ordinal, &val64) != DRMF_SUCCESS) ASSERT(false, "drsys_pre_syscall_arg64 failed"); if (arg->size < sizeof(val)) { val = truncate_int_to_size(val, arg->size); val64 = truncate_int_to_size(val64, arg->size); } ASSERT(val == arg->value, "values do not match"); ASSERT(val64 == arg->value64, "values do not match"); } /* We could test drsys_handle_is_current_process() but we'd have to * locate syscalls operating on processes. Currently drsyscall.c * already tests this call. */ return true; /* keep going */ }
static void post_open(void *drcontext) { int fd; struct per_thread_journal_state *jstate; jstate = (struct per_thread_journal_state *) drmgr_get_tls_field(drcontext, tls_idx); if (jstate->state == THREAD_STATE_DEFAULT) return; fd = (int)dr_syscall_get_result(drcontext); if (jstate->state == THREAD_STATE_OPENING_JFILE_0) { fi_printf("fd of jfile0: %d\n", fd); jfile_fds[0] = fd; } else if (jstate->state == THREAD_STATE_OPENING_JFILE_1) { fi_printf("fd of jfile1: %d\n", fd); jfile_fds[1] = fd; } jstate->state = THREAD_STATE_DEFAULT; }