[ros-kernel] Macro SEH support ported - sort of

Filip Navara xnavara at volny.cz
Wed Nov 5 17:03:27 CET 2003


I fired up too fast this morning. Now the code is more correct and compiles
without errors, but it doesn't work. Feel free to continue and find out
what's wrong.

Thanks
Filip
----- Original Message ----- 
From: "KJK::Hyperion" <noog at libero.it>
To: <ros-kernel at reactos.com>
Sent: Wednesday, November 05, 2003 1:32 AM
Subject: [ros-kernel] Macro SEH support ported - sort of


> I have ported Skywing's macros for SEH support to GCC. The port is
> incomplete mainly because of what appears to be a GCC bug (the "g" and "i"
> constraints assembling an immediate when they should be assembling an
> offset), and because I don't know how to refer to a C label from inline
> assembly. The code I've produced so far is attached. If anyone knows the
> answer, he's welcome


----------------------------------------------------------------------------
----


> _______________________________________________
> Ros-kernel mailing list
> Ros-kernel at reactos.com
> http://reactos.geldorp.nl:8080/mailman/listinfo/ros-kernel
-------------- next part --------------
#include <stdio.h>
#include <stddef.h>
#include <windows.h>

/* NOTE: change into whatever allocation model you like */
#define SEH_Alloc(SIZE__) (alloca(SIZE__))
#define SEH_Free(PTR__) ((void)(PTR__))

#define SEH_DbgPrint(STR__) (OutputDebugStringA((STR__)))
#define SEH_RaiseStatus(STATUS__) \
 (RaiseException((STATUS__), EXCEPTION_NONCONTINUABLE, 0, NULL))

STDAPI_(VOID) RtlUnwind
(
 IN OUT PVOID TargetFrame OPTIONAL,
 IN PVOID TargetIp OPTIONAL,
 IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL,
 IN PVOID ReturnValue
);

/* BEGIN */
/* to be moved in excpt.h */
enum
{
 ExceptionContinueExecution,
 ExceptionContinueSearch,
 ExceptionNestedException,
 ExceptionCollidedUnwind
}
EXCEPTION_DISPOSITION;

#define GetExceptionCode() (_exception_code())
#define exception_code()   (_exception_code())

#define GetExceptionInformation() \
 ((struct _EXCEPTION_POINTERS *)_exception_info())

#define exception_info() \
 ((struct _EXCEPTION_POINTERS *)_exception_info())

#undef AbnormalTermination
#define AbnormalTermination()  (_abnormal_termination())
#define abnormal_termination() (_abnormal_termination())

#define _exception_code() ((unsigned long)(EXCEPT_ExceptionCode))
#define _exception_info() ((void *)(&EXCEPT_ExceptionPointers))
#define _abnormal_termination() (0)

/* /END */

#define EXCEPT_LOCALS (sizeof(CONTEXT) + 5 * 4)
#define EXCEPT_CONTEXT_OFFSET 0
#define EXCEPT_POINTERS_OFFSET (sizeof(CONTEXT))

#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

