示例#1
0
/* Procedure executed by sideline threads.
 * XXX i#500: Cannot use libc routines (printf) in the child process.
 */
int run(void *arg)
{
    int threadnum = (int)(long) arg;
    int i = 0;
    /* for CLONE_CHILD_CLEARTID for signaling parent.  if we used raw
     * clone system call we could get kernel to do this for us.
     */
    child[threadnum] = dynamorio_syscall(SYS_gettid, 0);
    dynamorio_syscall(SYS_set_tid_address, 1, &child[threadnum]);
    child_started[threadnum] = true;
    nolibc_print("Sideline thread started\n");
    while (true) {
        /* do nothing for now */
        i++;
        if (i % 25000000 == 0)
            break;
    }
    while (!child_exit[threadnum])
        nolibc_nanosleep(&sleeptime);
    nolibc_print("Sideline thread finished, exiting whole group\n");
    /* We deliberately bring down the whole group.  Note that this is
     * the default on x64 on returning for some reason which seems
     * like a bug in _clone() (xref i#94).
     */
    dynamorio_syscall(SYS_exit_group, 0);
    return 0;
}
示例#2
0
/* Procedure executed by sideline threads
 * XXX i#500: Cannot use libc routines (printf) in the child process.
 */
int run(void *arg)
{
    int i = 0;
    /* for CLONE_CHILD_CLEARTID for signaling parent.  if we used raw
     * clone system call we could get kernel to do this for us. 
     */
    child = nolibc_syscall(SYS_gettid, 0);
    nolibc_syscall(SYS_set_tid_address, 1, &child);
    nolibc_print("Sideline thread started\n");
    while (true) {
        /* do nothing for now */
        i++;
        if (i % 2500000 == 0) {
            nolibc_print("i = ");
            nolibc_print_int(i);
            nolibc_print("\n");
        }
        if (i % 25000000 == 0)
            break;
    }
    while (!child_exit)
        nanosleep(&sleeptime, NULL);
    nolibc_print("Sideline thread finished\n");
    child_done = true;
#ifdef X64
    /* FIXME: returning here invokes SYS_exit_group and takes down the
     * parent...what's up with that?  Xref i#94.
     */
    nolibc_syscall(SYS_exit, 0);
#endif
    return 0;
}
示例#3
0
/* allocate stack storage on the app's heap */
static void *
stack_alloc(int size)
{
    size_t sp;
    void *q = NULL;
    void *p;

#if STACK_OVERFLOW_PROTECT
    /* allocate an extra page and mark it non-accessible to trap stack overflow */
    q = nolibc_mmap(0, PAGE_SIZE, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
    if (q == NULL || q == MAP_FAILED)
        nolibc_print("mmap failed\n");
    stack_redzone_start = (size_t) q;
#endif

    p = nolibc_mmap(q, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
    if (p == NULL || p == MAP_FAILED)
        nolibc_print("mmap failed\n");
#ifdef DEBUG
    nolibc_memset(p, 0xab, size);
#endif

    /* stack grows from high to low addresses, so return a ptr to the top of the
       allocated region */
    sp = (size_t)p + size;

    return (void*) sp;
}
示例#4
0
文件: tools.c 项目: Safe3/dynamorio
/* Safe print int syscall.
 */
void
nolibc_print_int(int n)
{
    char buf[12];  /* 2 ** 31 has 10 digits, plus sign and nul. */
    int i = 0;
    int m;
    int len;

    /* Sign. */
    if (n < 0) {
        buf[i++] = '-';
        n = -n;
    }

    /* Go forward by the number of digits we'll need. */
    m = n;
    while (m > 0) {
        m /= 10;
        i++;
    }
    len = i;
    assert(len <= sizeof(buf));

    /* Go backward for each digit. */
    while (n > 0) {
        buf[--i] = '0' + (n % 10);
        n /= 10;
    }

    buf[len] = '\0';

    nolibc_print(buf);
}
示例#5
0
static void 
delete_thread(pid_t pid, void *stack)
{
    pid_t result;
    /* do not print out pids to make diff easy */
    nolibc_print("Waiting for child to exit\n");
    result = waitpid(pid, NULL, 0);
    nolibc_print("Child has exited\n");
    if (result == -1 || result != pid) {
        /* somehow getting errors: ignoring for now since works */
#if VERBOSE
	perror("delete_thread waitpid");
#endif
    }
    stack_free(stack, THREAD_STACK_SIZE);
}
示例#6
0
/* Create a new thread. It should be passed "fcn", a function which
 * takes two arguments, (the second one is a dummy, always 4). The
 * first argument is passed in "arg". Returns the TID of the new
 * thread */
static pid_t
create_thread(int (*fcn)(void *), void *arg, void **stack, bool same_group)
{
    pid_t newpid;
    int flags;
    void *my_stack;

    my_stack = stack_alloc(THREAD_STACK_SIZE);
    /* need SIGCHLD so parent will get that signal when child dies,
     * else have errors doing a wait */
    flags = SIGCHLD | CLONE_VM |
        /* CLONE_THREAD => no signal to parent on termination; have to use
         * CLONE_CHILD_CLEARTID to get that.  Since we're using library call
         * instead of raw system call we don't have child_tidptr argument,
         * so we set the location in the child itself via set_tid_address(). */
        CLONE_CHILD_CLEARTID | CLONE_FS | CLONE_FILES | CLONE_SIGHAND;
    if (same_group)
        flags |= CLONE_THREAD;
    /* XXX: Using libc clone in the child here really worries me, but it seems
     * to work.  My theory is that the parent has to call clone, which invokes
     * the loader to fill in the PLT entry, so when the child calls clone it
     * doesn't go into the loader and avoiding the races like we saw in i#500.
     */
    newpid = clone(fcn, my_stack, flags, arg);
    /* this is really a tid if we passed CLONE_THREAD: child has same pid as us */

    if (newpid == -1) {
        nolibc_print("smp.c: Error calling clone\n");
        stack_free(my_stack, THREAD_STACK_SIZE);
        return -1;
    }

    *stack = my_stack;
    return newpid;
}
示例#7
0
/* Procedure executed by sideline threads
 * XXX i#500: Cannot use libc routines (printf) in the child process.
 */
int run(void *arg)
{
    int i = 0;
    nolibc_print("Sideline thread started\n");
    while (true) {
        /* do nothing for now */
        i++;
        if (i % 2500000 == 0) {
            nolibc_print("i = ");
            nolibc_print_int(i);
            nolibc_print("\n");
        }
        if (i % 25000000 == 0)
            break;
    }
    while (!child_exit)
        nolibc_nanosleep(&sleeptime);
    nolibc_print("Sideline thread finished\n");
    child_done = true;
    return 0;
}
示例#8
0
/* Procedure executed by sideline threads
 * XXX i#500: Cannot use libc routines (printf) in the child process.
 */
int run(void *arg)
{
    int threadnum = (int)(long) arg;
    int i = 0;
    /* for CLONE_CHILD_CLEARTID for signaling parent.  if we used raw
     * clone system call we could get kernel to do this for us. 
     */
    child[threadnum] = nolibc_syscall(SYS_gettid, 0);
    nolibc_syscall(SYS_set_tid_address, 1, &child[threadnum]);

    if (threadnum == 0) {
        /* first child creates rest of group */
        int j;
        for (j = 1; j < NUM_THREADS; j++) {
            child[j] = create_thread(run, (void *)(long)j, &stack[j], true);
            if (child[j] < 0)
                nolibc_print("failed to create child thread\n");
        }
    }

    child_started[threadnum] = true;
    nolibc_print("Sideline thread started\n");

    while (true) {
        /* do nothing for now */
        i++;
        if (i % 25000000 == 0)
            break;
    }
    while (!child_exit[threadnum])
        nolibc_nanosleep(&sleeptime);
    nolibc_print("Sideline thread finished, exiting whole group\n");
    child_done[threadnum] = true;
    /* We deliberately bring down the whole group.  Note that this is
     * the default on x64 on returning for some reason which seems
     * like a bug in _clone() (xref i#94).
     */
    nolibc_syscall(SYS_exit_group, 0);
    return 0;
}