[ros-kernel] Macro SEH support, version 2 (Help needed:translating to AT&T assembler syntax)

Filip Navara xnavara at volny.cz
Sun Nov 2 18:28:54 CET 2003


I tried to do the job of translating it to AT&T syntax, but unfortunetly I
never used it and I gave up after few minutes. The already finished part is
at www.volny.cz/xnavara/sehatat.c, if anybody wants to continue with that.

Filip
----- Original Message ----- 
From: "Vizzini" <vizzini at plasmic.com>
To: "ReactOS Kernel List" <ros-kernel at reactos.com>
Sent: Sunday, November 02, 2003 7:07 AM
Subject: Re: [ros-kernel] Macro SEH support, version 2 (Help
needed:translating to AT&T assembler syntax)


> I think it is really critical to get some exception handling implemented
> in our system call handlers.  At this point, it's trivial to crash the
> whole operating system with a misbehaving user-mode app.  This macro
> system, while not optimal, will tide us over until the MinGW
> exception-handling work is complete.
>
> Are there any assembler people out there who need a weekend project?
> This isn't terribly long, but it does need somebody who knows what
> they're doing.  If you've been lurking for a while waiting to find
> something you can contribute, this might just be the ticket!  Mail the
> list or me directly if you're interested and I'll point you in the right
> direction.
>
> Nice work, Skywing.
>
>  -Vizzini
>
> On Mon, 2003-10-27 at 10:16, Skywing wrote:
> > I've done a significant amount of reworking on the macro SEH support
that I
> > introduced on the mailinglist some time ago.  It now passes every test I
can
> > throw at it with flying colors, including interoperating with VC-style
SEH.
> > This includes unwinding and nested exception handlers.  This release
fixes a
> > number of bugs with the original implementation.
> >
> > Request for help:  I don't know AT&T assembler, so somebody needs to
port
> > this if it's to be used with MinGW (which is the primary purpose for me
> > writing it).  Unless somebody is willing to lend a hand with GNU-ASM'ing
it,
> > this will probably not benefit the ReactOS project much.
> >
> > I've tried to code this as defensively as possible, so that any code in
the
> > handler or filter areas will properly run without any special knowledge
> > about the values of the stack/other registers while in an exception
handler.
> > I'm pretty sure that the macros are virtually bulletproof against the
> > compiler generating code that doesn't work inside of them, provided you
> > follow these rules: Enable frame pointer generation.  This is absolutely
> > crucial to any SEH implementation; without frame pointers, the macros
will
> > fall over and die. Preferably, exit the SEH exception handler with
> > fallthrough.  If you must exit it otherwise, you can try using the
> > ExceptCleanup() macro before leaving the handler with a return or
similar
> > statement.  Exiting the SEH handler inside the filter expression is
probably
> > a Bad Idea and may not work, as the "panic stack" will be used through
the
> > remainder of the function.
> >
> > Additionally, GetExceptionCode() and GetExceptionPointers() should be
> > available at the proper scopes.  You ought to get an undefined
identifier
> > error if you try to use them elsewhere.
> >
> > The macros work with "heap-based" SEH in order to work around the
Borland
> > patent.  There are some limitations with using this with regular
Microsoft
> > Windows (see below), but it should be no problem to modify ReactOS to
work
> > with this scheme if necessary.
> >
> > The semantics for using the macros are as follows:
> > TRY
> > {
> >   try-protected-code;
> > }
> > EXCEPT(( filter-expression )) /* Note that double parens are needed */ {
> > handler-code; } EXCEPT_END();
> >
> > Issues with "heap-based" SEH:
> > The default Microsoft RtlUnwind implementation will not call an
exception
> > handler if the exception registration is not within the threads stack
> > limits.  It would be a good idea to ensure that the ReactOS RtlUnwind
> > implementation does not have this limitation if we wish to use
"heap-based"
> > SEH and not "stack-based" SEH.
> >
> > Issues with the macros and MSVC++:
> > The VC compiler crashes if you use if(0) { code; } or goto label; {
code; }
> > label: instead of __asm jmp label; { code; } label; to prevent the
exception
> > handler from being executed by fallthrough.  I think that this is
because
> > the optimizer decides that the exception handler is unreachable and
removes
> > it, despite an existing reference to code in the handler (the label for
the
> > start of the OS-invoked SEH handler function itself).  Later this causes
the
> > compiler to crash, hence my workaround with __asm jmp
EXCEPT_EndOfExcept.
> >
> > ----- Macro definitions follow -----
> >
> > #define ExceptCleanup() { \
> > ExFreePool(EXCEPT_ExceptionPointers); \
> > __asm { \
> > __asm push eax \
> > __asm mov eax, dword ptr fs:[0x00000000] \
> > __asm mov eax, dword ptr [eax] \
> > __asm mov dword ptr fs:[0x00000000], eax \
> > __asm pop eax \
> > } \
> > }
> > #define GetExceptionCode() ((DWORD)(EXCEPT_ExceptionCode))
> > #define GetExceptionPointers()
> > ((PEXCEPTION_POINTERS)(&EXCEPT_ExceptionPointers))
> >
> > #define EH_NONCONTINUABLE 0x00000001
> > #define EH_UNWINDING 0x00000002
> > #define EH_EXIT_UNWIND 0x00000004
> > #define EH_STACK_INVALID 0x00000008
> > #define EH_NESTED_CALL 0x00000010
> > #define EH_UNWIND_CONTEXT EH_UNWINDING | EH_EXIT_UNWIND
> >
> > #define _TRY_SAVED_EBP 0x08
> > #define _TRY_SAVED_EBX 0x0c
> > #define _TRY_SAVED_ESI 0x10
> > #define _TRY_SAVED_EDI 0x14
> > #define _TRY_SAVED_ESP 0x18
> >
> > #if 0 // Enable if you don't have these in scope
> > typedef enum {
> > ExceptionContinueExecution,
> > ExceptionContinueSearch,
> > ExceptionNestedException,
> > ExceptionCollidedUnwind
> > } EXCEPTION_DISPOSITION;
> > #endif
> >
> > #define TRY { \
> > PVOID TRY_ExceptionRegistration = ExAllocatePoolWithTag(PagedPool,
> > 28, ' HES'); \
> > volatile DWORD EXCEPT_ExceptionCode; \
> > __asm { \
> > __asm push eax \
> > __asm push ecx \
> > __asm mov eax, TRY_ExceptionRegistration \
> > __asm mov ecx, dword ptr fs:[0] \
> > __asm mov dword ptr [eax+0x00], ecx \
> > __asm mov dword ptr fs:[0], eax \
> > __asm lea ecx, EXCEPT_Handler \
> > __asm mov dword ptr [eax+0x04], ecx \
> > __asm mov dword ptr [eax+_TRY_SAVED_EBP], ebp
> > \
> > __asm mov dword ptr [eax+_TRY_SAVED_EBX], ebx
> > \
> > __asm mov dword ptr [eax+_TRY_SAVED_ESI], esi
> > \
> > __asm mov dword ptr [eax+_TRY_SAVED_EDI], edi
> > \
> > __asm mov dword ptr [eax+_TRY_SAVED_ESP], esp
> > \
> > __asm add dword ptr [eax+_TRY_SAVED_ESP], 0x08
> > \
> > __asm pop ecx \
> > __asm pop eax \
> > }
> >
> > #define EXCEPT_LOCALS TYPE CONTEXT + 20
> > #define EXCEPT_CONTEXT_OFFSET 0
> > #define EXCEPT_POINTERS_OFFSET TYPE CONTEXT
> >
> >
> > #ifdef _MSC_VER
> > #pragma comment(linker, "/INCLUDE:_RtlUnwind at 16")
> > #endif
> >
> > #if 0 // Enable if not in scope
> > // RtlUnwind unwinds procedure call stack frames.
> > extern "C"
> > NTSYSAPI
> > VOID
> > NTAPI
> > RtlUnwind(
> > IN OUT PVOID TargetFrame OPTIONAL,
> > IN PVOID TargetIp OPTIONAL,
> > IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
> > IN PVOID ReturnValue
> > );
> > #endif
> >
> > #define EXCEPT(Expression) { __asm { jmp EXCEPT_EndOfExcept} \
> > volatile EXCEPTION_POINTERS EXCEPT_ExceptionPointers; \
> > EXCEPT_Handler: /* EXCEPTION_DISPOSITION __cdecl
> > handler(EXCEPTION_RECORD* ExceptionRecord, void* EstablisherFrame,
CONTEXT*
> > ContextRecord, void* DispatcherContext) */ \
> > __asm { \
> > __asm mov eax, dword ptr [esp+0x04] \
> > __asm test dword ptr
> > [eax]EXCEPTION_RECORD.ExceptionFlags, EH_UNWIND_CONTEXT | EH_NESTED_CALL
\
> > __asm je EXCEPT_DoHandler \
> > \
> > __asm xor eax, eax \
> > __asm or eax, ExceptionContinueSearch \
> > __asm ret \
> > } \
> > EXCEPT_DoHandler: /* Can't define this in inline asm macro + __asm{}
> > block, or compiler complains. */ \
> > __asm { \
> > __asm sub esp, EXCEPT_LOCALS \
> > __asm mov [esp]CONTEXT.Ebp, ebp \
> > __asm mov [esp]CONTEXT.Ebx, ebx \
> > __asm mov [esp]CONTEXT.Edi, edi \
> > __asm mov [esp]CONTEXT.Esi, esi \
> > __asm pushfd \
> > __asm pop ecx \
> > __asm mov [esp]CONTEXT.EFlags, ecx \
> > __asm mov ebp, dword ptr
> > [esp+0x08+EXCEPT_LOCALS] \
> > __asm mov ebp, dword ptr [ebp+0x08] \
> > __asm lea edx, EXCEPT_ExceptionPointers \
> > __asm mov ecx, dword ptr
> > [esp+0x04+EXCEPT_LOCALS] \
> > __asm mov
> > [edx]EXCEPTION_POINTERS.ExceptionRecord, ecx \
> > __asm mov ecx, dword ptr
> > [esp+0x0c+EXCEPT_LOCALS] \
> > __asm mov
> > [edx]EXCEPTION_POINTERS.ContextRecord, ecx \
> > __asm mov edx,
> > [edx]EXCEPTION_POINTERS.ExceptionRecord \
> > __asm mov edx,
> > [edx]EXCEPTION_RECORD.ExceptionCode \
> > __asm mov EXCEPT_ExceptionCode, edx \
> > __asm mov ebp, dword ptr
> > [esp+0x0c+EXCEPT_LOCALS] \
> > __asm mov eax, [ebp]CONTEXT.EFlags \
> > __asm push eax \
> > __asm popfd \
> > __asm mov ebp, dword ptr
> > [esp+0x08+EXCEPT_LOCALS] \
> > __asm mov ebx, dword ptr [ebp+_TRY_SAVED_EBX]
> > \
> > __asm mov esi, dword ptr [ebp+_TRY_SAVED_ESI]
> > \
> > __asm mov edi, dword ptr [ebp+_TRY_SAVED_EDI]
> > \
> > __asm mov ebp, dword ptr [ebp+_TRY_SAVED_EBP]
> > \
> > __asm cld \
> > } \
> > \
> > switch( (Expression) ) { \
> > \
> > case EXCEPTION_CONTINUE_SEARCH: \
> > ExFreePool(TRY_ExceptionRegistration); \
> > __asm { \
> > __asm mov ebp, [esp]CONTEXT.Ebp \
> > __asm mov ebx, [esp]CONTEXT.Ebx \
> > __asm mov edi, [esp]CONTEXT.Edi \
> > __asm mov esi, [esp]CONTEXT.Esi \
> > __asm add esp, EXCEPT_LOCALS \
> > __asm xor eax, eax \
> > __asm or eax, ExceptionContinueSearch
> > \
> > __asm ret \
> > } \
> > \
> > case EXCEPTION_CONTINUE_EXECUTION: \
> > ExFreePool(TRY_ExceptionRegistration); \
> > __asm { \
> > __asm mov eax, dword ptr
> > [esp+0x08+EXCEPT_LOCALS] \
> > __asm push 0 \
> > __asm push 0 \
> > __asm push
> > __ret_label_CONTINUE_EXECUTION \
> > __asm push eax \
> > __asm call dword ptr [RtlUnwind] \
> > } \
> > __ret_label_CONTINUE_EXECUTION: \
> > __asm { \
> > __asm mov ebp, [esp]CONTEXT.Ebp \
> > __asm mov ebx, [esp]CONTEXT.Ebx \
> > __asm mov edi, [esp]CONTEXT.Edi \
> > __asm mov esi, [esp]CONTEXT.Esi \
> > __asm add esp, EXCEPT_LOCALS \
> > __asm xor eax, eax \
> > __asm or eax,
> > ExceptionContinueExecution \
> > __asm ret \
> > } \
> > \
> > case EXCEPTION_EXECUTE_HANDLER: \
> > __asm { \
> > __asm pushad \
> > __asm pushfd \
> > __asm mov eax, dword ptr
> > [esp+0x08+0x04+0x20+EXCEPT_LOCALS] \
> > __asm push 0 \
> > __asm push 0 \
> > __asm push __ret_label_EXECUTE_HANDLER
> > \
> > __asm push eax \
> > __asm call dword ptr [RtlUnwind] \
> > } \
> > __ret_label_EXECUTE_HANDLER: \
> > __asm { \
> > __asm popfd \
> > __asm popad \
> > } \
> > break; \
> > \
> > default: \
> > DPRINT("SEH: Invalid disposition returned from filter
> > expression!\n"); \
> > RtlRaiseStatus(STATUS_INVALID_DISPOSITION); \
> > \
> > } \
> > \
> > __asm { \
> > __asm mov ebp, dword ptr
> > [esp+0x08+EXCEPT_LOCALS] \
> > __asm mov ebx, dword ptr [ebp+_TRY_SAVED_EBX]
> > \
> > __asm mov esi, dword ptr [ebp+_TRY_SAVED_ESI]
> > \
> > __asm mov edi, dword ptr [ebp+_TRY_SAVED_EDI]
> > \
> > __asm mov esp, dword ptr [ebp+_TRY_SAVED_ESP]
> > \
> > __asm mov ebp, dword ptr [ebp+0x08] \
> > } }
> >
> > -- End --
> >
> >
> > _______________________________________________
> > Ros-kernel mailing list
> > Ros-kernel at reactos.com
> > http://reactos.geldorp.nl:8080/mailman/listinfo/ros-kernel
> >
>
> _______________________________________________
> Ros-kernel mailing list
> Ros-kernel at reactos.com
> http://reactos.geldorp.nl:8080/mailman/listinfo/ros-kernel
>



More information about the Ros-kernel mailing list