PR middle-end/20297
[official-gcc.git] / gcc / ada / seh_init.c
blob7b2f093feca8d1047e5919fb6585608f19eaf319
1 /****************************************************************************
2 * *
3 * GNAT COMPILER COMPONENTS *
4 * *
5 * S E H - I N I T *
6 * *
7 * C Implementation File *
8 * *
9 * Copyright (C) 2005, Free Software Foundation, Inc. *
10 * *
11 * GNAT is free software; you can redistribute it and/or modify it under *
12 * terms of the GNU General Public License as published by the Free Soft- *
13 * ware Foundation; either version 2, or (at your option) any later ver- *
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
17 * for more details. You should have received a copy of the GNU General *
18 * Public License distributed with GNAT; see file COPYING. If not, write *
19 * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 * *
22 * As a special exception, if you link this file with other files to *
23 * produce an executable, this file does not by itself cause the resulting *
24 * executable to be covered by the GNU General Public License. This except- *
25 * ion does not however invalidate any other reasons why the executable *
26 * file might be covered by the GNU Public License. *
27 * *
28 * GNAT was originally developed by the GNAT team at New York University. *
29 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 * *
31 ****************************************************************************/
33 /* This unit contains support for SEH (Structured Exception Handling).
34 Right now the only implementation is for Win32. */
36 #ifdef IN_RTS
37 #include "tconfig.h"
38 #include "tsystem.h"
40 /* We don't have libiberty, so us malloc. */
41 #define xmalloc(S) malloc (S)
43 #else
44 #include "config.h"
45 #include "system.h"
46 #endif
48 #include "raise.h"
50 /* Addresses of exception data blocks for predefined exceptions. */
51 extern struct Exception_Data constraint_error;
52 extern struct Exception_Data numeric_error;
53 extern struct Exception_Data program_error;
54 extern struct Exception_Data storage_error;
55 extern struct Exception_Data tasking_error;
56 extern struct Exception_Data _abort_signal;
58 #define Raise_From_Signal_Handler \
59 ada__exceptions__raise_from_signal_handler
60 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
63 #ifdef _WIN32
65 #include <windows.h>
66 #include <excpt.h>
68 extern void _global_unwind2 (void *);
70 EXCEPTION_DISPOSITION __gnat_SEH_error_handler
71 (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*);
73 EXCEPTION_DISPOSITION
74 __gnat_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
75 void *EstablisherFrame,
76 struct _CONTEXT* ContextRecord ATTRIBUTE_UNUSED,
77 void *DispatcherContext ATTRIBUTE_UNUSED)
79 struct Exception_Data *exception;
80 const char *msg;
82 switch (ExceptionRecord->ExceptionCode)
84 case EXCEPTION_ACCESS_VIOLATION:
85 /* If the failing address isn't maximally-aligned or if the page
86 before the faulting page is not accessible, this is a program error.
88 if ((ExceptionRecord->ExceptionInformation[1] & 3) != 0
89 || IsBadCodePtr
90 ((void *)(ExceptionRecord->ExceptionInformation[1] + 4096)))
92 exception = &program_error;
93 msg = "EXCEPTION_ACCESS_VIOLATION";
95 else
97 /* otherwise it is a stack overflow */
98 exception = &storage_error;
99 msg = "stack overflow (or erroneous memory access)";
101 break;
103 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
104 exception = &constraint_error;
105 msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
106 break;
108 case EXCEPTION_DATATYPE_MISALIGNMENT:
109 exception = &constraint_error;
110 msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
111 break;
113 case EXCEPTION_FLT_DENORMAL_OPERAND:
114 exception = &constraint_error;
115 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
116 break;
118 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
119 exception = &constraint_error;
120 msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
121 break;
123 case EXCEPTION_FLT_INVALID_OPERATION:
124 exception = &constraint_error;
125 msg = "EXCEPTION_FLT_INVALID_OPERATION";
126 break;
128 case EXCEPTION_FLT_OVERFLOW:
129 exception = &constraint_error;
130 msg = "EXCEPTION_FLT_OVERFLOW";
131 break;
133 case EXCEPTION_FLT_STACK_CHECK:
134 exception = &program_error;
135 msg = "EXCEPTION_FLT_STACK_CHECK";
136 break;
138 case EXCEPTION_FLT_UNDERFLOW:
139 exception = &constraint_error;
140 msg = "EXCEPTION_FLT_UNDERFLOW";
141 break;
143 case EXCEPTION_INT_DIVIDE_BY_ZERO:
144 exception = &constraint_error;
145 msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
146 break;
148 case EXCEPTION_INT_OVERFLOW:
149 exception = &constraint_error;
150 msg = "EXCEPTION_INT_OVERFLOW";
151 break;
153 case EXCEPTION_INVALID_DISPOSITION:
154 exception = &program_error;
155 msg = "EXCEPTION_INVALID_DISPOSITION";
156 break;
158 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
159 exception = &program_error;
160 msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
161 break;
163 case EXCEPTION_PRIV_INSTRUCTION:
164 exception = &program_error;
165 msg = "EXCEPTION_PRIV_INSTRUCTION";
166 break;
168 case EXCEPTION_SINGLE_STEP:
169 exception = &program_error;
170 msg = "EXCEPTION_SINGLE_STEP";
171 break;
173 case EXCEPTION_STACK_OVERFLOW:
174 exception = &storage_error;
175 msg = "EXCEPTION_STACK_OVERFLOW";
176 break;
178 default:
179 exception = &program_error;
180 msg = "unhandled signal";
183 /* This call is important as it avoids locking the second time we catch a
184 signal. Note that this routine is documented as internal to Windows and
185 should not be used. */
187 _global_unwind2 (EstablisherFrame);
188 /* Call equivalent to RtlUnwind (EstablisherFrame, NULL, NULL, 0); */
190 Raise_From_Signal_Handler (exception, msg);
191 return 0; /* This is never reached, avoid compiler warning */
194 /* Install the Win32 SEH exception handler. Note that the caller must have
195 allocated 8 bytes on the stack and pass the pointer to this stack
196 space. This is needed as the SEH exception handler must be on the stack of
197 the thread.
199 int buf[2];
201 __gnat_install_SEH_handler ((void*)buf);
203 main();
205 This call must be done before calling the main procedure or the thread
206 entry. The stack space must exists during all the main run. */
208 void
209 __gnat_install_SEH_handler (void *ER)
211 int *ptr;
213 /* put current handler in ptr */
215 asm ("mov %%fs:(0),%%ecx" : : : "%ecx");
216 asm ("mov %%ecx,%0" : "=m" (ptr));
218 ((int *)ER)[0] = (int)ptr; /* previous handler */
219 ((int *)ER)[1] = (int)__gnat_SEH_error_handler; /* new handler */
221 /* ptr is the new handler, set fs:(0) with this value */
223 ptr = (int *)ER;
224 asm ("mov %0,%%ecx" : : "m" (ptr) : "%ecx");
225 asm ("mov %ecx,%fs:(0)");
228 #else /* _WIN32 */
229 /* For all non Windows targets we provide a dummy SEH install handler. */
230 void __gnat_install_SEH_handler (void *eh ATTRIBUTE_UNUSED)
233 #endif