[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