msvcrt: Set the correct ebp value before calling the local unwind handler.

This commit is contained in:
Alexandre Julliard 2007-06-08 12:56:19 +02:00
parent abc5fefada
commit 72bc7429e4
2 changed files with 45 additions and 30 deletions

View File

@ -71,15 +71,26 @@ static inline void call_finally_block( void *code_block, void *base_ptr )
: : "a" (code_block), "g" (base_ptr)); : : "a" (code_block), "g" (base_ptr));
} }
static inline DWORD call_filter( void *func, void *arg, void *ebp ) static inline int call_filter( int (*func)(PEXCEPTION_POINTERS), void *arg, void *ebp )
{ {
DWORD ret; int ret;
__asm__ __volatile__ ("pushl %%ebp; pushl %3; movl %2,%%ebp; call *%%eax; popl %%ebp; popl %%ebp" __asm__ __volatile__ ("pushl %%ebp; pushl %3; movl %2,%%ebp; call *%%eax; popl %%ebp; popl %%ebp"
: "=a" (ret) : "=a" (ret)
: "0" (func), "r" (ebp), "r" (arg) : "0" (func), "r" (ebp), "r" (arg)
: "ecx", "edx", "memory" ); : "ecx", "edx", "memory" );
return ret; return ret;
} }
static inline int call_unwind_func( int (*func)(void), void *ebp )
{
int ret;
__asm__ __volatile__ ("pushl %%ebp; movl %2,%%ebp; call *%0; popl %%ebp"
: "=a" (ret)
: "0" (func), "r" (ebp)
: "ecx", "edx", "memory" );
return ret;
}
#endif #endif
static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec, static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec,
@ -109,21 +120,8 @@ __ASM_GLOBAL_FUNC(_EH_prolog,
"leal 12(%esp), %ebp\n\t" "leal 12(%esp), %ebp\n\t"
"pushl %eax\n\t" "pushl %eax\n\t"
"ret") "ret")
#endif
/******************************************************************* static void msvcrt_local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp)
* _global_unwind2 (MSVCRT.@)
*/
void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame)
{
TRACE("(%p)\n",frame);
RtlUnwind( frame, 0, 0, 0 );
}
/*******************************************************************
* _local_unwind2 (MSVCRT.@)
*/
void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel)
{ {
EXCEPTION_REGISTRATION_RECORD reg; EXCEPTION_REGISTRATION_RECORD reg;
@ -140,16 +138,34 @@ void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel)
frame->trylevel = frame->scopetable[level].previousTryLevel; frame->trylevel = frame->scopetable[level].previousTryLevel;
if (!frame->scopetable[level].lpfnFilter) if (!frame->scopetable[level].lpfnFilter)
{ {
FIXME( "__try block cleanup level %d handler %p not fully implemented\n", TRACE( "__try block cleanup level %d handler %p ebp %p\n",
level, frame->scopetable[level].lpfnHandler ); level, frame->scopetable[level].lpfnHandler, ebp );
/* FIXME: should probably set ebp to frame->_ebp */ call_unwind_func( frame->scopetable[level].lpfnHandler, ebp );
frame->scopetable[level].lpfnHandler();
} }
} }
__wine_pop_frame(&reg); __wine_pop_frame(&reg);
TRACE("unwound OK\n"); TRACE("unwound OK\n");
} }
/*******************************************************************
* _local_unwind2 (MSVCRT.@)
*/
void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel)
{
msvcrt_local_unwind2( frame, trylevel, &frame->_ebp );
}
#endif /* __i386__ */
/*******************************************************************
* _global_unwind2 (MSVCRT.@)
*/
void CDECL _global_unwind2(EXCEPTION_REGISTRATION_RECORD* frame)
{
TRACE("(%p)\n",frame);
RtlUnwind( frame, 0, 0, 0 );
}
/********************************************************************* /*********************************************************************
* _except_handler2 (MSVCRT.@) * _except_handler2 (MSVCRT.@)
*/ */
@ -172,8 +188,7 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec,
PCONTEXT context, void* dispatcher) PCONTEXT context, void* dispatcher)
{ {
#if defined(__GNUC__) && defined(__i386__) #if defined(__GNUC__) && defined(__i386__)
long retval; int retval, trylevel;
int trylevel;
EXCEPTION_POINTERS exceptPtrs; EXCEPTION_POINTERS exceptPtrs;
PSCOPETABLE pScopeTable; PSCOPETABLE pScopeTable;
@ -186,7 +201,7 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec,
if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
{ {
/* Unwinding the current frame */ /* Unwinding the current frame */
_local_unwind2(frame, TRYLEVEL_END); msvcrt_local_unwind2(frame, TRYLEVEL_END, &frame->_ebp);
TRACE("unwound current frame, returning ExceptionContinueSearch\n"); TRACE("unwound current frame, returning ExceptionContinueSearch\n");
return ExceptionContinueSearch; return ExceptionContinueSearch;
} }
@ -218,7 +233,7 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec,
{ {
/* Unwind all higher frames, this one will handle the exception */ /* Unwind all higher frames, this one will handle the exception */
_global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame); _global_unwind2((EXCEPTION_REGISTRATION_RECORD*)frame);
_local_unwind2(frame, trylevel); msvcrt_local_unwind2(frame, trylevel, &frame->_ebp);
/* Set our trylevel to the enclosing block, and call the __finally /* Set our trylevel to the enclosing block, and call the __finally
* code, which won't return * code, which won't return
@ -298,7 +313,7 @@ DEFINE_SETJMP_ENTRYPOINT(MSVCRT__setjmp)
int CDECL __regs_MSVCRT__setjmp(struct MSVCRT___JUMP_BUFFER *jmp) int CDECL __regs_MSVCRT__setjmp(struct MSVCRT___JUMP_BUFFER *jmp)
{ {
jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList; jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList;
if (jmp->Registration == TRYLEVEL_END) if (jmp->Registration == ~0UL)
jmp->TryLevel = TRYLEVEL_END; jmp->TryLevel = TRYLEVEL_END;
else else
jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel; jmp->TryLevel = ((MSVCRT_EXCEPTION_FRAME*)jmp->Registration)->trylevel;
@ -317,7 +332,7 @@ int CDECL __regs_MSVCRT__setjmp3(struct MSVCRT___JUMP_BUFFER *jmp, int nb_args,
jmp->Cookie = MSVCRT_JMP_MAGIC; jmp->Cookie = MSVCRT_JMP_MAGIC;
jmp->UnwindFunc = 0; jmp->UnwindFunc = 0;
jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList; jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList;
if (jmp->Registration == TRYLEVEL_END) if (jmp->Registration == ~0UL)
{ {
jmp->TryLevel = TRYLEVEL_END; jmp->TryLevel = TRYLEVEL_END;
} }
@ -367,8 +382,8 @@ int CDECL MSVCRT_longjmp(struct MSVCRT___JUMP_BUFFER *jmp, int retval)
unwind_func(jmp); unwind_func(jmp);
} }
else else
_local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration, msvcrt_local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration,
jmp->TryLevel); jmp->TryLevel, (void *)jmp->Ebp);
} }
if (!retval) if (!retval)
@ -382,7 +397,7 @@ int CDECL MSVCRT_longjmp(struct MSVCRT___JUMP_BUFFER *jmp, int retval)
*/ */
void __stdcall _seh_longjmp_unwind(struct MSVCRT___JUMP_BUFFER *jmp) void __stdcall _seh_longjmp_unwind(struct MSVCRT___JUMP_BUFFER *jmp)
{ {
_local_unwind2( (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, jmp->TryLevel ); msvcrt_local_unwind2( (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, jmp->TryLevel, (void *)jmp->Ebp );
} }
#endif /* i386 */ #endif /* i386 */

View File

@ -323,7 +323,7 @@
@ cdecl _kbhit() @ cdecl _kbhit()
@ cdecl _lfind(ptr ptr ptr long ptr) @ cdecl _lfind(ptr ptr ptr long ptr)
@ cdecl _loaddll(str) @ cdecl _loaddll(str)
@ cdecl _local_unwind2(ptr long) @ cdecl -i386 _local_unwind2(ptr long)
@ cdecl _lock(long) @ cdecl _lock(long)
@ cdecl _locking(long long long) @ cdecl _locking(long long long)
@ cdecl _logb( double ) @ cdecl _logb( double )