Example #1
0
static void c_handler(Registers* pregs,
                        void* fault_addr, size_t code, size_t flags)
{ // this exception handler is executed *after* VEH handler returned
    int result;
    Boolean iscrash = (DWORD)flags == EXCEPTION_NONCONTINUABLE;

    switch ((DWORD)code)
    {
    case STATUS_STACK_OVERFLOW:
        result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, pregs, fault_addr, iscrash);
        break;
    case STATUS_ACCESS_VIOLATION:
        result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, iscrash);
        break;
    case STATUS_INTEGER_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
    case EXCEPTION_FLT_OVERFLOW:
    case EXCEPTION_FLT_UNDERFLOW:
    case EXCEPTION_INT_OVERFLOW:
        result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, iscrash);
        break;
    case JVMTI_EXCEPTION_STATUS:
        result = port_process_signal(PORT_SIGNAL_BREAKPOINT, pregs, fault_addr, iscrash);
        break;
    default:
        result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
    }

    port_tls_data_t* tlsdata = get_private_tls_data();

    if (result == 0)
    {
        // Restore guard page if needed
        if (tlsdata->restore_guard_page)
        {
            port_thread_restore_guard_page();
            tlsdata->restore_guard_page = FALSE;
        }

        if (port_thread_detach_temporary() == 0)
            STD_FREE(tlsdata);
        return;
    }

    if (result > 0 /*Assert dialog*/|| FLAG_CORE)
    {
        // Prepare second catch of this exception to produce minidump (because
        // we've lost LPEXCEPTION_POINTERS structure) and/or show assert dialog
        if (FLAG_CORE)
            tlsdata->produce_core = TRUE;
        if (result > 0)
            tlsdata->debugger = TRUE;
        // To catch STACK_OVERFLOW
        port_thread_restore_guard_page();

        return; // To produce exception again
    }

    _exit(-1); // We need neither dump nor assert dialog
}
Example #2
0
// exception catch support for JVMTI, also restore stack after Stack Overflow Error
void jvmti_exception_catch_callback() {
    Registers regs = {0};
    VM_thread *thread = p_TLS_vmthread;
    assert(thread);

    if (thread->regs) {
        regs = *(Registers*)thread->regs;
    }

    M2nFrame* m2n = (M2nFrame *) STD_ALLOCA(m2n_get_size());
    m2n_push_suspended_frame(thread, m2n, &regs);
    M2nFrame* prev_m2n = m2n_get_previous_frame(m2n);

    StackIterator* si = (StackIterator*) STD_ALLOCA(si_size());
    si_fill_from_registers(si, &regs, false, prev_m2n);

    // si_create_from_registers uses large stack space,
    // so guard page restored after its invoke, 
    // but befor ti agent callback invokation, 
    // because it should work on protected page.
    if (p_TLS_vmthread->restore_guard_page) {
        int res = port_thread_restore_guard_page();

        if (res != 0) {
            Global_Env *env = VM_Global_State::loader_env;

            if (si_is_native(si)) {
                m2n_set_last_frame(prev_m2n);

                if ((interpreter_enabled() || (!prev_m2n) ||
                        (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
                    exn_raise_by_class(env->java_lang_StackOverflowError_Class);
                } else {
                    //si_free(si);
                    exn_throw_by_class(env->java_lang_StackOverflowError_Class);
                }
            } else {
                //si_free(si);
                exn_throw_by_class(env->java_lang_StackOverflowError_Class);
            }
        }

        p_TLS_vmthread->restore_guard_page = false;
    }

    if (!si_is_native(si))
    {
        CodeChunkInfo* catch_cci = si_get_code_chunk_info(si);
        assert(catch_cci);
        Method* catch_method = catch_cci->get_method();
        NativeCodePtr catch_method_location = si_get_ip(si);
        JIT* catch_method_jit = catch_cci->get_jit();
        ManagedObject** exn_obj = (ManagedObject**) si_get_return_pointer(si);
        *exn_obj = jvmti_jit_exception_catch_event_callback_call( *exn_obj,
                catch_method_jit, catch_method, catch_method_location);
    }

    si_transfer_control(si);
}
Example #3
0
// exception catch callback to restore stack after Stack Overflow Error
void exception_catch_callback() {
    Registers regs = {0};
    VM_thread *thread = p_TLS_vmthread;
    assert(thread);

    if (thread->regs) {
        regs = *(Registers*)thread->regs;
    }

    M2nFrame* m2n = (M2nFrame *) STD_ALLOCA(m2n_get_size());
    m2n_push_suspended_frame(thread, m2n, &regs);
    M2nFrame* prev_m2n = m2n_get_previous_frame(m2n);

    StackIterator* si = (StackIterator*) STD_ALLOCA(si_size());
    si_fill_from_registers(si, &regs, false, prev_m2n);

    // si_create_from_registers uses large stack space,
    // so guard page restored after its invoke.
    if (p_TLS_vmthread->restore_guard_page) {
        int res = port_thread_restore_guard_page();

        if (res != 0) {
            Global_Env *env = VM_Global_State::loader_env;

            if (si_is_native(si)) {
                m2n_set_last_frame(prev_m2n);

                if ((interpreter_enabled() || (!prev_m2n) ||
                        (m2n_get_frame_type(prev_m2n) & FRAME_NON_UNWINDABLE))) {
                    exn_raise_by_class(env->java_lang_StackOverflowError_Class);
                } else {
                    //si_free(si);
                    exn_throw_by_class(env->java_lang_StackOverflowError_Class);
                }
            } else {
                //si_free(si);
                exn_throw_by_class(env->java_lang_StackOverflowError_Class);
            }
        }

        p_TLS_vmthread->restore_guard_page = false;
    }

    si_transfer_control(si);
}
void exn_clear()
{
    tmn_suspend_disable_recursive();
    clear_exception_internal();
    tmn_suspend_enable_recursive();

    // This will restore quard stack if needed
    if (p_TLS_vmthread->restore_guard_page) {
        int res = port_thread_restore_guard_page();

        // if guard stack can't be restored raise SOE
        if (res != 0) {
            Global_Env *env = VM_Global_State::loader_env;
            exn_raise_by_class(env->java_lang_StackOverflowError_Class);
        }

        p_TLS_vmthread->restore_guard_page = false;
    }
}
Example #5
0
void prepare_assert_dialog(Registers* regs)
{
    // To catch STACK_OVERFLOW
    port_thread_restore_guard_page();
    shutdown_signals();
}
Example #6
0
static void c_handler(Registers* pregs, size_t signum, void* fault_addr)
{   // this exception handler is executed *after* OS signal handler returned
    int result;
    port_tls_data_t* tlsdata = get_private_tls_data();

    switch ((int)signum)
    {
    case SIGSEGV:
        if (tlsdata->restore_guard_page)
        {
            // Now it's safe to disable alternative stack
            set_alt_stack(tlsdata, FALSE);
            result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, pregs, fault_addr, FALSE);
        }
        else
            result = port_process_signal(PORT_SIGNAL_GPF, pregs, fault_addr, FALSE);
        break;
    case SIGFPE:
        result = port_process_signal(PORT_SIGNAL_ARITHMETIC, pregs, fault_addr, FALSE);
        break;
    case SIGTRAP:
        // Correct return address
        pregs->set_ip((void*)((POINTER_SIZE_INT)pregs->get_ip() - 1));
        result = port_process_signal(PORT_SIGNAL_BREAKPOINT, pregs, fault_addr, FALSE);
        break;
    case SIGINT:
        result = port_process_signal(PORT_SIGNAL_CTRL_C, pregs, fault_addr, FALSE);
        break;
    case SIGQUIT:
        result = port_process_signal(PORT_SIGNAL_QUIT, pregs, fault_addr, FALSE);
        break;
    case SIGABRT:
        result = port_process_signal(PORT_SIGNAL_ABORT, NULL, fault_addr, FALSE);
        break;
    default:
        result = port_process_signal(PORT_SIGNAL_UNKNOWN, pregs, fault_addr, TRUE);
    }

    if (result == 0)
    {
        // Restore guard page if needed
        if (tlsdata->restore_guard_page)
        {
            port_thread_restore_guard_page();
            tlsdata->restore_guard_page = FALSE;

            if (port_thread_detach_temporary() == 0)
                STD_FREE(tlsdata);
        }
        return;
    }

    // We've got a crash
    if (signum == SIGSEGV)
    {
        port_thread_restore_guard_page(); // To catch SO again
        tlsdata->restore_guard_page = FALSE;
    }

    if (result > 0) // invoke debugger
    {   // Prepare second catch of signal to attach GDB from signal handler
        //assert(tlsdata); // Should be attached - provided by general_signal_handler
        tlsdata->debugger = TRUE;
        return; // To produce signal again
    }

    // result < 0 - exit process
    if (FLAG_CORE)
    {   // Return to the same place to produce the same crash and generate core
        signal(signum, SIG_DFL); // setup default handler
        return;
    }

    // No core needed - simply terminate
    _exit(-1);
}