⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 except.c

📁 一个实时的驱动支持库
💻 C
📖 第 1 页 / 共 2 页
字号:
        /* type is the same, now check the flags */        if ((exception_type->flags & TYPE_FLAG_CONST) &&            !(catchblock->flags & TYPE_FLAG_CONST)) continue;        if ((exception_type->flags & TYPE_FLAG_VOLATILE) &&            !(catchblock->flags & TYPE_FLAG_VOLATILE)) continue;        return type;  /* it matched */    }    return NULL;}/* copy the exception object where the catch block wants it */static void copy_exception(void *object, cxx_exception_frame *frame,                           catchblock_info *catchblock, const cxx_type_info *type){    void **dest_ptr;    if (!catchblock->type_info || !catchblock->type_info->name[0]) return;    if (!catchblock->offset) return;    dest_ptr = (void **)((char *)&frame->ebp + catchblock->offset);    if (catchblock->flags & TYPE_FLAG_REFERENCE)    {        *dest_ptr = get_this_pointer(type, object);    }    else if (type->flags & CLASS_IS_SIMPLE_TYPE)    {        memcpy(dest_ptr, object, type->size);        /* if it is a pointer, adjust it */        if (type->size == sizeof(void *)) *dest_ptr = get_this_pointer(type, *dest_ptr);    }    else  /* copy the object */    {        if (type->copy_constructor)        {            cxx_push_handler(unexpected_handler);            cxx_call_copy_constructor(type->copy_constructor, dest_ptr, get_this_pointer(type, object),                (type->flags & CLASS_HAS_VIRTUAL_BASE_CLASS));            cxx_pop_handler();        }        else        {            memcpy(dest_ptr, get_this_pointer(type, object), type->size);        }    }}/* unwind the local function up to a given trylevel */static void cxx_local_unwind(cxx_exception_frame *frame, cxx_function_descr *descr,                             int last_level){    while (frame->trylevel != last_level)    {        if (frame->trylevel < 0 || frame->trylevel >= descr->unwind_count)        {            terminate();        }        if (descr->unwind_table[frame->trylevel].handler)        {            cxx_push_handler(unexpected_handler);            cxx_call_handler(descr->unwind_table[frame->trylevel].handler, &frame->ebp);            cxx_pop_handler();        }        frame->trylevel = descr->unwind_table[frame->trylevel].prev;    }}/* global unwind */static void cxx_global_unwind(PEXCEPTION_FRAME last_frame){
    PEXCEPTION_FRAME frame, current_frame, stack_base, stack_top;
    PEXCEPTION_RECORD rec;
    PCONTEXT context;

    __asm
    {
        mov  eax, dword ptr fs:[0]
        mov  dword ptr [current_frame], eax

        mov  eax, dword ptr fs:[4]
        mov  dword ptr [stack_top], eax

        mov  eax, dword ptr fs:[8]
        mov  dword ptr [stack_base], eax
    }

    rec = ExAllocatePool(NonPagedPool, (sizeof(EXCEPTION_RECORD)));
    memset(rec, 0, sizeof(EXCEPTION_RECORD));
    //rec->ExceptionCode = STATUS_UNWIND;
    rec->ExceptionFlags = EH_UNWINDING;
    rec->ExceptionAddress = 0;
    rec->ExceptionRecord = 0;

    context = ExAllocatePool(NonPagedPool, (sizeof(CONTEXT)));
    memset(context, 0, sizeof(CONTEXT));

    for (frame = current_frame; frame != last_frame; frame = frame->Prev)
    {
        //check for possible stack corruption
        if (frame < stack_base ||
            frame + sizeof(EXCEPTION_FRAME) > stack_top ||
            frame > last_frame ||
            (frame->Prev != (PEXCEPTION_FRAME) -1 && frame > frame->Prev)
            )
        {
            terminate();
        }

        cxx_push_handler(unexpected_handler);
        (*frame->Handler)(rec, frame, context, 0);
        cxx_pop_handler();
    }

    ExFreePool(rec);
    ExFreePool(context);

    __asm
    {
        mov  eax, dword ptr [last_frame]
        mov  dword ptr fs:[0], eax
    }
}

