From 72bc7429e496b3d9a45806eb95f1be2461731604 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 8 Jun 2007 12:56:19 +0200 Subject: [PATCH] msvcrt: Set the correct ebp value before calling the local unwind handler. --- dlls/msvcrt/except.c | 73 +++++++++++++++++++++++++---------------- dlls/msvcrt/msvcrt.spec | 2 +- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/dlls/msvcrt/except.c b/dlls/msvcrt/except.c index c9240889034..aef51337904 100644 --- a/dlls/msvcrt/except.c +++ b/dlls/msvcrt/except.c @@ -71,15 +71,26 @@ static inline void call_finally_block( void *code_block, void *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" : "=a" (ret) : "0" (func), "r" (ebp), "r" (arg) : "ecx", "edx", "memory" ); 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 static DWORD MSVCRT_nested_handler(PEXCEPTION_RECORD rec, @@ -109,21 +120,8 @@ __ASM_GLOBAL_FUNC(_EH_prolog, "leal 12(%esp), %ebp\n\t" "pushl %eax\n\t" "ret") -#endif -/******************************************************************* - * _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) +static void msvcrt_local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel, void *ebp) { EXCEPTION_REGISTRATION_RECORD reg; @@ -140,16 +138,34 @@ void CDECL _local_unwind2(MSVCRT_EXCEPTION_FRAME* frame, int trylevel) frame->trylevel = frame->scopetable[level].previousTryLevel; if (!frame->scopetable[level].lpfnFilter) { - FIXME( "__try block cleanup level %d handler %p not fully implemented\n", - level, frame->scopetable[level].lpfnHandler ); - /* FIXME: should probably set ebp to frame->_ebp */ - frame->scopetable[level].lpfnHandler(); + TRACE( "__try block cleanup level %d handler %p ebp %p\n", + level, frame->scopetable[level].lpfnHandler, ebp ); + call_unwind_func( frame->scopetable[level].lpfnHandler, ebp ); } } __wine_pop_frame(®); 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.@) */ @@ -172,8 +188,7 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec, PCONTEXT context, void* dispatcher) { #if defined(__GNUC__) && defined(__i386__) - long retval; - int trylevel; + int retval, trylevel; EXCEPTION_POINTERS exceptPtrs; PSCOPETABLE pScopeTable; @@ -186,7 +201,7 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec, if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)) { /* Unwinding the current frame */ - _local_unwind2(frame, TRYLEVEL_END); + msvcrt_local_unwind2(frame, TRYLEVEL_END, &frame->_ebp); TRACE("unwound current frame, returning ExceptionContinueSearch\n"); return ExceptionContinueSearch; } @@ -218,7 +233,7 @@ int CDECL _except_handler3(PEXCEPTION_RECORD rec, { /* Unwind all higher frames, this one will handle the exception */ _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 * code, which won't return @@ -298,7 +313,7 @@ DEFINE_SETJMP_ENTRYPOINT(MSVCRT__setjmp) int CDECL __regs_MSVCRT__setjmp(struct MSVCRT___JUMP_BUFFER *jmp) { jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList; - if (jmp->Registration == TRYLEVEL_END) + if (jmp->Registration == ~0UL) jmp->TryLevel = TRYLEVEL_END; else 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->UnwindFunc = 0; jmp->Registration = (unsigned long)NtCurrentTeb()->Tib.ExceptionList; - if (jmp->Registration == TRYLEVEL_END) + if (jmp->Registration == ~0UL) { jmp->TryLevel = TRYLEVEL_END; } @@ -367,8 +382,8 @@ int CDECL MSVCRT_longjmp(struct MSVCRT___JUMP_BUFFER *jmp, int retval) unwind_func(jmp); } else - _local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration, - jmp->TryLevel); + msvcrt_local_unwind2((MSVCRT_EXCEPTION_FRAME*)jmp->Registration, + jmp->TryLevel, (void *)jmp->Ebp); } 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) { - _local_unwind2( (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, jmp->TryLevel ); + msvcrt_local_unwind2( (MSVCRT_EXCEPTION_FRAME *)jmp->Registration, jmp->TryLevel, (void *)jmp->Ebp ); } #endif /* i386 */ diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 66f2ededfb0..cb427ab23b5 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -323,7 +323,7 @@ @ cdecl _kbhit() @ cdecl _lfind(ptr ptr ptr long ptr) @ cdecl _loaddll(str) -@ cdecl _local_unwind2(ptr long) +@ cdecl -i386 _local_unwind2(ptr long) @ cdecl _lock(long) @ cdecl _locking(long long long) @ cdecl _logb( double )