📄 except.c
字号:
/* 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 + -