1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
#ifndef _SIGSEGV_H
#define _SIGSEGV_H
/*
* Copyright 1998-1999 Bruno Haible, <haible@clisp.cons.org>
*
* This is free software distributed under the GNU General Public Licence
* described in the file COPYING. Contact the author if you don't have this
* or can't live with it. There is ABSOLUTELY NO WARRANTY, explicit or implied,
* on this software.
*/
/*
* Portability section:
* HAVE_SIGSEGV_RECOVERY is defined if the system supports catching SIGSEGV.
* HAVE_STACK_OVERFLOW_RECOVERY is defined if stack overflow can be caught.
*/
#if defined(__linux__) && (defined(i386) || defined(__i386)) /* Linux */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if defined(__NetBSD__) || defined(__FreeBSD__) /* NetBSD, FreeBSD */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if defined(__linux__) && defined(sparc) && 0 /* Linux */
/* This used to work. But in Linux-2.0.33 and 2.2.0 a task's tss.sig_address
* is passed to the signal handler only if old SunOS signal frames are in use,
* and there is no reliable way to force this. Blech. */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if defined(sun) && defined(unix) && (defined(mc68020) || defined(sparc) || (defined(i386) || defined(__i386))) /* SunOS */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if (defined(sgi) || defined(__sgi)) && (defined(SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4)) /* Irix 5 */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if defined(__osf__) /* OSF/1 */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if defined(_AIX) /* AIX */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if defined(NeXT) /* NeXTstep */
#define HAVE_SIGSEGV_RECOVERY
#endif
#if defined(_WIN32) && !defined(__BORLANDC__) /* Win32, but not Borland C */
#define HAVE_SIGSEGV_RECOVERY
#define HAVE_STACK_OVERFLOW_RECOVERY
#endif
#undef HAVE_SIGSEGV_RECOVERY
#if defined(__linux__) || (defined(sun) && defined(unix) && (defined(mc68020) || defined(sparc) || (defined(i386) || defined(__i386)))) || ((defined(sgi) || defined(__sgi)) && (defined(SYSTYPE_SVR4) || defined(__SYSTYPE_SVR4))) || defined(__osf__) /* Linux, SunOS, Irix, OSF/1 */
#define HAVE_STACK_OVERFLOW_RECOVERY
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* -------------------------------------------------------------------------- */
/*
* The type of a global SIGSEGV handler.
* The fault address is passed as argument.
* The access type (read access or write access) is not passed; your handler
* has to know itself how to distinguish these two cases.
* The second argument is 0, meaning it could also be a stack overflow, or 1,
* meaning the handler should seriously try to fix the fault.
* The return value should be nonzero if the handler has done its job
* and no other handler should be called, or 0 if the handler declines
* responsibility for the given address.
*/
typedef int (*sigsegv_handler_t) (void* fault_address, int serious);
/*
* Installs a global SIGSEGV handler.
* This should be called once only, and it ignores any previously installed
* SIGSEGV handler.
* Returns 0 on success, or -1 if the system doesn't support catching SIGSEGV.
*/
extern int sigsegv_install_handler (sigsegv_handler_t handler);
/*
* Deinstalls the global SIGSEGV handler.
* This goes back to the state where no SIGSEGV handler is installed.
*/
extern void sigsegv_deinstall_handler (void);
/*
* Prepares leaving a SIGSEGV handler (through longjmp or similar means).
* On Unix, this unblocks some signals.
*/
extern void sigsegv_leave_handler (void);
/*
* The type of a context passed to a stack overflow handler.
*/
#if defined(__linux__) && (defined(i386) || defined(__i386) || defined(m68k) || defined(__m68k) || defined(mips) || defined(__mips) || defined(sparc) || defined(__sparc) || defined(alpha) || defined(__alpha) || defined(arm) || defined(__arm))
typedef struct sigcontext * stackoverflow_context_t;
#else
typedef void * stackoverflow_context_t;
#endif
/*
* The type of a stack overflow handler.
* Such a handler should perform a longjmp call in order to reduce the amount
* of stack needed. It must not return.
* The emergency argument is 0 when the stack could be repared, or 1 if the
* application should better save its state and exit now.
*/
typedef void (*stackoverflow_handler_t) (int emergency, stackoverflow_context_t scp);
/*
* Installs a stack overflow handler.
* The extra_stack argument is a pointer to a pre-allocated area used as a
* stack for executing the handler. It is typically allocated by use of
* `alloca' during `main'. Its size should be sufficiently large (typically
* 16 KB).
* Returns 0 on success, or -1 if the system doesn't support catching stack
* overflow.
*/
extern int stackoverflow_install_handler (stackoverflow_handler_t handler,
void* extra_stack, unsigned long extra_stack_size);
/*
* Deinstalls the stack overflow handler.
*/
extern void stackoverflow_deinstall_handler (void);
/* -------------------------------------------------------------------------- */
/*
* The following structure and functions permit to define different SIGSEGV
* policies on different address ranges.
*/
/*
* The type of a local SIGSEGV handler.
* The fault address is passed as argument.
* The second argument is fixed arbitrary user data.
* The return value should be nonzero if the handler has done its job
* and no other handler should be called, or 0 if the handler declines
* responsibility for the given address.
*/
typedef int (*sigsegv_area_handler_t) (void* fault_address, void* user_arg);
/*
* This structure represents a table of memory areas (address range intervals),
* with an local SIGSEGV handler for each.
*/
typedef
struct sigsegv_dispatcher {
void* tree;
}
sigsegv_dispatcher;
/*
* Initializes a sigsegv_dispatcher structure.
*/
extern void sigsegv_init (sigsegv_dispatcher* dispatcher);
/*
* Adds a local SIGSEGV handler to a sigsegv_dispatcher structure.
* It will cover the interval [address..address+len-1].
* Returns a "ticket" that can be used to remove the handler later.
*/
extern void* sigsegv_register (sigsegv_dispatcher* dispatcher,
void* address, unsigned long len,
sigsegv_area_handler_t handler, void* handler_arg);
/*
* Removes a local SIGSEGV handler.
*/
extern void sigsegv_unregister (sigsegv_dispatcher* dispatcher, void* ticket);
/*
* Call the local SIGSEGV handler responsible for the given fault address.
* Return the handler's return value. 0 means that no handler has been found,
* or that a handler was found but declined responsibility.
*/
extern int sigsegv_dispatch (sigsegv_dispatcher* dispatcher, void* fault_address);
/* -------------------------------------------------------------------------- */
#ifdef __cplusplus
}
#endif
#endif /* _SIGSEGV_H */
|