diff options
Diffstat (limited to 'private/crt32/misc/i386/exsup3.asm')
-rw-r--r-- | private/crt32/misc/i386/exsup3.asm | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/private/crt32/misc/i386/exsup3.asm b/private/crt32/misc/i386/exsup3.asm new file mode 100644 index 000000000..ff8a91dfa --- /dev/null +++ b/private/crt32/misc/i386/exsup3.asm @@ -0,0 +1,290 @@ +;*** +;exsup3.asm +; +; Copyright (c) 1994 Microsoft Corporation. All rights reserved. +; +;Purpose: +; Exception handling for i386. This is just the C9.0 version of +; the language-specific exception handler. The C8.0 version is +; found in exsup2.asm, and the routines common to both C8 and C9 +; are found in exsup.asm. +; +;Notes: +; +;Revision History: +; 01-10-94 PML Create VC/C++ 2.0 (C9.0) version from C8.0 original +; +;******************************************************************************* + +;hnt = -D_WIN32_ -Dsmall32 -Dflat32 -Mx $this; + +;Define small32 and flat32 since these are not defined in the NT build process +small32 equ 1 +flat32 equ 1 + +ifdef _WIN32_ +_WIN32_OR_POSIX_ equ 1 +endif +ifdef _POSIX_ +_WIN32_OR_POSIX_ equ 1 +endif + +.xlist +include pversion.inc +?DFDATA = 1 +?NODATA = 1 +include cmacros.mas +include exsup.inc +.list + +;REVIEW: can we get rid of _global_unwind2, and just use +; the C runtimes version, _global_unwind? + +extrn __global_unwind2:near +extrn __local_unwind2:near + +;typedef struct _EXCEPTION_REGISTRATION PEXCEPTION_REGISTRATION; +;struct _EXCEPTION_REGISTRATION{ +;/* _esp, xpointers at negative offset */ +; int _esp; +; PEXCEPTION_POINTERS xpointers; +; struct _EXCEPTION_REGISTRATION *prev; +; void (*handler)(PEXCEPTION_RECORD, PEXCEPTION_REGISTRATION, PCONTEXT, PEXCEPTION_RECORD); +; struct scopetable_entry *scopetable; +; int trylevel; +;}; +;private (at negative offsets from node ptr) + _esp = -8 + xpointers = -4 +_C9_EXCEPTION_REGISTRATION struc ; C9.0 version +;public: + dd ? ; prev (common) + dd ? ; handler (common) +;private: + scopetable dd ? + trylevel dd ? +_C9_EXCEPTION_REGISTRATION ends +FRAME_EBP_OFFSET equ 16 + +;#define EXCEPTION_MAXIMUM_PARAMETERS 4 +;typedef struct _EXCEPTION_RECORD EXCEPTION_RECORD; +;typedef EXCEPTION_RECORD *PEXCEPTION_RECORD; +;struct _EXCEPTION_RECORD{ +; NTSTATUS ExceptionCode; +; ULONG ExceptionFlags; +; struct _EXCEPTION_RECORD *ExceptionRecord; +; PVOID ExceptionAddress; +; ULONG NumberParameters; +; ULONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +;}; +_EXCEPTION_RECORD struc + exception_number dd ? + exception_flags dd ? + exception_record dd ? + exception_address dd ? + number_parameters dd ? + exception_information dd 4 dup(?) +_EXCEPTION_RECORD ends +SIZEOF_EXCEPTION_RECORD equ 36 + +;/* following is the structure returned by the _exception_info() intrinsic. */ +;typedef struct _EXCEPTION_POINTERS EXCEPTION_POINTERS; +;typedef struct EXCEPTION_POINTERS *PEXCEPTION_POINTERS; +;struct _EXCEPTION_POINTERS{ +; PEXCEPTION_RECORD ExceptionRecord; +; PCONTEXT Context; +;}; +_EXCEPTION_POINTERS struc + ep_xrecord dd ? + ep_context dd ? +_EXCEPTION_POINTERS ends +SIZEOF_EXCEPTION_POINTERS equ 8 + +assumes DS,DATA +assumes FS,DATA + +__except_list equ 0 + +;struct _SCOPETABLE_ENTRY{ +; int enclosing_level; /* lexical level of enclosing scope */ +; int (*filter)(PEXCEPTION_RECORD); /* NULL for a termination handler */ +; void (*specific_handler)(void); /* xcpt or termination handler */ +;}; +;struct _SCOPETABLE_ENTRY Scopetable[NUMTRYS]; +_SCOPETABLE_ENTRY struc + enclosing_level dd ? + filter dd ? + specific_handler dd ? +_SCOPETABLE_ENTRY ends + +BeginCODE +if @Version LT 600 +ifdef _WIN32_OR_POSIX_ +;this needs to go here to work around a masm5 bug. (emits wrong fixup) +assumes CS,FLAT +else +assumes CS,CODE +endif +endif + +;/* _EXCEPT_HANDLER3 - Try to find an exception handler listed in the scope +; * table associated with the given registration record, that wants to accept +; * the current exception. If we find one, run it (and never return). +; * RETURNS: (*if* it returns) +; * DISPOSITION_DISMISS - dismiss the exception. +; * DISPOSITION_CONTINUE_SEARCH - pass the exception up to enclosing handlers +; */ +;int _except_handler3( +; PEXCEPTION_RECORD exception_record, +; PEXCEPTION_REGISTRATION registration, +; PCONTEXT context, +; PEXCEPTION_REGISTRATION dispatcher) +;{ +; int ix, filter_result; +; +; for(ix=registration->trylevel; ix!=-1; ix=registration->xscope[ix].enclosing_level){ +; /* if filter==NULL, then this is an entry for a termination handler */ +; if(registration->xscope[ix].filter){ +; /* NB: call to the filter may trash the callee save +; registers. (this is *not* a standard cdecl function) */ +; filter_result=(*registration->xscope[ix].filter)(xinfo); +; if(filter_result==FILTER_DISMISS) +; return(-1); /* dismiss */ +; if(filter_result==FILTER_ACCEPT){ +; _global_unwind2(registration); +; _local_unwind2(registration, ix); +; (*registration->xscope[ix].specific_handler)(void); +; assert(UNREACHED); /*should never return from handler*/ +; } +; assert(filter_result==FILTER_CONTINUE_SEARCH); +; } +; } +; return(0); /* didnt find one */ +;} + db 'VC20' ;; VC/C++ 2.0/32-bit (C9.0) version + db 'XC00' ;; so debugger can recognize this proc (cuda:3936) +cProc _except_handler3,<C,PUBLIC>,<IBX,ISI,IDI,IBP> + parmDP xrecord + parmDP registration + parmDP context + parmDP dispatcher + localV xp,SIZEOF_EXCEPTION_POINTERS +cBegin + ;4*4b for callee saves + 4b return address + 4b param = 24 + + ;DF in indeterminate state at time of exception, so clear it + cld + + mov ebx, registration ;ebx= PEXCEPTION_REGISTRATION + mov eax, xrecord + + test [eax.exception_flags], EXCEPTION_UNWIND_CONTEXT + jnz short _lh_unwinding + + ;build the EXCEPTION_POINTERS locally store its address in the + ; registration record. this is the pointer that is returned by + ; the _eception_info intrinsic. + mov xp.ep_xrecord, eax + mov eax, context + mov xp.ep_context, eax + lea eax, xp + mov [ebx.xpointers], eax + + mov esi, [ebx.trylevel] ;esi= try level + mov edi, [ebx.scopetable] ;edi= scope table base +_lh_top: + cmp esi, -1 + je short _lh_bagit + lea ecx, [esi+esi*2] ;ecx= trylevel*3 + cmp dword ptr [(edi+ecx*4).filter], 0 + je short _lh_continue ;term handler, so keep looking + + ;filter may trash *all* registers, so save ebp and scopetable offset + push esi + push ebp + + lea ebp, FRAME_EBP_OFFSET[ebx] + call [(edi+ecx*4).filter] ;call the filter + + pop ebp + pop esi + ;ebx may have been trashed by the filter, so we must reload + mov ebx, registration + + ; Accept <0, 0, >0 instead of just -1, 0, +1 + or eax, eax + jz short _lh_continue + js short _lh_dismiss + ;assert(eax==FILTER_ACCEPT) + + ;reload xscope base, cuz it was trashed by the filter call + mov edi, [ebx.scopetable] + ;load handler address before we loose components of address mode + push ebx ;registration* + call __global_unwind2 ;run term handlers + add esp, 4 + + ;setup ebp for the local unwinder and the specific handler + lea ebp, FRAME_EBP_OFFSET[ebx] + + ;the stop try level == accepting except level + push esi ;stop try level + push ebx ;registration* + call __local_unwind2 + add esp, 8 + + lea ecx, [esi+esi*2] ;ecx=trylevel*3 +; set the current trylevel to our enclosing level immediately +; before giving control to the handler. it is the enclosing +; level, if any, that guards the handler. + mov eax, [(edi+ecx*4).enclosing_level] + mov [ebx.trylevel], eax + call [(edi+ecx*4).specific_handler] ;call the except handler + ;assert(0) ;(NB! should not return) + +_lh_continue: + ;reload the scope table base, possibly trashed by call to filter + mov edi, [ebx.scopetable] + lea ecx, [esi+esi*2] + mov esi, [edi+ecx*4+0] ;load the enclosing trylevel + jmp short _lh_top + +_lh_dismiss: + mov eax, DISPOSITION_DISMISS ;dismiss the exception + jmp short _lh_return + +_lh_bagit: + mov eax, DISPOSITION_CONTINUE_SEARCH + jmp short _lh_return + +_lh_unwinding: + push ebp + lea ebp, FRAME_EBP_OFFSET[ebx] + push -1 + push ebx + call __local_unwind2 + add esp, 8 + pop ebp + ;the return value is not really relevent in an unwind context + mov eax, DISPOSITION_CONTINUE_SEARCH + +_lh_return: +cEnd + +public __seh_longjmp_unwind@4 +__seh_longjmp_unwind@4 proc near + push ebp + mov ecx, 8[esp] + mov ebp, [ecx.saved_ebp] + mov eax, [ecx.saved_trylevel] + push eax + mov eax, [ecx.saved_xregistration] + push eax + call __local_unwind2 + add esp, 8 + pop ebp + ret 4 +__seh_longjmp_unwind@4 endp + +EndCODE +END |