Beispiel #1
0
static void generate_report()
{
    EXCEPTION_RECORD local_exception_record;
    CONTEXT local_context;

    EXCEPTION_POINTERS local_exception_pointers;

    local_exception_pointers.ExceptionRecord = &local_exception_record;
    local_exception_pointers.ContextRecord = &local_context;

    if (!exception_pointers_)
    {
        get_exception_pointers(&local_exception_pointers);
        exception_pointers_ = &local_exception_pointers;
    }

    create_minidump();
    ::TerminateProcess(::GetCurrentProcess(), 100500);
}
Beispiel #2
0
LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception)
{
    DWORD code = nt_exception->ExceptionRecord->ExceptionCode;
    void* fault_addr = nt_exception->ExceptionRecord->ExceptionAddress;

    Registers regs;
    // Convert NT context to Registers
    port_thread_context_to_regs(&regs, nt_exception->ContextRecord);

    // Check if TLS structure is set - probably we should produce minidump
    port_tls_data_t* tlsdata = get_private_tls_data();

    if (!tlsdata) // Tread is not attached - attach thread temporarily
    {
        int res;
        tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t));

        if (tlsdata) // Try to attach the thread
            res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0);

        if (!tlsdata || res != 0)
        { // Can't process correctly; perform default actions
            if (FLAG_CORE)
                create_minidump(nt_exception);

            if (FLAG_DBG)
            {
                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
                _exit(-1);
                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
            }

            _exit(-1);
        }

        // SO for alien thread can't be processed out of VEH
        if (code == STATUS_STACK_OVERFLOW &&
            sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
        {
            int result;
            size_t alt_stack_size = ALT_PAGES_COUNT*tlsdata->guard_page_size;
            void* alt_stack = map_alt_stack(alt_stack_size);
            void* stack_bottom = (void*)((POINTER_SIZE_INT)alt_stack + alt_stack_size);

            if (alt_stack)
                result = (int)(POINTER_SIZE_INT)port_call_alt_stack(
                                            port_process_signal, stack_bottom, 4,
                                            PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);
            else
                result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, &regs, fault_addr, FALSE);

            if (result == 0)
            {
                if (port_thread_detach_temporary() == 0)
                    STD_FREE(tlsdata);
                if (alt_stack)
                    unmap_alt_stack(alt_stack, alt_stack_size);
                return EXCEPTION_CONTINUE_EXECUTION;
            }

            if (FLAG_CORE)
            {
                if (alt_stack)
                    port_call_alt_stack(create_minidump, stack_bottom, 1, nt_exception);
                else
                    create_minidump(nt_exception);
            }

            if (alt_stack)
                unmap_alt_stack(alt_stack, alt_stack_size);

            if (result > 0)
            {
                show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work
                _exit(-1);
                shutdown_signals();
                return EXCEPTION_CONTINUE_SEARCH; // Assert dialog
            }

            _exit(-1);
        }
    }

    if (tlsdata->produce_core)
    {
        create_minidump(nt_exception);
        if (!tlsdata->debugger)
            _exit(-1);
    }

    if (tlsdata->debugger)
    {
        show_debugger_dialog(); // Workaround
        _exit(-1);
        // Go to handler to restore CRT/VEH settings and crash once again
//        port_set_longjump_regs(&prepare_assert_dialog, &regs, 1, &regs);
//        port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
//        return EXCEPTION_CONTINUE_EXECUTION;
    }

    switch (code)
    {
    case STATUS_STACK_OVERFLOW:
        if (!sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case STATUS_ACCESS_VIOLATION:
        if (!sd_is_handler_registered(PORT_SIGNAL_GPF))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    case JVMTI_EXCEPTION_STATUS:
        if (!sd_is_handler_registered(PORT_SIGNAL_BREAKPOINT))
            return EXCEPTION_CONTINUE_SEARCH;
        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:
        if (!sd_is_handler_registered(PORT_SIGNAL_ARITHMETIC))
            return EXCEPTION_CONTINUE_SEARCH;
        break;
    default:
        return EXCEPTION_CONTINUE_SEARCH;
    }

    if (code == STATUS_STACK_OVERFLOW)
    {
        tlsdata->guard_page_set = FALSE; // GUARD_PAGE was cleared by OS

        if (!tlsdata->restore_guard_page)
            tlsdata->restore_guard_page = TRUE;
    }

    // Prepare to transfering control out of VEH handler
    port_set_longjump_regs(&c_handler, &regs, 4, &regs,
        nt_exception->ExceptionRecord->ExceptionAddress,
        (void*)(size_t)nt_exception->ExceptionRecord->ExceptionCode,
        (void*)(size_t)nt_exception->ExceptionRecord->ExceptionFlags);
    // Convert prepared Registers back to NT context
    port_thread_regs_to_context(nt_exception->ContextRecord, &regs);
    // Return from VEH - presumably continue execution
    return EXCEPTION_CONTINUE_EXECUTION;
}