Пример #1
0
DLLEXPORT int julia_trampoline(int argc, char **argv, int (*pmain)(int ac,char *av[]))
{
#if defined(_WIN32) //&& !defined(_WIN64)
    SetUnhandledExceptionFilter(exception_handler);
#endif
    unsigned char * p = (unsigned char *) &__stack_chk_guard;
    char a = p[sizeof(__stack_chk_guard)-1];
    char b = p[sizeof(__stack_chk_guard)-2];
    char c = p[0];
    /* If you have the ability to generate random numbers in your kernel then use them */
    p[sizeof(__stack_chk_guard)-1] = 255;
    p[sizeof(__stack_chk_guard)-2] = '\n';
    p[0] = 0;
#ifdef COPY_STACKS
    // initialize base context of root task
    jl_root_task->stackbase = (char*)&argc;
    if (jl_setjmp(jl_root_task->base_ctx, 0)) {
        jl_switch_stack(jl_current_task, jl_jmp_target);
    }
#endif
    int ret = pmain(argc, argv);
    p[sizeof(__stack_chk_guard)-1] = a;
    p[sizeof(__stack_chk_guard)-2] = b;
    p[0] = c;
    return ret;
}
Пример #2
0
static jl_value_t *eval_body(jl_array_t *stmts, jl_value_t **locals, size_t nl,
                             int start)
{
    jl_savestate_t __ss;
    jl_jmp_buf __handlr;
    size_t i=start;
    while (1) {
        jl_value_t *stmt = jl_cellref(stmts,i);
        if (jl_is_gotonode(stmt)) {
            i = label_idx(jl_fieldref(stmt,0), stmts);
            continue;
        }
        if (jl_is_expr(stmt)) {
            jl_sym_t *head = ((jl_expr_t*)stmt)->head;
            if (head == goto_ifnot_sym) {
                jl_value_t *cond = eval(jl_exprarg(stmt,0), locals, nl);
                if (cond == jl_false) {
                    i = label_idx(jl_exprarg(stmt,1), stmts);
                    continue;
                }
                else if (cond != jl_true) {
                    jl_type_error_rt("toplevel", "if",
                                     (jl_value_t*)jl_bool_type, cond);
                }
            }
            else if (head == return_sym) {
                return eval(jl_exprarg(stmt,0), locals, nl);
            }
            else if (head == enter_sym) {
                jl_enter_handler(&__ss, &__handlr);
                if (!jl_setjmp(__handlr,1)) {
                    return eval_body(stmts, locals, nl, i+1);
                }
                else {
                    i = label_idx(jl_exprarg(stmt,0), stmts);
                    continue;
                }
            }
            else if (head == leave_sym) {
                int hand_n_leave = jl_unbox_long(jl_exprarg(stmt,0));
                jl_pop_handler(hand_n_leave);
            }
            else {
                eval(stmt, locals, nl);
            }
        }
        else {
            eval(stmt, locals, nl);
        }
        i++;
    }
    assert(0);
    return NULL;
}
Пример #3
0
DLLEXPORT
int julia_trampoline(int argc, char *argv[], int (*pmain)(int ac,char *av[]))
{
#ifdef COPY_STACKS
    // initialize base context of root task
    jl_root_task->stackbase = (char*)&argc;
    if (jl_setjmp(jl_root_task->base_ctx, 1)) {
        jl_switch_stack(jl_current_task, jl_jmp_target);
    }
#endif
    return pmain(argc, argv);
}
Пример #4
0
JL_DLLEXPORT void jl_(void *jl_value)
{
    jl_ptls_t ptls = jl_get_ptls_states();
    jl_jmp_buf *old_buf = ptls->safe_restore;
    jl_jmp_buf buf;
    ptls->safe_restore = &buf;
    if (!jl_setjmp(buf, 0)) {
        jl_static_show((JL_STREAM*)STDERR_FILENO, (jl_value_t*)jl_value);
        jl_printf((JL_STREAM*)STDERR_FILENO,"\n");
    }
    else {
        jl_printf((JL_STREAM*)STDERR_FILENO, "\n!!! ERROR in jl_ -- ABORTING !!!\n");
    }
    ptls->safe_restore = old_buf;
}
Пример #5
0
static size_t jl_safe_read_mem(const volatile char *ptr, char *out, size_t len)
{
    jl_ptls_t ptls = jl_get_ptls_states();
    jl_jmp_buf *old_buf = ptls->safe_restore;
    jl_jmp_buf buf;
    ptls->safe_restore = &buf;
    volatile size_t i = 0;
    if (!jl_setjmp(buf, 0)) {
        for (;i < len;i++) {
            out[i] = ptr[i];
        }
    }
    ptls->safe_restore = old_buf;
    return i;
}
Пример #6
0
size_t jl_unw_stepn(bt_cursor_t *cursor, uintptr_t *ip, uintptr_t *sp, size_t maxsize)
{
    jl_ptls_t ptls = jl_get_ptls_states();
    volatile size_t n = 0;
    uintptr_t nullsp;
#if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_)
    assert(!jl_in_stackwalk);
    jl_in_stackwalk = 1;
#endif
#if !defined(_OS_WINDOWS_)
    jl_jmp_buf *old_buf = ptls->safe_restore;
    jl_jmp_buf buf;
    if (!jl_setjmp(buf, 0)) {
        ptls->safe_restore = &buf;
#endif
        while (1) {
           if (n >= maxsize) {
               n = maxsize; // return maxsize + 1 if ran out of space
               break;
           }
           if (!jl_unw_step(cursor, &ip[n], sp ? &sp[n] : &nullsp))
               break;
           n++;
        }
        n++;
#if !defined(_OS_WINDOWS_)
    }
    else {
        // The unwinding fails likely because a invalid memory read.
        // Back off one frame since it is likely invalid.
        // This seems to be good enough on x86 to make the LLVM debug info
        // reader happy.
        if (n > 0) n -= 1;
    }
    ptls->safe_restore = old_buf;
#endif
#if defined(_OS_WINDOWS_) && !defined(_CPU_X86_64_)
    jl_in_stackwalk = 0;
#endif
    return n;
}
Пример #7
0
DLLEXPORT void *jl_eval_string(char *str)
{
#ifdef COPY_STACKS
    jl_root_task->stackbase = (char*)&str;
    if (jl_setjmp(jl_root_task->base_ctx, 1)) {
        jl_switch_stack(jl_current_task, jl_jmp_target);
    }
#endif
    jl_value_t *r;
    JL_TRY {
        jl_value_t *ast = jl_parse_input_line(str);
        JL_GC_PUSH1(&ast);
        r = jl_toplevel_eval(ast);
        JL_GC_POP();
    }
    JL_CATCH {
        //jl_show(jl_stderr_obj(), jl_exception_in_transit);
        r = NULL;
    }
    return r;
}
Пример #8
0
static void *signal_listener(void *arg)
{
    static uintptr_t bt_data[JL_MAX_BT_SIZE + 1];
    static size_t bt_size = 0;
    sigset_t sset;
    int sig, critical, profile;
    jl_sigsetset(&sset);
#ifdef HAVE_KEVENT
    struct kevent ev;
    int sigqueue = kqueue();
    if (sigqueue == -1) {
        perror("signal kqueue");
    }
    else {
        kqueue_signal(&sigqueue, &ev, SIGINT);
        kqueue_signal(&sigqueue, &ev, SIGTERM);
        kqueue_signal(&sigqueue, &ev, SIGABRT);
        kqueue_signal(&sigqueue, &ev, SIGQUIT);
#ifdef SIGINFO
        kqueue_signal(&sigqueue, &ev, SIGINFO);
#else
        kqueue_signal(&sigqueue, &ev, SIGUSR1);
#endif
#ifdef HAVE_ITIMER
        kqueue_signal(&sigqueue, &ev, SIGPROF);
#endif
    }
#endif
    while (1) {
        profile = 0;
        sig = 0;
        errno = 0;
#ifdef HAVE_KEVENT
        if (sigqueue != -1) {
            int nevents = kevent(sigqueue, NULL, 0, &ev, 1, NULL);
            if (nevents == -1) {
                if (errno == EINTR)
                    continue;
                perror("signal kevent");
            }
            if (nevents != 1) {
                close(sigqueue);
                sigqueue = -1;
                continue;
            }
            sig = ev.ident;
        }
        else
#endif
        if (sigwait(&sset, &sig)) {
            sig = SIGABRT; // this branch can't occur, unless we had stack memory corruption of sset
        }
        else if (!sig || errno == EINTR) {
            // This should never happen, but it has been observed to occur
            // when this thread gets used to handle run a signal handler (without SA_RESTART).
            // It would be nice to prohibit the kernel from doing that, by blocking signals on this thread,
            // (so that we aren't temporarily unable to handle the signals that this thread exists to handle)
            // but that sometimes results in the signals never getting delivered at all.
            // Apparently the only consistent way to handle signals with sigwait is all-or-nothing :(
            // And while sigwait handles per-process signals more sanely,
            // it can't really handle thread-targeted signals at all.
            // So signals really do seem to always just be lose-lose.
            continue;
        }
#ifndef HAVE_MACH
#  ifdef HAVE_ITIMER
        profile = (sig == SIGPROF);
#  else
        profile = (sig == SIGUSR1);
#  endif
#endif

        if (sig == SIGINT) {
            if (jl_ignore_sigint()) {
                continue;
            }
            else if (exit_on_sigint) {
                critical = 1;
            }
            else {
                jl_try_deliver_sigint();
                continue;
            }
        }
        else {
            critical = 0;
        }

        critical |= (sig == SIGTERM);
        critical |= (sig == SIGABRT);
        critical |= (sig == SIGQUIT);
#ifdef SIGINFO
        critical |= (sig == SIGINFO);
#else
        critical |= (sig == SIGUSR1 && !profile);
#endif

        int doexit = critical;
#ifdef SIGINFO
        if (sig == SIGINFO)
            doexit = 0;
#else
        if (sig == SIGUSR1)
            doexit = 0;
#endif

        bt_size = 0;
#if !defined(JL_DISABLE_LIBUNWIND)
        unw_context_t *signal_context;
        // sample each thread, round-robin style in reverse order
        // (so that thread zero gets notified last)
        for (int i = jl_n_threads; i-- > 0; ) {
            // notify thread to stop
            jl_thread_suspend_and_get_state(i, &signal_context);

            // do backtrace on thread contexts for critical signals
            // this part must be signal-handler safe
            if (critical) {
                bt_size += rec_backtrace_ctx(bt_data + bt_size,
                        JL_MAX_BT_SIZE / jl_n_threads - 1,
                        signal_context);
                bt_data[bt_size++] = 0;
            }

            // do backtrace for profiler
            if (profile && running) {
                if (bt_size_cur < bt_size_max - 1) {
                    // unwinding can fail, so keep track of the current state
                    // and restore from the SEGV handler if anything happens.
                    jl_ptls_t ptls = jl_get_ptls_states();
                    jl_jmp_buf *old_buf = ptls->safe_restore;
                    jl_jmp_buf buf;

                    ptls->safe_restore = &buf;
                    if (jl_setjmp(buf, 0)) {
                        jl_safe_printf("WARNING: profiler attempt to access an invalid memory location\n");
                    } else {
                        // Get backtrace data
                        bt_size_cur += rec_backtrace_ctx((uintptr_t*)bt_data_prof + bt_size_cur,
                                bt_size_max - bt_size_cur - 1, signal_context);
                    }
                    ptls->safe_restore = old_buf;

                    // Mark the end of this block with 0
                    bt_data_prof[bt_size_cur++] = 0;
                }
                if (bt_size_cur >= bt_size_max - 1) {
                    // Buffer full: Delete the timer
                    jl_profile_stop_timer();
                }
            }

            // notify thread to resume
            jl_thread_resume(i, sig);
        }
#endif

        // this part is async with the running of the rest of the program
        // and must be thread-safe, but not necessarily signal-handler safe
        if (critical) {
            jl_critical_error(sig, NULL, bt_data, &bt_size);
            if (doexit) {
                thread0_exit_count++;
                jl_exit_thread0(128 + sig);
            }
        }
    }
    return NULL;
}