Example #1
0
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");
    }
}
Example #2
0
static void
check_cls_from_cache(void *cls_val)
{
    CHECK(cls_val == drmgr_get_cls_field(dr_get_current_drcontext(), cls_idx),
          "cls read from cache incorrect");
    checked_cls_from_cache = true;
}
Example #3
0
static void
event_post_syscall(void *drcontext, int sysnum)
{
    process_id_t child_pid = 0;
    per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, cls_idx);
    /* XXX i#752: should DR provide a child creation event that gives us the pid? */
#ifdef LINUX
    if (sysnum == SYS_fork ||
        (sysnum == SYS_clone && !TEST(CLONE_VM, data->saved_param))) {
        child_pid = dr_syscall_get_result(drcontext);
        if (child_pid > 0)
            nudge_child(child_pid);
    }
#else
    if (sysnum == sysnum_CreateProcess || sysnum == sysnum_CreateProcessEx ||
        sysnum == sysnum_CreateUserProcess) {
        if (dr_syscall_get_result(drcontext) >= 0) { /* success */
            HANDLE *hproc = (HANDLE) data->saved_param;
            HANDLE h;
            size_t read;
            if (dr_safe_read(hproc, sizeof(h), &h, &read) && read == sizeof(h))
                data->child_pid = dr_convert_handle_to_pid(h);
            /* we can't nudge now b/c the child's initial thread is suspended */
        }
    } else if (sysnum == sysnum_ResumeThread) {
        /* child should be alive now */
        if (data->child_pid != INVALID_PROCESS_ID)
            nudge_child(data->child_pid);
    }
#endif
}
Example #4
0
static bool
event_pre_syscall(void *drcontext, int sysnum)
{
#ifdef LINUX
    if (sysnum == SYS_clone) {
        per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, cls_idx);
        data->saved_param = dr_syscall_get_param(drcontext, 0);
    }
#else
    if (sysnum == sysnum_CreateProcess || sysnum == sysnum_CreateProcessEx ||
        sysnum == sysnum_CreateUserProcess) {
        per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, cls_idx);
        data->saved_param = dr_syscall_get_param(drcontext, 0);
    }
#endif
    return true;
}
Example #5
0
static void 
event_thread_context_exit(void *drcontext, bool thread_exit)
{
    if (thread_exit) {
        per_thread_t *data = (per_thread_t *) drmgr_get_cls_field(drcontext, cls_idx);
        dr_thread_free(drcontext, data, sizeof(per_thread_t));
    }
    /* else, nothing to do: we leave the struct for re-use on next context */
}
Example #6
0
static void
check_cls_write_from_cache(void)
{
    CHECK(drmgr_get_cls_field(dr_get_current_drcontext(), cls_idx) ==
          (void *) MAGIC_NUMBER_FROM_CACHE,
          "cls write from cache incorrect");
    /* now restore */
    drmgr_set_cls_field(dr_get_current_drcontext(), cls_idx,
                        (void *)(ptr_int_t)cb_depth);
    checked_cls_write_from_cache = true;
}
Example #7
0
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 */
}
Example #8
0
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);
        }
    }
}
Example #9
0
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));
}
Example #10
0
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");
    }
}
Example #11
0
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);
        }
    }
}
Example #12
0
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;
    if (new_depth) {
        data = (per_thread_t *) dr_thread_alloc(drcontext, sizeof(per_thread_t));
        drmgr_set_cls_field(drcontext, cls_idx, data);
    } else
        data = (per_thread_t *) drmgr_get_cls_field(drcontext, cls_idx);
    memset(data, 0, sizeof(*data));
    /* test self-nudge to make up for lack of nudge_test on windows (waiting
     * for runall support (i#120)
     */
    if (!sent_self) {
        sent_self = true;
        if (!dr_nudge_client(client_id, NUDGE_ARG_SELF))
            dr_fprintf(STDERR, "self nudge failed");
    }
}
Example #13
0
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 */
}
Example #14
0
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 */
}