/* exception handler for exceptions thrown from a catch block */static EXCEPTION_DISPOSITION __stdcall catch_block_protector(PEXCEPTION_RECORD rec, PEXCEPTION_FRAME frame,
                                                             PCONTEXT context, void *dispatch)
{
    if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
    {
        /* get the previous exception saved on the stack */
        void* exception_object = (void*) ((ULONG*)frame)[2];
        cxx_exception_type* exception_type = (cxx_exception_type*) ((ULONG*)frame)[3];

        if (rec->ExceptionCode == CXX_EXCEPTION &&
            rec->NumberParameters == 3 &&
            rec->ExceptionInformation[0] == CXX_FRAME_MAGIC &&
            rec->ExceptionInformation[1] == 0 &&
            rec->ExceptionInformation[2] == 0)
        {
            /* rethrow the previous exception */
            rec->ExceptionInformation[1] = (ULONG) exception_object;
            rec->ExceptionInformation[2] = (ULONG) exception_type;
        }
        else
        {
            /* throw of new exception, delete the previous exception object */
            if (exception_object && exception_type->destructor)
            {
                cxx_push_handler(unexpected_handler);                cxx_call_destructor(exception_type->destructor, exception_object);                cxx_pop_handler();            }
        }
    }
    return ExceptionContinueSearch;
}
/* find and call the appropriate catch block for an exception *//* returns the address to continue execution to after the catch block was called */static void *call_catch_block(PEXCEPTION_RECORD rec, cxx_exception_frame *frame,                              cxx_function_descr *descr){    unsigned int i;    int j;    void *ret_addr;    void *exception_object = (void *) rec->ExceptionInformation[1];    cxx_exception_type *exception_type = (cxx_exception_type *) rec->ExceptionInformation[2];    int trylevel = frame->trylevel;    for (i = 0; i < descr->tryblock_count; i++)    {        tryblock_info *tryblock = &descr->tryblock[i];        if (trylevel < tryblock->start_level) continue;        if (trylevel > tryblock->end_level) continue;        /* got a try block */        for (j = 0; j < tryblock->catchblock_count; j++)        {            catchblock_info *catchblock = &tryblock->catchblock[j];            const cxx_type_info *type = find_caught_type(exception_type, catchblock);            if (!type) continue;            /* copy the exception to its destination on the stack */            copy_exception(exception_object, frame, catchblock, type);            /* unwind the stack */            _global_unwind2(frame);
            //cxx_global_unwind((PEXCEPTION_FRAME)frame);
            cxx_local_unwind(frame, descr, tryblock->start_level);            frame->trylevel = tryblock->end_level + 1;            /* call the catch block */            __asm push exception_type            __asm push exception_object            cxx_push_handler(catch_block_protector);            ret_addr = cxx_call_handler(catchblock->handler, &frame->ebp);            cxx_pop_handler();            __asm add esp, 8            /* delete the exception object */            if (exception_object && exception_type->destructor)            {                cxx_push_handler(unexpected_handler);                cxx_call_destructor(exception_type->destructor, exception_object);                cxx_pop_handler();            }            return ret_addr;        }    }    return NULL;}static EXCEPTION_DISPOSITION cxx_frame_handler(PEXCEPTION_RECORD rec, cxx_exception_frame *frame,                                               PCONTEXT context, void *dispatch,                                               cxx_function_descr *descr){    if (descr->magic != CXX_FRAME_MAGIC)    {        return ExceptionContinueSearch;    }    /* stack unwinding */    if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))    {        if(frame->trylevel >= descr->unwind_count) //stack corruption
        {
            terminate();
        }
        if (descr->unwind_count)        {            cxx_local_unwind(frame, descr, -1);        }    }    /* non C++ exception */    else if (rec->ExceptionCode != CXX_EXCEPTION)    {        if (_se_translator)        {            EXCEPTION_POINTERS ep = {rec, context};            (*_se_translator)(rec->ExceptionCode, &ep);        }    }    /* C++ exception */    else if (rec->NumberParameters == 3 &&
             rec->ExceptionInformation[0] == CXX_FRAME_MAGIC &&
             rec->ExceptionInformation[1] != 0 &&
             rec->ExceptionInformation[2] != 0)
    {
        void *ret_addr = call_catch_block(rec, frame, descr);        if (ret_addr)        {            rec->ExceptionFlags &= ~EH_NONCONTINUABLE;            context->Eip = (ULONG)ret_addr;            context->Ebp = (ULONG)&frame->ebp;            context->Esp = ((ULONG*)frame)[-1];            return ExceptionContinueExecution;        }    }    return ExceptionContinueSearch;}__declspec (naked)EXCEPTION_DISPOSITION __cdecl __CxxFrameHandler(PEXCEPTION_RECORD rec, PEXCEPTION_FRAME frame,
                                                PCONTEXT context, void *dispatch)
{
    __asm
    {
        push ebp
        mov  ebp, esp
        cld
        push eax
        push dispatch
        push context
        push frame
        push rec
        call cxx_frame_handler
        mov  esp, ebp
        pop  ebp
        ret  16
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -