include: Add a target address for unwinding for platforms that need it.

This commit is contained in:
Alexandre Julliard 2009-06-18 13:32:26 +02:00
parent c9deac1126
commit c152b4e7d1
2 changed files with 44 additions and 21 deletions

View File

@ -213,6 +213,18 @@ static inline EXCEPTION_REGISTRATION_RECORD *__wine_pop_frame( EXCEPTION_REGISTR
#endif #endif
} }
static inline EXCEPTION_REGISTRATION_RECORD *__wine_get_frame(void)
{
#if defined(__GNUC__) && defined(__i386__)
EXCEPTION_REGISTRATION_RECORD *ret;
__asm__ __volatile__(".byte 0x64\n\tmovl (0),%0" : "=r" (ret) );
return ret;
#else
NT_TIB *teb = (NT_TIB *)NtCurrentTeb();
return teb->ExceptionList;
#endif
}
/* Exception handling flags - from OS/2 2.0 exception handling */ /* Exception handling flags - from OS/2 2.0 exception handling */
/* Win32 seems to use the same flags as ExceptionFlags in an EXCEPTION_RECORD */ /* Win32 seems to use the same flags as ExceptionFlags in an EXCEPTION_RECORD */
@ -238,26 +250,36 @@ extern void __wine_enter_vm86( CONTEXT *context );
NTSYSAPI void WINAPI RtlUnwind(PVOID,PVOID,PEXCEPTION_RECORD,PVOID); NTSYSAPI void WINAPI RtlUnwind(PVOID,PVOID,PEXCEPTION_RECORD,PVOID);
static inline void DECLSPEC_NORETURN __wine_unwind_target(void)
{
__WINE_FRAME *wine_frame = (__WINE_FRAME *)__wine_get_frame();
__wine_pop_frame( &wine_frame->frame );
siglongjmp( wine_frame->jmp, 1 );
}
/* wrapper for RtlUnwind since it clobbers registers on Windows */ /* wrapper for RtlUnwind since it clobbers registers on Windows */
static inline void __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame, EXCEPTION_RECORD *record ) static inline void DECLSPEC_NORETURN __wine_rtl_unwind( EXCEPTION_REGISTRATION_RECORD* frame,
EXCEPTION_RECORD *record,
void (*target)(void) )
{ {
#if defined(__GNUC__) && defined(__i386__) #if defined(__GNUC__) && defined(__i386__)
int dummy1, dummy2, dummy3; int dummy1, dummy2, dummy3, dummy4;
__asm__ __volatile__("pushl %%ebp\n\t" __asm__ __volatile__("pushl %%ebp\n\t"
"pushl %%ebx\n\t" "pushl %%ebx\n\t"
"pushl $0\n\t" "pushl $0\n\t"
"pushl %3\n\t"
"pushl %2\n\t" "pushl %2\n\t"
"pushl $0\n\t"
"pushl %1\n\t" "pushl %1\n\t"
"call *%0\n\t" "call *%0\n\t"
"popl %%ebx\n\t" "popl %%ebx\n\t"
"popl %%ebp" "popl %%ebp"
: "=a" (dummy1), "=S" (dummy2), "=D" (dummy3) : "=a" (dummy1), "=S" (dummy2), "=D" (dummy3), "=c" (dummy4)
: "0" (RtlUnwind), "1" (frame), "2" (record) : "0" (RtlUnwind), "1" (frame), "2" (target), "3" (record)
: "ecx", "edx", "memory" ); : "edx", "memory" );
#else #else
RtlUnwind( frame, 0, record, 0 ); RtlUnwind( frame, target, record, 0 );
#endif #endif
for (;;) target();
} }
static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *record, static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *record,
@ -269,9 +291,7 @@ static inline void DECLSPEC_NORETURN __wine_unwind_frame( EXCEPTION_RECORD *reco
wine_frame->ExceptionCode = record->ExceptionCode; wine_frame->ExceptionCode = record->ExceptionCode;
wine_frame->ExceptionRecord = wine_frame; wine_frame->ExceptionRecord = wine_frame;
__wine_rtl_unwind( frame, record ); __wine_rtl_unwind( frame, record, __wine_unwind_target );
__wine_pop_frame( frame );
siglongjmp( wine_frame->jmp, 1 );
} }
static inline DWORD __wine_exception_handler( EXCEPTION_RECORD *record, static inline DWORD __wine_exception_handler( EXCEPTION_RECORD *record,

View File

@ -3989,6 +3989,19 @@ void write_exceptions( FILE *file )
fprintf( file, " __DECL_EXCEPTION_FRAME\n"); fprintf( file, " __DECL_EXCEPTION_FRAME\n");
fprintf( file, "};\n"); fprintf( file, "};\n");
fprintf( file, "\n"); fprintf( file, "\n");
fprintf( file, "static inline void __widl_unwind_target(void)\n" );
fprintf( file, "{\n");
fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)__wine_get_frame();\n" );
fprintf( file, " if (exc_frame->finally_level > exc_frame->filter_level)\n" );
fprintf( file, " {\n");
fprintf( file, " exc_frame->abnormal_termination = 1;\n");
fprintf( file, " exc_frame->finally( exc_frame );\n");
fprintf( file, " __wine_pop_frame( &exc_frame->frame );\n");
fprintf( file, " }\n");
fprintf( file, " exc_frame->filter_level = 0;\n");
fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n");
fprintf( file, "}\n");
fprintf( file, "\n");
fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n"); fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n");
fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n");
fprintf( file, " CONTEXT *context,\n"); fprintf( file, " CONTEXT *context,\n");
@ -4007,17 +4020,7 @@ void write_exceptions( FILE *file )
fprintf( file, " }\n" ); fprintf( file, " }\n" );
fprintf( file, " exc_frame->code = record->ExceptionCode;\n"); fprintf( file, " exc_frame->code = record->ExceptionCode;\n");
fprintf( file, " if (exc_frame->filter_level && exc_frame->filter( record, exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" ); fprintf( file, " if (exc_frame->filter_level && exc_frame->filter( record, exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" );
fprintf( file, " {\n"); fprintf( file, " __wine_rtl_unwind( frame, record, __widl_unwind_target );\n");
fprintf( file, " __wine_rtl_unwind( frame, record );\n");
fprintf( file, " if (exc_frame->finally_level > exc_frame->filter_level)\n" );
fprintf( file, " {\n");
fprintf( file, " exc_frame->abnormal_termination = 1;\n");
fprintf( file, " exc_frame->finally( exc_frame );\n");
fprintf( file, " __wine_pop_frame( frame );\n");
fprintf( file, " }\n");
fprintf( file, " exc_frame->filter_level = 0;\n");
fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n");
fprintf( file, " }\n");
fprintf( file, " return ExceptionContinueSearch;\n"); fprintf( file, " return ExceptionContinueSearch;\n");
fprintf( file, "}\n"); fprintf( file, "}\n");
fprintf( file, "\n"); fprintf( file, "\n");