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

KJK::Hyperion noog at libero.it
Wed Nov 5 01:32:03 CET 2003


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 
-------------- 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())

#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" \
   "mov    %1, %%ecx" "\n" \
   "mov    %%ecx, 0x4(%%eax)" "\n" \
   "mov    %%ebp, %2(%%eax)" "\n" \
   "mov    %%ebx, %3(%%eax)" "\n" \
   "mov    %%esi, %4(%%eax)" "\n" \
   "mov    %%edi, %5(%%eax)" "\n" \
   "mov    %%esp, %6(%%eax)" "\n" \
   "addl   $0x8, %6(%%eax)" "\n" \
   "pop    %%ecx" "\n" \
   "pop    %%eax" "\n" \
  : \
  : \
   "r"(TRY_ExceptionRegistration), \
   "r"(&&EXCEPT_Handler), \
   "g"(_TRY_SAVED_EBP), \
   "g"(_TRY_SAVED_EBX), \
   "g"(_TRY_SAVED_ESI), \
   "g"(_TRY_SAVED_EDI), \
   "g"(_TRY_SAVED_ESP) \
 );

#define EXCEPT(EXPR__) \
{ \
 volatile EXCEPTION_POINTERS EXCEPT_ExceptionPointers; \
 \
 __asm__ __volatile__("jmp %0" "\n" : : "o"(&&EXCEPT_EndOfExcept)); \
 \
EXCEPT_Handler: \
 __asm__ __volatile__ \
 ( \
   "mov    0x4(%%esp, 1), %%eax" "\n" \
   "testl  %0, %1(%%eax)" "\n" \
   "je     *%2" "\n" \
   "xor    %%eax, %%eax" "\n" \
   "or     %3, %%eax" "\n" \
   "ret" "\n" \
  : \
  : \
   "i"(EH_UNWIND_CONTEXT | EH_NESTED_CALL), \
   "g"(offsetof(EXCEPTION_RECORD, ExceptionFlags)), \
   "r"(&&EXCEPT_DoHandler), \
   "i"(ExceptionContinueSearch) \
  : \
   "%eax", "%esp" \
 ); \
 \
EXCEPT_DoHandler: \
 __asm__ __volatile__ \
 ( \
   "sub    %1, %%esp" "\n" \
   "mov    %%ebp, %2(%%esp, 1)" "\n" \
   "mov    %%ebx, %3(%%esp, 1)" "\n" \
   "mov    %%edi, %4(%%esp, 1)" "\n" \
   "mov    %%esi, %5(%%esp, 1)" "\n" \
   "pushf" "\n" \
   "pop    %%ecx" "\n" \
   "mov    %%ecx, %6(%%esp, 1)" "\n" \
   "mov    %7(%%esp, 1), %%ebp" "\n" \
   "mov    0x8(%%ebp), %%ebp" "\n" \
   "mov    %8, %%edx" "\n" \
   "mov    %9(%%esp, 1), %%ecx" "\n" \
   "mov    %%ecx, %10(%%edx)" "\n" \
   "mov    %11(%%esp, 1), %%ecx" "\n" \
   "mov    %%ecx, %12(%%edx)" "\n" \
   "mov    %10(%%edx), %%edx" "\n" \
   "mov    %13(%%edx), %%edx" "\n" \
   "mov    %%edx, %0" "\n" \
   "mov    %11(%%esp, 1), %%ebp" "\n" \
   "mov    %6(%%ebp), %%eax" "\n" \
   "push   %%eax" "\n" \
   "popf" "\n" \
   "mov    %7(%%esp, 1), %%ebp" "\n" \
   "mov    %14(%%ebp), %%ebx" "\n" \
   "mov    %15(%%ebp), %%esi" "\n" \
   "mov    %16(%%ebp), %%edi" "\n" \
   "mov    %17(%%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 %0(%%esp, 1), %%ebp" "\n" \
     "mov %1(%%esp, 1), %%ebx" "\n" \
     "mov %2(%%esp, 1), %%edi" "\n" \
     "mov %3(%%esp, 1), %%esi" "\n" \
     "add %4, %%esp" "\n" \
     "xor %%eax, %%eax" "\n" \
     "or  %5, %%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, 1), %0" "\n" : \
    "=r"(pTargetFrame) : \
    "g"(0x08 + EXCEPT_LOCALS) \
   ); \
 \
   RtlUnwind(pTargetFrame, &&__ret_label_CONTINUE_EXECUTION, NULL, NULL); \
 \
__ret_label_CONTINUE_EXECUTION: \
   __asm__ __volatile__ \
   ( \
     "mov %0(%%esp, 1), %%ebp" "\n" \
     "mov %1(%%esp, 1), %%ebx" "\n" \
     "mov %2(%%esp, 1), %%edi" "\n" \
     "mov %3(%%esp, 1), %%esi" "\n" \
     "add %4, %%esp" "\n" \
     "xor %%eax, %%eax" "\n" \
     "or  %5, %%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 %1(%%esp, 1), %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    %0(%%esp,1), %%ebp" "\n" \
   "mov    %1(%%ebp), %%ebx" "\n" \
   "mov    %2(%%ebp), %%esi" "\n" \
   "mov    %3(%%ebp), %%edi" "\n" \
   "mov    %4(%%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() \
EXCEPT_EndOfExcept: \
 \
 __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();
 
 return 0;
}


More information about the Ros-kernel mailing list