#define TRY \
{ \
 void * TRY_ExceptionRegistration = SEH_Alloc(28); \
 volatile unsigned long EXCEPT_ExceptionCode; \
\
 __asm__ __volatile__ \
 ( \
   "push   %%eax" "\n" \
   "push   %%ecx" "\n" \
   "mov    %0, %%eax" "\n" \
   "mov    %%fs:0x0, %%ecx" "\n" \
   "mov    %%ecx, (%%eax)" "\n" \
   "mov    %%eax, %%fs:0x0" "\n" \
   "lea    EXCEPT_Handler, %%ecx" "\n" \
   "mov    %%ecx, 0x4(%%eax)" "\n" \
   "mov    %%ebp, %c1(%%eax)" "\n" \
   "mov    %%ebx, %c2(%%eax)" "\n" \
   "mov    %%esi, %c3(%%eax)" "\n" \
   "mov    %%edi, %c4(%%eax)" "\n" \
   "mov    %%esp, %c5(%%eax)" "\n" \
   "addl   $0x8, %c5(%%eax)" "\n" \
   "pop    %%ecx" "\n" \
   "pop    %%eax" "\n" \
  : \
  : \
   "r"(TRY_ExceptionRegistration), \
   "n"(_TRY_SAVED_EBP), \
   "n"(_TRY_SAVED_EBX), \
   "n"(_TRY_SAVED_ESI), \
   "n"(_TRY_SAVED_EDI), \
   "n"(_TRY_SAVED_ESP) \
 );

#define EXCEPT(EXPR__) \
{ \
 volatile EXCEPTION_POINTERS EXCEPT_ExceptionPointers; \
 \
 __asm__ __volatile__("jmp EXCEPT_EndOfExcept" "\n"); \
 __asm__ __volatile__("EXCEPT_Handler:" "\n"); \
 __asm__ __volatile__ \
 ( \
   "mov    0x4(%%esp), %%eax" "\n" \
   "testl  %0, %c1(%%eax)" "\n" \
   "je     EXCEPT_DoHandler" "\n" \
   "xor    %%eax, %%eax" "\n" \
   "or     %c2, %%eax" "\n" \
   "ret" "\n" \
  : \
  : \
   "i"(EH_UNWIND_CONTEXT | EH_NESTED_CALL), \
   "g"(offsetof(EXCEPTION_RECORD, ExceptionFlags)), \
   "i"(ExceptionContinueSearch) \
  : \
   "%eax", "%esp" \
 ); \
 __asm__ __volatile__("EXCEPT_DoHandler:" "\n"); \
 __asm__ __volatile__ \
 ( \
   "sub    %c1, %%esp" "\n" \
   "mov    %%ebp, %c2(%%esp)" "\n" \
   "mov    %%ebx, %c3(%%esp)" "\n" \
   "mov    %%edi, %c4(%%esp)" "\n" \
   "mov    %%esi, %c5(%%esp)" "\n" \
   "pushf" "\n" \
   "pop    %%ecx" "\n" \
   "mov    %%ecx, %c6(%%esp)" "\n" \
   "mov    %c7(%%esp), %%ebp" "\n" \
   "mov    0x8(%%ebp), %%ebp" "\n" \
   "mov    %8, %%edx" "\n" \
   "mov    %c9(%%esp), %%ecx" "\n" \
   "mov    %%ecx, %c10(%%edx)" "\n" \
   "mov    %c11(%%esp), %%ecx" "\n" \
   "mov    %%ecx, %c12(%%edx)" "\n" \
   "mov    %c10(%%edx), %%edx" "\n" \
   "mov    %c13(%%edx), %%edx" "\n" \
   "mov    %%edx, %0" "\n" \
   "mov    %c11(%%esp), %%ebp" "\n" \
   "mov    %c6(%%ebp), %%eax" "\n" \
   "push   %%eax" "\n" \
   "popf" "\n" \
   "mov    %c7(%%esp), %%ebp" "\n" \
   "mov    %c14(%%ebp), %%ebx" "\n" \
   "mov    %c15(%%ebp), %%esi" "\n" \
   "mov    %c16(%%ebp), %%edi" "\n" \
   "mov    %c17(%%ebp), %%ebp" "\n" \
   "cld" "\n" \
  : \
   "=r"(EXCEPT_ExceptionCode) \
  : \
   "i"(EXCEPT_LOCALS), \
   "g"(offsetof(CONTEXT, Ebp)), \
   "g"(offsetof(CONTEXT, Ebx)), \
   "g"(offsetof(CONTEXT, Edi)), \
   "g"(offsetof(CONTEXT, Esi)), \
   "g"(offsetof(CONTEXT, EFlags)), \
   "g"(0x08 + EXCEPT_LOCALS), \
   "r"(&EXCEPT_ExceptionPointers), \
   "g"(0x04 + EXCEPT_LOCALS), \
   "g"(offsetof(EXCEPTION_POINTERS, ExceptionRecord)), \
   "g"(0x0C + EXCEPT_LOCALS), \
   "g"(offsetof(EXCEPTION_POINTERS, ContextRecord)), \
   "g"(offsetof(EXCEPTION_RECORD, ExceptionCode)), \
   "g"(_TRY_SAVED_EBX), \
   "g"(_TRY_SAVED_ESI), \
   "g"(_TRY_SAVED_EDI), \
   "g"(_TRY_SAVED_EBP) \
 ); \
 \
 switch((EXPR__)) \
 { \
  case EXCEPTION_CONTINUE_SEARCH: \
  { \
   SEH_Free(TRY_ExceptionRegistration); \
 \
   __asm__ __volatile__ \
   ( \
     "mov %c0(%%esp), %%ebp" "\n" \
     "mov %c1(%%esp), %%ebx" "\n" \
     "mov %c2(%%esp), %%edi" "\n" \
     "mov %c3(%%esp), %%esi" "\n" \
     "add %c4, %%esp" "\n" \
     "xor %%eax, %%eax" "\n" \
     "or  %c5, %%eax" "\n" \
     "ret" "\n" \
    : \
    : \
     "g"(offsetof(CONTEXT, Ebp)), \
     "g"(offsetof(CONTEXT, Ebx)), \
     "g"(offsetof(CONTEXT, Esi)), \
     "g"(offsetof(CONTEXT, Edi)), \
     "i"(EXCEPT_LOCALS), \
     "i"(ExceptionContinueSearch) \
    : \
     "%ebp", "%ebx", "%edi", "%esi", "%esp", "%eax" \
   ); \
  } \
 \
  case EXCEPTION_CONTINUE_EXECUTION: \
  { \
   register PVOID pTargetFrame; \
 \
   SEH_Free(TRY_ExceptionRegistration); \
 \
   __asm__ __volatile__ \
   ( \
    "mov %1(%%esp), %0" "\n" : \
    "=r"(pTargetFrame) : \
    "g"(0x08 + EXCEPT_LOCALS) \
   ); \
 \
   RtlUnwind(pTargetFrame, &&__ret_label_CONTINUE_EXECUTION, NULL, NULL); \
 \
__ret_label_CONTINUE_EXECUTION: \
   __asm__ __volatile__ \
   ( \
     "mov %c0(%%esp), %%ebp" "\n" \
     "mov %c1(%%esp), %%ebx" "\n" \
     "mov %c2(%%esp), %%edi" "\n" \
     "mov %c3(%%esp), %%esi" "\n" \
     "add %c4, %%esp" "\n" \
     "xor %%eax, %%eax" "\n" \
     "or  %c5, %%eax" "\n" \
     "ret" "\n" \
    : \
    : \
     "g"(offsetof(CONTEXT, Ebp)), \
     "g"(offsetof(CONTEXT, Ebx)), \
     "g"(offsetof(CONTEXT, Esi)), \
     "g"(offsetof(CONTEXT, Edi)), \
     "g"(EXCEPT_LOCALS), \
     "g"(ExceptionContinueExecution) \
    : \
     "%ebp", "%ebx", "%edi", "%esi", "%esp", "%eax" \
   ); \
  } \
 \
  case EXCEPTION_EXECUTE_HANDLER: \
  { \
   register PVOID pTargetFrame; \
 \
   __asm__ __volatile__ \
   ( \
    "pusha" "\n" "pushf" "\n" "mov %c1(%%esp), %0" "\n" : \
    "=r"(pTargetFrame) : \
    "g"(0x08 + 0x04 + 0x20 + EXCEPT_LOCALS) : \
    "%esp" \
   ); \
 \
   RtlUnwind(pTargetFrame, &&__ret_label_EXECUTE_HANDLER, NULL, NULL); \
 \
__ret_label_EXECUTE_HANDLER: \
   __asm__ __volatile__("popf" "\n" "popa" "\n" : : : "memory" ); \
   break; \
  } \
   \
  default: \
  { \
   SEH_DbgPrint("SEH: Invalid disposition returned from filter expression\n"); \
   SEH_RaiseStatus(STATUS_INVALID_DISPOSITION); \
  } \
 } \
 \
 __asm__ __volatile__ \
 ( \
   "mov    %c0(%%esp), %%ebp" "\n" \
   "mov    %c1(%%ebp), %%ebx" "\n" \
   "mov    %c2(%%ebp), %%esi" "\n" \
   "mov    %c3(%%ebp), %%edi" "\n" \
   "mov    %c4(%%ebp), %%esp" "\n" \
   "mov    0x8(%%ebp), %%ebp" "\n" \
  : \
  : \
   "g"(0x08 + EXCEPT_LOCALS), \
   "g"(_TRY_SAVED_EBX), \
   "g"(_TRY_SAVED_ESI), \
   "g"(_TRY_SAVED_EDI), \
   "g"(_TRY_SAVED_ESP) \
  : \
   "%ebx", "%esp", "%ebp", "%esi", "%edi" \
 ); \
}

#define EXCEPT_END() \
 __asm__ __volatile__("EXCEPT_EndOfExcept:" "\n"); \
 __asm__ __volatile__ \
 ( \
   "push   %eax" "\n" \
   "mov    %fs:0x0, %eax" "\n" \
   "mov    (%eax), %eax" "\n" \
   "mov    %eax, %fs:0x0" "\n" \
   "pop    %eax" "\n"\
 ); \
 \
 SEH_Free(TRY_ExceptionRegistration); \
}

int main(void)
{
 TRY
 {
  printf("try\n");
  *((void **)NULL) = NULL; /* throw */
  printf("after crash\n");
 }
 EXCEPT((printf("filter\n"), EXCEPTION_EXECUTE_HANDLER))
 {
  printf("except\n");
 }
 EXCEPT_END();
 printf("after except block\n");
 
 return 0;
}


More information about the Ros-kernel mailing list