mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 12:54:13 +00:00
include: Add a target address for unwinding for platforms that need it.
This commit is contained in:
parent
c9deac1126
commit
c152b4e7d1
2 changed files with 44 additions and 21 deletions
|
@ -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,
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in a new issue