[ros-kernel] Macro SEH support ported - sort of
KJK::Hyperion
noog at libero.it
Sun Nov 9 22:19:52 CET 2003
At 17.03 05/11/2003, you wrote:
>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.
Where did you find documentation for the %c<number> replaceable? anyway, I
don't like the use of asm labels, as this makes impossible to use
TRY..EXCEPT twice in the same compilation unit (does it?). Finally, I have
found the problem: line 126 doesn't subtract 736 from esp, but subtracts
esp from the doubleword located at 736. There were five other such bugs in
the code. After correcting them, the test code works correctly when the
filter returns EXCEPTION_EXECUTE_HANDLER. I tried
EXCEPTION_CONTINUE_SEARCH, but the instruction at line 188 doesn't appear
to set the stack pointer correctly - the ret at line 191 returns to an
address on the stack. The same goes for EXCEPTION_CONTINUE_EXECUTION, but
the affected lines are different (227 and 230)
-------------- 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 %2, %%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 %1, %%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 %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 %c1(%%esp), %0" "\n" : \
"=r"(pTargetFrame) : \
"n"(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 %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 %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); \
}
__declspec(dllexport) 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