1 /* exceptions.h 2 3 Copyright 1996, 1997, 1998, 2001 Red Hat, Inc. 4 5 This file is part of Cygwin. 6 7 This software is a copyrighted work licensed under the terms of the 8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for 9 details. */ 10 11 #ifndef _EXCEPTIONS_H 12 #define _EXCEPTIONS_H 13 14 #ifdef __cplusplus 15 extern "C" { 16 #endif /* __cplusplus */ 17 18 /* Documentation on the innards of exception handling (i.e. from the 19 perspective of a compiler implementor) apparently doesn't exist. Sigh. 20 However, the following came from Onno Hovers <onno@stack.urc.tue.nl> 21 22 The first pointer to the chain of handlers is in the thread environment block 23 at FS:[0]. This chain has the following format: 24 25 typedef struct __EXCEPTION_FRAME 26 { 27 struct __EXCEPTION_FRAME *Prev; /-* pointer to the previous frame *-/ 28 PEXCEPTION_HANDLER Handler; /-* handler function *-/ 29 } 30 31 You register an exception handler in your compiler with this simple ASM 32 sequence: 33 PUSH _MyExceptionHandler 34 PUSH FS:[0] 35 MOV FS:[0],ESP 36 An exception frame MUST be on the stack! The frame may have more fields and 37 both Visual C++ and Borland C++ use more fields for themselves. 38 39 When an exception occurs the system calls all handlers starting with the 40 handler at FS:0, and then the previous etc. until one handler returns 41 ExceptionContinueExecution, which is 0. If a handler does not want to handle 42 the exception it should just return ExceptionContinueSearch, which is 1. 43 44 The handler has the following parameters: 45 ehandler ( 46 PEXCEPTION_RECORD erecord, 47 PEXCEPTION_FRAME myframe, 48 PCONTEXT context, /-* context before and after *-/ 49 PVOID dispatch) /-* something *-/ 50 51 When a handler wants to handle the exception, it has some alternatives: 52 53 -one is to do do something about the exception condition, like emulating 54 an invalid instruction, mapping memory where there was a page fault, etc. 55 If the handler wants to have the context of the thread that causes the 56 exception changed, it should make that change in the context passed to the 57 handler. 58 59 -the second alternative is to call all exception handlers again, indicating 60 that you want them to clean up. This way all the __finally blocks get 61 executed. After doing that you change the context passed to the handler so 62 the code starts executing in the except block. For this purpose you could 63 call RtlUnwind. This (undocumented) function calls all exception handlers 64 up to but not including the exception frame passed to it. If NULL is passed 65 as exception frame RtlUnwind calls all exception handlers and then exits the 66 process. The parameters to RtlUnwind are: 67 68 RtlUnwind ( 69 PEXCEPTION_FRAME endframe, 70 PVOID unusedEip, 71 PEXCEPTION_RECORD erecord, 72 DWORD returnEax) 73 74 You should set unusedEip to the address where RtlUnwind should return like 75 this: 76 PUSH 0 77 PUSH OFFSET ReturnUnwind 78 PUSH 0 79 PUSH 0 80 CALL RtlUnwind 81 ReturnUnwind: 82 ..... 83 84 If no EXCEPTION_RECORD is passed, RtlUnwind makes a default exception 85 record. In any case, the ExceptionFlags part of this record has the 86 EH_UNWINDING (=2), flag set. (and EH_EXIT_UNWIND (=4), when NULL is passed as the end 87 frame.). 88 89 The handler for a exception as well as a for unwinds may be executed in the 90 thread causing the exception, but may also be executed in another (special 91 exception) thread. So it is not wise to make any assumptions about that! 92 93 As an alternative you may consider the SetUnhandledExceptionFilter API 94 to install your own exception filter. This one is documented. 95 */ 96 97 /* The January 1994 MSJ has an article entitled "Clearer, More Comprehensive 98 Error Processing with Win32 Structured Exception Handling". It goes into 99 a teensy bit of detail of the innards of exception handling (i.e. what we 100 have to do). */ 101 102 typedef int (exception_handler) 103 (EXCEPTION_RECORD *, void *, CONTEXT *, void *); 104 105 typedef struct _exception_list 106 { 107 struct _exception_list *prev; 108 exception_handler *handler; 109 110 /* We're apparently free to add more stuff here. 111 At present we don't need any. */ 112 } exception_list; 113 114 void init_exceptions (exception_list *); 115 116 #ifdef __cplusplus 117 }; 118 #endif /* __cplusplus */ 119 120 #endif /* _EXCEPTIONS_H */ |