msvcrt: Set the correct ebp value before calling the local unwind handler.
This commit is contained in:
parent
abc5fefada
commit
72bc7429e4
|
@ -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(®);
|
__wine_pop_frame(®);
|
||||||
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 */
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
Loading…
Reference in New Issue