From: vadim y. <zg...@bm...> - 2004-06-15 09:16:32
|
hello, SourceForge.net! on Mon, 14 Jun 2004 20:22:00 -0700 you wrote: Sn> (Have a look at excpt.h if you want it really badly.) excpt.h from mingw-runtime is unusable. there is another version. it works, but only with switch -O0. i use another approach for catch windows exceptions. i wrote in assembler followed function: BOOL SafeCall(PVOID data,PSAFECALLFUNC call,PSAFECALLFUNC except); its equivalent next pseodo code: SafeCall() { BOOL res=TRUE; __try { call(data); } __except(...) { except(data); res=FALSE; } return res; } implementation: ----------------- file: D:\00000005.DIR\c\SEH\example\seh.s ---->8---- .text .align 4 .globl _SafeCall _SafeCall: push %ebp pushl $0 pushl $0 pushl $safe_place pushl $handler pushl %fs:0 movl %esp,%fs:0 pushl 0x1c(%esp) call *0x24(%esp) addl $4,%esp movl $1,%eax jmp exit safe_place: pushl 0x1c(%esp) call *0x28(%esp) addl $4,%esp xor %eax,%eax exit: popl %fs:0 addl $0x14,%esp ret handler: push %ebp mov %esp,%ebp push %ebx push %edi push %esi movl 8(%ebp),%ebx testl $1,4(%ebx) jnz nodeal testl $2,4(%ebx) jz unwind jmp nodeal unwind: pushl $0 pushl 8(%ebp) pushl $unwind_ret pushl 0x0c(%ebp) call _RtlUnwind@16 unwind_ret: movl 0x10(%ebp),%esi movl 0x0c(%ebp),%edi movl %edi,0xc4(%esi) movl 8(%edi),%eax movl %eax,0xb8(%esi) movl 0x14(%edi),%eax movl %eax,0xb4(%esi) xor %eax,%eax jmp fin nodeal: movl $1,%eax fin: pop %esi pop %edi pop %ebx mov %ebp,%esp pop %ebp ret ----8<---- end of file: D:\00000005.DIR\c\SEH\example\seh.s ---------- ----------------- file: D:\00000005.DIR\c\SEH\example\seh.h ---->8---- #ifndef __SEH_H__ #define __SEH_H__ typedef VOID (*PSAFECALLFUNC)(PVOID data); BOOL SafeCall(PVOID data,PSAFECALLFUNC call,PSAFECALLFUNC except); #endif // __SEH_H__ ----8<---- end of file: D:\00000005.DIR\c\SEH\example\seh.h ---------- example: ----------------- file: D:\00000005.DIR\c\SEH\example\test.c ---->8---- #include <windows.h> #include <stdio.h> #include "seh.h" VOID test1_except(PVOID data) { printf("except\n"); } VOID test1_call(PVOID data) { if(!data) { printf("level 1\n"); printf("Result: %d\n",SafeCall((PVOID)1,test1_call,test1_except)); } else printf("level 2\n"); *(char *)0=0; } VOID test2_call(PVOID data) { printf("all fine\n"); } VOID test3_call(PVOID data) { printf("big alloc\n"); HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY|HEAP_GENERATE_EXCEPTIONS,1000*1000*1000); } int main(int argc,char *argv[],char *environ[]) { printf("Result: %d\n",SafeCall(NULL,test1_call,test1_except)); printf("Result: %d\n",SafeCall(NULL,test2_call,test1_except)); printf("Result: %d\n",SafeCall(NULL,test3_call,test1_except)); return 0; } ----8<---- end of file: D:\00000005.DIR\c\SEH\example\test.c ---------- ----------------- file: D:\00000005.DIR\c\SEH\example\makefile ---->8---- all: test.exe test.exe: test.o seh.o gcc -O3 -s -o $@ $^ test.o: test.c gcc -O3 -c $^ seh.o: seh.s as -o $@ $^ ----8<---- end of file: D:\00000005.DIR\c\SEH\example\makefile ---------- ps: this function also can be used in kernel mode. -- wbr, zg |