added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2008 KJK::Hyperion
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
copy of this software and associated documentation files (the "Software"),
|
|
|
|
to deal in the Software without restriction, including without limitation
|
|
|
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
DEALINGS IN THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2008-12-23 02:45:25 +00:00
|
|
|
#define _NTSYSTEM_ /* removes dllimport attribute from RtlUnwind */
|
|
|
|
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
#define STRICT
|
2013-09-22 20:55:48 +00:00
|
|
|
#include <windef.h>
|
|
|
|
#include <stdarg.h>
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
|
|
|
#include <pseh/pseh2.h>
|
|
|
|
#include <excpt.h>
|
2008-12-23 02:45:25 +00:00
|
|
|
#include <intrin.h>
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
2008-12-14 02:55:50 +00:00
|
|
|
#ifndef EXCEPTION_EXIT_UNWIND
|
|
|
|
#define EXCEPTION_EXIT_UNWIND 4
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EXCEPTION_UNWINDING
|
|
|
|
#define EXCEPTION_UNWINDING 2
|
|
|
|
#endif
|
|
|
|
|
2009-01-09 16:36:21 +00:00
|
|
|
extern DECLSPEC_NORETURN int __SEH2Handle(void *, void *, void *, void *, void *, void *);
|
2008-12-14 02:55:50 +00:00
|
|
|
extern int __cdecl __SEH2FrameHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
|
2008-12-30 04:00:45 +00:00
|
|
|
extern int __cdecl __SEH2UnwindHandler(struct _EXCEPTION_RECORD *, void *, struct _CONTEXT *, void *);
|
2008-12-14 02:55:50 +00:00
|
|
|
|
2009-08-16 16:40:52 +00:00
|
|
|
typedef struct __SEHTrampoline
|
|
|
|
{
|
|
|
|
unsigned char STR_MovEcx;
|
|
|
|
unsigned char * STR_Closure;
|
|
|
|
unsigned char STR_Jmp;
|
|
|
|
unsigned char * STR_Function;
|
|
|
|
}
|
|
|
|
__attribute__((packed))
|
|
|
|
_SEHTrampoline_t;
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
int _SEHIsTrampoline(_SEHTrampoline_t * trampoline_)
|
|
|
|
{
|
|
|
|
return trampoline_->STR_MovEcx == 0xb9 && trampoline_->STR_Jmp == 0xe9;
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
void * _SEHFunctionFromTrampoline(_SEHTrampoline_t * trampoline_)
|
|
|
|
{
|
|
|
|
return (int)(trampoline_ + 1) + trampoline_->STR_Function;
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
void * _SEHClosureFromTrampoline(_SEHTrampoline_t * trampoline_)
|
|
|
|
{
|
|
|
|
return trampoline_->STR_Closure;
|
|
|
|
}
|
|
|
|
|
2008-12-23 02:45:25 +00:00
|
|
|
FORCEINLINE
|
|
|
|
_SEH2Registration_t * __cdecl _SEH2CurrentRegistration(void)
|
|
|
|
{
|
|
|
|
return (_SEH2Registration_t *)__readfsdword(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
void __cdecl __SEH2EnterFrame(_SEH2Registration_t * frame)
|
|
|
|
{
|
|
|
|
frame->SER_Prev = _SEH2CurrentRegistration();
|
|
|
|
__writefsdword(0, (unsigned long)frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
FORCEINLINE
|
|
|
|
void __cdecl __SEH2LeaveFrame(void)
|
|
|
|
{
|
|
|
|
__writefsdword(0, (unsigned long)_SEH2CurrentRegistration()->SER_Prev);
|
|
|
|
}
|
|
|
|
|
2008-12-20 23:27:17 +00:00
|
|
|
FORCEINLINE
|
|
|
|
void _SEH2GlobalUnwind(void * target)
|
|
|
|
{
|
|
|
|
__asm__ __volatile__
|
|
|
|
(
|
2012-02-16 07:37:27 +00:00
|
|
|
"push %%ebp\n\t"
|
|
|
|
"push $0\n\t"
|
|
|
|
"push $0\n\t"
|
|
|
|
"push $Return%=\n\t"
|
|
|
|
"push %[target]\n\t"
|
2008-12-20 23:27:17 +00:00
|
|
|
"call %c[RtlUnwind]\n"
|
2012-02-16 07:37:27 +00:00
|
|
|
"Return%=:\n\t"
|
|
|
|
"pop %%ebp" :
|
2008-12-20 23:27:17 +00:00
|
|
|
:
|
|
|
|
[target] "g" (target), [RtlUnwind] "g" (&RtlUnwind) :
|
|
|
|
"eax", "ebx", "ecx", "edx", "esi", "edi", "flags", "memory"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2008-12-23 02:45:25 +00:00
|
|
|
static
|
|
|
|
__SEH_EXCEPT_RET _SEH2Except(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel, struct _EXCEPTION_POINTERS * ep)
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
{
|
Supersedes r38084. Take three
modified include/reactos/libs/pseh/pseh2.h
modified lib/pseh/framebased-gcchack.c
modified lib/pseh/i386/framebased-gcchack.S
Disassemble trampolines in the library, instead of the macros. Results in better, smaller code. As a side effect, PSEH no longer requires a trampoline for nested functions - which results in even better, even smaller code in many common cases where the nested functions don't use any variables from the containing function
Simulate a no-op setjmp so that GCC correctly handles variables in registers, instead of surprise-corrupting random variables in random conditions
Save EBP and ESP every time a _SEH2_TRY/_SEH2_EXCEPT is entered, instead of only the first time. Probably not entirely correct yet
Don't generate a nested function for a _SEH2_EXCEPT() filter expression if the value is a compile-time constant: convert the value to (void *)0, (void *)1 or (void *)-1, and set that as the filter, instead (like Visual C++ does, incidentally)
If a _SEH2_EXCEPT() filter expression is a compile-time constant evaluating to EXCEPTION_CONTINUE_EXECUTION or EXCEPTION_CONTINUE_SEARCH, allow GCC to optimize out the body of the _SEH2_EXCEPT (because it'd be unreachable). This should really result in a compile-time warning, but #pragma message is unsupported in GCC 4.1.3
Let _SEH2_EXCEPT() accept a comma expression as filter expression (e.g. _SEH2_EXCEPT(MessageBox(...), EXCEPTION_EXECUTE_HANDLER) instead of _SEH2_EXCEPT((MessageBox(...), EXCEPTION_EXECUTE_HANDLER)))
Small optimizations in PSEH library
Clean up GCC hacks
Remove currently unused PSEH 3 hacks
svn path=/trunk/; revision=38197
2008-12-20 13:05:57 +00:00
|
|
|
void * filter = trylevel->ST_Filter;
|
|
|
|
void * context = NULL;
|
2008-12-23 02:45:25 +00:00
|
|
|
__SEH_EXCEPT_RET ret;
|
Supersedes r38084. Take three
modified include/reactos/libs/pseh/pseh2.h
modified lib/pseh/framebased-gcchack.c
modified lib/pseh/i386/framebased-gcchack.S
Disassemble trampolines in the library, instead of the macros. Results in better, smaller code. As a side effect, PSEH no longer requires a trampoline for nested functions - which results in even better, even smaller code in many common cases where the nested functions don't use any variables from the containing function
Simulate a no-op setjmp so that GCC correctly handles variables in registers, instead of surprise-corrupting random variables in random conditions
Save EBP and ESP every time a _SEH2_TRY/_SEH2_EXCEPT is entered, instead of only the first time. Probably not entirely correct yet
Don't generate a nested function for a _SEH2_EXCEPT() filter expression if the value is a compile-time constant: convert the value to (void *)0, (void *)1 or (void *)-1, and set that as the filter, instead (like Visual C++ does, incidentally)
If a _SEH2_EXCEPT() filter expression is a compile-time constant evaluating to EXCEPTION_CONTINUE_EXECUTION or EXCEPTION_CONTINUE_SEARCH, allow GCC to optimize out the body of the _SEH2_EXCEPT (because it'd be unreachable). This should really result in a compile-time warning, but #pragma message is unsupported in GCC 4.1.3
Let _SEH2_EXCEPT() accept a comma expression as filter expression (e.g. _SEH2_EXCEPT(MessageBox(...), EXCEPTION_EXECUTE_HANDLER) instead of _SEH2_EXCEPT((MessageBox(...), EXCEPTION_EXECUTE_HANDLER)))
Small optimizations in PSEH library
Clean up GCC hacks
Remove currently unused PSEH 3 hacks
svn path=/trunk/; revision=38197
2008-12-20 13:05:57 +00:00
|
|
|
|
|
|
|
if(filter == (void *)0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if(filter == (void *)1)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if(filter == (void *)-1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if(_SEHIsTrampoline((_SEHTrampoline_t *)filter))
|
|
|
|
{
|
|
|
|
context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)filter);
|
|
|
|
filter = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)filter);
|
|
|
|
}
|
|
|
|
|
2008-12-23 02:45:25 +00:00
|
|
|
__asm__ __volatile__
|
|
|
|
(
|
2012-02-16 07:37:27 +00:00
|
|
|
"push %[ep]\n\t"
|
|
|
|
"push %[frame]\n\t"
|
|
|
|
"call *%[filter]\n\t"
|
|
|
|
"pop %%edx\n\t"
|
|
|
|
"pop %%edx" :
|
2008-12-23 02:45:25 +00:00
|
|
|
[ret] "=a" (ret) :
|
2012-02-16 07:37:27 +00:00
|
|
|
"c" (context), [filter] "r" (filter), [frame] "r" (frame), [ep] "r" (ep) :
|
2008-12-23 02:45:25 +00:00
|
|
|
"edx", "flags", "memory"
|
|
|
|
);
|
|
|
|
|
|
|
|
return ret;
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
}
|
|
|
|
|
2008-12-23 02:45:25 +00:00
|
|
|
static
|
2008-11-24 01:38:43 +00:00
|
|
|
void _SEH2Finally(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
{
|
Supersedes r38084. Take three
modified include/reactos/libs/pseh/pseh2.h
modified lib/pseh/framebased-gcchack.c
modified lib/pseh/i386/framebased-gcchack.S
Disassemble trampolines in the library, instead of the macros. Results in better, smaller code. As a side effect, PSEH no longer requires a trampoline for nested functions - which results in even better, even smaller code in many common cases where the nested functions don't use any variables from the containing function
Simulate a no-op setjmp so that GCC correctly handles variables in registers, instead of surprise-corrupting random variables in random conditions
Save EBP and ESP every time a _SEH2_TRY/_SEH2_EXCEPT is entered, instead of only the first time. Probably not entirely correct yet
Don't generate a nested function for a _SEH2_EXCEPT() filter expression if the value is a compile-time constant: convert the value to (void *)0, (void *)1 or (void *)-1, and set that as the filter, instead (like Visual C++ does, incidentally)
If a _SEH2_EXCEPT() filter expression is a compile-time constant evaluating to EXCEPTION_CONTINUE_EXECUTION or EXCEPTION_CONTINUE_SEARCH, allow GCC to optimize out the body of the _SEH2_EXCEPT (because it'd be unreachable). This should really result in a compile-time warning, but #pragma message is unsupported in GCC 4.1.3
Let _SEH2_EXCEPT() accept a comma expression as filter expression (e.g. _SEH2_EXCEPT(MessageBox(...), EXCEPTION_EXECUTE_HANDLER) instead of _SEH2_EXCEPT((MessageBox(...), EXCEPTION_EXECUTE_HANDLER)))
Small optimizations in PSEH library
Clean up GCC hacks
Remove currently unused PSEH 3 hacks
svn path=/trunk/; revision=38197
2008-12-20 13:05:57 +00:00
|
|
|
if(trylevel->ST_Filter == NULL && trylevel->ST_Body != NULL)
|
|
|
|
{
|
|
|
|
void * body = trylevel->ST_Body;
|
|
|
|
void * context = NULL;
|
|
|
|
|
|
|
|
if(_SEHIsTrampoline((_SEHTrampoline_t *)body))
|
|
|
|
{
|
|
|
|
context = _SEHClosureFromTrampoline((_SEHTrampoline_t *)body);
|
|
|
|
body = _SEHFunctionFromTrampoline((_SEHTrampoline_t *)body);
|
|
|
|
}
|
|
|
|
|
2012-02-16 07:37:27 +00:00
|
|
|
__asm__ __volatile__("call *%1" : : "c" (context), "r" (body) : "eax", "edx", "flags", "memory");
|
Supersedes r38084. Take three
modified include/reactos/libs/pseh/pseh2.h
modified lib/pseh/framebased-gcchack.c
modified lib/pseh/i386/framebased-gcchack.S
Disassemble trampolines in the library, instead of the macros. Results in better, smaller code. As a side effect, PSEH no longer requires a trampoline for nested functions - which results in even better, even smaller code in many common cases where the nested functions don't use any variables from the containing function
Simulate a no-op setjmp so that GCC correctly handles variables in registers, instead of surprise-corrupting random variables in random conditions
Save EBP and ESP every time a _SEH2_TRY/_SEH2_EXCEPT is entered, instead of only the first time. Probably not entirely correct yet
Don't generate a nested function for a _SEH2_EXCEPT() filter expression if the value is a compile-time constant: convert the value to (void *)0, (void *)1 or (void *)-1, and set that as the filter, instead (like Visual C++ does, incidentally)
If a _SEH2_EXCEPT() filter expression is a compile-time constant evaluating to EXCEPTION_CONTINUE_EXECUTION or EXCEPTION_CONTINUE_SEARCH, allow GCC to optimize out the body of the _SEH2_EXCEPT (because it'd be unreachable). This should really result in a compile-time warning, but #pragma message is unsupported in GCC 4.1.3
Let _SEH2_EXCEPT() accept a comma expression as filter expression (e.g. _SEH2_EXCEPT(MessageBox(...), EXCEPTION_EXECUTE_HANDLER) instead of _SEH2_EXCEPT((MessageBox(...), EXCEPTION_EXECUTE_HANDLER)))
Small optimizations in PSEH library
Clean up GCC hacks
Remove currently unused PSEH 3 hacks
svn path=/trunk/; revision=38197
2008-12-20 13:05:57 +00:00
|
|
|
}
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
}
|
|
|
|
|
2008-12-30 04:00:45 +00:00
|
|
|
typedef struct __SEH2UnwindFrame
|
|
|
|
{
|
|
|
|
_SEH2Registration_t SUF_Registration;
|
|
|
|
_SEH2Frame_t * SUF_Frame;
|
|
|
|
volatile _SEH2TryLevel_t * SUF_TargetTryLevel;
|
|
|
|
}
|
|
|
|
_SEH2UnwindFrame_t;
|
|
|
|
|
|
|
|
static void _SEH2LocalUnwind(_SEH2Frame_t *, volatile _SEH2TryLevel_t *);
|
|
|
|
|
2008-12-14 02:55:50 +00:00
|
|
|
extern
|
2008-12-30 04:00:45 +00:00
|
|
|
int __cdecl _SEH2UnwindHandler
|
2008-12-14 02:55:50 +00:00
|
|
|
(
|
|
|
|
struct _EXCEPTION_RECORD * ExceptionRecord,
|
|
|
|
void * EstablisherFrame,
|
|
|
|
struct _CONTEXT * ContextRecord,
|
|
|
|
void * DispatcherContext
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
|
2008-12-30 04:00:45 +00:00
|
|
|
{
|
|
|
|
_SEH2UnwindFrame_t * unwindframe = CONTAINING_RECORD(EstablisherFrame, _SEH2UnwindFrame_t, SUF_Registration);
|
|
|
|
_SEH2LocalUnwind(unwindframe->SUF_Frame, unwindframe->SUF_TargetTryLevel);
|
|
|
|
*((void **)DispatcherContext) = EstablisherFrame;
|
|
|
|
return ExceptionCollidedUnwind;
|
|
|
|
}
|
2008-12-14 02:55:50 +00:00
|
|
|
|
2008-12-30 04:00:45 +00:00
|
|
|
return ExceptionContinueSearch;
|
2008-12-14 02:55:50 +00:00
|
|
|
}
|
|
|
|
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
static
|
2008-11-24 01:38:43 +00:00
|
|
|
void _SEH2LocalUnwind(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * dsttrylevel)
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
{
|
2008-11-24 01:38:43 +00:00
|
|
|
volatile _SEH2TryLevel_t * trylevel;
|
2008-12-30 04:00:45 +00:00
|
|
|
_SEH2UnwindFrame_t unwindframe;
|
|
|
|
|
|
|
|
unwindframe.SUF_Frame = frame;
|
|
|
|
unwindframe.SUF_TargetTryLevel = dsttrylevel;
|
2008-12-14 02:55:50 +00:00
|
|
|
|
2008-12-30 04:00:45 +00:00
|
|
|
unwindframe.SUF_Registration.SER_Handler = &__SEH2UnwindHandler;
|
|
|
|
__SEH2EnterFrame(&unwindframe.SUF_Registration);
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
|
|
|
for(trylevel = frame->SF_TopTryLevel; trylevel && trylevel != dsttrylevel; trylevel = trylevel->ST_Next)
|
2008-12-30 04:00:45 +00:00
|
|
|
{
|
|
|
|
frame->SF_TopTryLevel = trylevel->ST_Next;
|
Supersedes r38084. Take three
modified include/reactos/libs/pseh/pseh2.h
modified lib/pseh/framebased-gcchack.c
modified lib/pseh/i386/framebased-gcchack.S
Disassemble trampolines in the library, instead of the macros. Results in better, smaller code. As a side effect, PSEH no longer requires a trampoline for nested functions - which results in even better, even smaller code in many common cases where the nested functions don't use any variables from the containing function
Simulate a no-op setjmp so that GCC correctly handles variables in registers, instead of surprise-corrupting random variables in random conditions
Save EBP and ESP every time a _SEH2_TRY/_SEH2_EXCEPT is entered, instead of only the first time. Probably not entirely correct yet
Don't generate a nested function for a _SEH2_EXCEPT() filter expression if the value is a compile-time constant: convert the value to (void *)0, (void *)1 or (void *)-1, and set that as the filter, instead (like Visual C++ does, incidentally)
If a _SEH2_EXCEPT() filter expression is a compile-time constant evaluating to EXCEPTION_CONTINUE_EXECUTION or EXCEPTION_CONTINUE_SEARCH, allow GCC to optimize out the body of the _SEH2_EXCEPT (because it'd be unreachable). This should really result in a compile-time warning, but #pragma message is unsupported in GCC 4.1.3
Let _SEH2_EXCEPT() accept a comma expression as filter expression (e.g. _SEH2_EXCEPT(MessageBox(...), EXCEPTION_EXECUTE_HANDLER) instead of _SEH2_EXCEPT((MessageBox(...), EXCEPTION_EXECUTE_HANDLER)))
Small optimizations in PSEH library
Clean up GCC hacks
Remove currently unused PSEH 3 hacks
svn path=/trunk/; revision=38197
2008-12-20 13:05:57 +00:00
|
|
|
_SEH2Finally(frame, trylevel);
|
2008-12-30 04:00:45 +00:00
|
|
|
}
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
2008-12-14 02:55:50 +00:00
|
|
|
__SEH2LeaveFrame();
|
|
|
|
}
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
2008-12-14 02:55:50 +00:00
|
|
|
static DECLSPEC_NORETURN
|
2008-11-24 01:38:43 +00:00
|
|
|
void _SEH2Handle(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
{
|
2009-01-09 16:36:21 +00:00
|
|
|
volatile _SEH2HandleTryLevel_t * fulltrylevel = CONTAINING_RECORD(trylevel, _SEH2HandleTryLevel_t, SHT_Common);
|
|
|
|
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
_SEH2GlobalUnwind(frame);
|
2009-01-09 16:36:21 +00:00
|
|
|
_SEH2LocalUnwind(frame, &fulltrylevel->SHT_Common);
|
2009-07-08 20:32:50 +00:00
|
|
|
frame->SF_TopTryLevel = fulltrylevel->SHT_Common.ST_Next;
|
2009-01-09 16:36:21 +00:00
|
|
|
|
|
|
|
__SEH2Handle
|
|
|
|
(
|
|
|
|
fulltrylevel->SHT_Common.ST_Body,
|
|
|
|
fulltrylevel->SHT_Esp,
|
|
|
|
fulltrylevel->SHT_Ebp,
|
|
|
|
fulltrylevel->SHT_Ebx,
|
|
|
|
fulltrylevel->SHT_Esi,
|
|
|
|
fulltrylevel->SHT_Edi
|
|
|
|
);
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
}
|
|
|
|
|
2008-12-14 02:55:50 +00:00
|
|
|
extern
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
int __cdecl _SEH2FrameHandler
|
|
|
|
(
|
|
|
|
struct _EXCEPTION_RECORD * ExceptionRecord,
|
|
|
|
void * EstablisherFrame,
|
|
|
|
struct _CONTEXT * ContextRecord,
|
|
|
|
void * DispatcherContext
|
|
|
|
)
|
|
|
|
{
|
2008-11-24 01:38:43 +00:00
|
|
|
_SEH2Frame_t * frame;
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
|
|
|
frame = EstablisherFrame;
|
|
|
|
|
|
|
|
/* Unwinding */
|
2008-12-14 02:55:50 +00:00
|
|
|
if(ExceptionRecord->ExceptionFlags & (EXCEPTION_EXIT_UNWIND | EXCEPTION_UNWINDING))
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
{
|
|
|
|
_SEH2LocalUnwind(frame, NULL);
|
|
|
|
}
|
|
|
|
/* Handling */
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int ret = 0;
|
2008-11-24 01:38:43 +00:00
|
|
|
volatile _SEH2TryLevel_t * trylevel;
|
Supersedes r38084. Take three
modified include/reactos/libs/pseh/pseh2.h
modified lib/pseh/framebased-gcchack.c
modified lib/pseh/i386/framebased-gcchack.S
Disassemble trampolines in the library, instead of the macros. Results in better, smaller code. As a side effect, PSEH no longer requires a trampoline for nested functions - which results in even better, even smaller code in many common cases where the nested functions don't use any variables from the containing function
Simulate a no-op setjmp so that GCC correctly handles variables in registers, instead of surprise-corrupting random variables in random conditions
Save EBP and ESP every time a _SEH2_TRY/_SEH2_EXCEPT is entered, instead of only the first time. Probably not entirely correct yet
Don't generate a nested function for a _SEH2_EXCEPT() filter expression if the value is a compile-time constant: convert the value to (void *)0, (void *)1 or (void *)-1, and set that as the filter, instead (like Visual C++ does, incidentally)
If a _SEH2_EXCEPT() filter expression is a compile-time constant evaluating to EXCEPTION_CONTINUE_EXECUTION or EXCEPTION_CONTINUE_SEARCH, allow GCC to optimize out the body of the _SEH2_EXCEPT (because it'd be unreachable). This should really result in a compile-time warning, but #pragma message is unsupported in GCC 4.1.3
Let _SEH2_EXCEPT() accept a comma expression as filter expression (e.g. _SEH2_EXCEPT(MessageBox(...), EXCEPTION_EXECUTE_HANDLER) instead of _SEH2_EXCEPT((MessageBox(...), EXCEPTION_EXECUTE_HANDLER)))
Small optimizations in PSEH library
Clean up GCC hacks
Remove currently unused PSEH 3 hacks
svn path=/trunk/; revision=38197
2008-12-20 13:05:57 +00:00
|
|
|
EXCEPTION_POINTERS ep;
|
|
|
|
|
|
|
|
ep.ExceptionRecord = ExceptionRecord;
|
|
|
|
ep.ContextRecord = ContextRecord;
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
|
|
|
frame->SF_Code = ExceptionRecord->ExceptionCode;
|
|
|
|
|
|
|
|
for(trylevel = frame->SF_TopTryLevel; trylevel != NULL; trylevel = trylevel->ST_Next)
|
|
|
|
{
|
2008-12-23 02:45:25 +00:00
|
|
|
ret = _SEH2Except(frame, trylevel, &ep);
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
|
Supersedes r38084. Take three
modified include/reactos/libs/pseh/pseh2.h
modified lib/pseh/framebased-gcchack.c
modified lib/pseh/i386/framebased-gcchack.S
Disassemble trampolines in the library, instead of the macros. Results in better, smaller code. As a side effect, PSEH no longer requires a trampoline for nested functions - which results in even better, even smaller code in many common cases where the nested functions don't use any variables from the containing function
Simulate a no-op setjmp so that GCC correctly handles variables in registers, instead of surprise-corrupting random variables in random conditions
Save EBP and ESP every time a _SEH2_TRY/_SEH2_EXCEPT is entered, instead of only the first time. Probably not entirely correct yet
Don't generate a nested function for a _SEH2_EXCEPT() filter expression if the value is a compile-time constant: convert the value to (void *)0, (void *)1 or (void *)-1, and set that as the filter, instead (like Visual C++ does, incidentally)
If a _SEH2_EXCEPT() filter expression is a compile-time constant evaluating to EXCEPTION_CONTINUE_EXECUTION or EXCEPTION_CONTINUE_SEARCH, allow GCC to optimize out the body of the _SEH2_EXCEPT (because it'd be unreachable). This should really result in a compile-time warning, but #pragma message is unsupported in GCC 4.1.3
Let _SEH2_EXCEPT() accept a comma expression as filter expression (e.g. _SEH2_EXCEPT(MessageBox(...), EXCEPTION_EXECUTE_HANDLER) instead of _SEH2_EXCEPT((MessageBox(...), EXCEPTION_EXECUTE_HANDLER)))
Small optimizations in PSEH library
Clean up GCC hacks
Remove currently unused PSEH 3 hacks
svn path=/trunk/; revision=38197
2008-12-20 13:05:57 +00:00
|
|
|
if(ret < 0)
|
|
|
|
return ExceptionContinueExecution;
|
|
|
|
else if(ret > 0)
|
|
|
|
_SEH2Handle(frame, trylevel);
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ExceptionContinueSearch;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern
|
2008-11-24 01:38:43 +00:00
|
|
|
void __cdecl _SEH2EnterFrame(_SEH2Frame_t * frame)
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
{
|
2008-12-14 02:55:50 +00:00
|
|
|
frame->SF_Registration.SER_Handler = __SEH2FrameHandler;
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
frame->SF_Code = 0;
|
2008-12-14 02:55:50 +00:00
|
|
|
__SEH2EnterFrame(&frame->SF_Registration);
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
}
|
|
|
|
|
2009-01-09 16:36:21 +00:00
|
|
|
extern
|
|
|
|
int __cdecl _SEH2EnterFrameAndTrylevel(_SEH2Frame_t * frame, volatile _SEH2TryLevel_t * trylevel)
|
|
|
|
{
|
|
|
|
frame->SF_TopTryLevel = trylevel;
|
|
|
|
_SEH2EnterFrame(frame);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-11-26 16:03:12 +00:00
|
|
|
extern
|
|
|
|
void __cdecl _SEH2LeaveFrame(void)
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
{
|
2008-11-26 16:03:12 +00:00
|
|
|
__SEH2LeaveFrame();
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
}
|
|
|
|
|
2008-11-12 20:39:18 +00:00
|
|
|
extern
|
|
|
|
void __cdecl _SEH2Return(void)
|
|
|
|
{
|
2008-11-24 01:38:43 +00:00
|
|
|
_SEH2LocalUnwind(CONTAINING_RECORD(_SEH2CurrentRegistration(), _SEH2Frame_t, SF_Registration), NULL);
|
2008-11-12 20:39:18 +00:00
|
|
|
_SEH2LeaveFrame();
|
|
|
|
}
|
|
|
|
|
added include/reactos/libs/pseh/pseh2.h
added lib/pseh/framebased-gcchack.c
added lib/pseh/i386/framebased-gcchack.S
modified lib/pseh/pseh.rbuild
Introducing PSEH 2.0. It only wants to be loved. Highlights of this version:
- PSEH 2.0 syntax is 99% compatible with native SEH syntax
- PSEH 2.0 binary code a vast improvement over 1.1 - no more setjmp, no bogus loops, no weird optimizer behavior
PSEH 2.0 is a horrible, GCC-only, x86-only hack. It makes several non-portable assumptions and hey, did you know __builtin_frame_address(0) is *not* the same thing as EBP? Overall, it must be a world record for compiler abuse
PSEH 2.0 is, sadly, not binary-compatible with PSEH 1.1, although I will almost certainly unify the implementation at a later time
PSEH 2.0 needs testers. And love.
Not implemented yet: returning from a SEH block (i.e. _SEH2_YIELD())
Example of 2.0 syntax (yes, _SEH2_END is unavoidable):
_SEH2_TRY
{
_SEH2_TRY
{
/* ... */
}
_SEH2_EXCEPT((/* ... */))
{
/* ... */
}
_SEH2_END;
}
_SEH2_FINALLY
{
/* ... */
}
_SEH2_END;
--
Happy early birthday, Aleksey.
svn path=/trunk/; revision=37315
2008-11-12 19:52:16 +00:00
|
|
|
/* EOF */
|