2015 01 31 02 52 [c] 用MinGW gcc 自己寫 exception handler (seh).

之前就寫過, 只是並不能用 MinGW gcc編譯.
所以寫這個當作紀錄.

#include <windows.h>
#include <stdio.h>

#define PUSH_SEH(handler) \
__asm__("push %0\n\t"  \
        "push %%fs:0x0\n\t" \
        "movl %%esp, %%fs:0x0\n\t" : : "r" (handler));

#define POP_SEH() \
__asm__("movl %esp, %eax\n\t" \
        "movl %eax, %fs:0x0\n\t" \
        "addl $0x8, %esp\n\t");

#define ExceptionContinueExecution (0)
#define ExceptionContinueSearch    (1)

int __cdecl handler(struct _EXCEPTION_RECORD *ExceptionRecord,
                    void * EstablisherFrame,
                    struct _CONTEXT *ContextRecord,
                    void * DispatcherContext)
{
        printf("Inside handler\n");
        printf("Didn't fix anything here.\n");
        return ExceptionContinueSearch;
}
int error=123;

int __cdecl handler2(struct _EXCEPTION_RECORD *ExceptionRecord,
                     void * EstablisherFrame,
                     struct _CONTEXT *ContextRecord,
                     void * DispatcherContext)
{
        printf("Inside handler2\n");
        printf("Fix Eax to %p\n",&error);
        ContextRecord->Eax = (DWORD)&error;
        return ExceptionContinueExecution;
}

int test()
{
        int *errPtr=NULL;
        PUSH_SEH(handler);
        printf("value(adress:%p)=%d\n",errPtr,*errPtr);
        printf("pass the error!\n");
        POP_SEH();
        return 0;
}

int main()
{
        PUSH_SEH(handler2);
        test();
        POP_SEH();
        return 0;
}

執行結果:

$ gcc seh32.c
$ ./a.exe
Inside handler
Didn't fix anything here.
Inside handler2
Fix Eax to 00404000
value(adress:00000000)=123
pass the error!