OSDN Git Service

* config/vax/vax.h (target_flags, MASK_UNIX_ASM, MASK_VAXC_ALIGNMENT)
[pf3gnuchains/gcc-fork.git] / gcc / ada / seh_init.c
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,  59 Temple Place - Suite 330,  Boston, *
20  * MA 02111-1307, 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  ****************************************************************************/
32
33 /*  This unit contains support for SEH (Structured Exception Handling).
34     Right now the only implementation is for Win32.  */
35
36 #ifdef IN_RTS
37 #include "tconfig.h"
38 #include "tsystem.h"
39 #include <sys/stat.h>
40
41 /* We don't have libiberty, so us malloc.  */
42 #define xmalloc(S) malloc (S)
43
44 #else
45 #include "config.h"
46 #include "system.h"
47 #endif
48
49 #include "raise.h"
50
51 /* Addresses of exception data blocks for predefined exceptions. */
52 extern struct Exception_Data constraint_error;
53 extern struct Exception_Data numeric_error;
54 extern struct Exception_Data program_error;
55 extern struct Exception_Data storage_error;
56 extern struct Exception_Data tasking_error;
57 extern struct Exception_Data _abort_signal;
58
59 #define Raise_From_Signal_Handler \
60                       ada__exceptions__raise_from_signal_handler
61 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
62
63
64 #ifdef _WIN32
65
66 #include <windows.h>
67 #include <excpt.h>
68
69 extern void _global_unwind2 (void *);
70
71 EXCEPTION_DISPOSITION __gnat_SEH_error_handler
72 (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*);
73
74 EXCEPTION_DISPOSITION
75 __gnat_SEH_error_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
76                           void *EstablisherFrame,
77                           struct _CONTEXT* ContextRecord ATTRIBUTE_UNUSED,
78                           void *DispatcherContext ATTRIBUTE_UNUSED)
79 {
80   struct Exception_Data *exception;
81   const char *msg;
82
83   switch (ExceptionRecord->ExceptionCode)
84     {
85     case EXCEPTION_ACCESS_VIOLATION:
86       /* If the failing address isn't maximally-aligned or if the page
87          before the faulting page is not accessible, this is a program error.
88       */
89       if ((ExceptionRecord->ExceptionInformation[1] & 3) != 0
90           || IsBadCodePtr
91           ((void *)(ExceptionRecord->ExceptionInformation[1] + 4096)))
92         {
93           exception = &program_error;
94           msg = "EXCEPTION_ACCESS_VIOLATION";
95         }
96       else
97         {
98           /* otherwise it is a stack overflow  */
99           exception = &storage_error;
100           msg = "stack overflow (or erroneous memory access)";
101         }
102       break;
103
104     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
105       exception = &constraint_error;
106       msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
107       break;
108
109     case EXCEPTION_DATATYPE_MISALIGNMENT:
110       exception = &constraint_error;
111       msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
112       break;
113
114     case EXCEPTION_FLT_DENORMAL_OPERAND:
115       exception = &constraint_error;
116       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
117       break;
118
119     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
120       exception = &constraint_error;
121       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
122       break;
123
124     case EXCEPTION_FLT_INVALID_OPERATION:
125       exception = &constraint_error;
126       msg = "EXCEPTION_FLT_INVALID_OPERATION";
127       break;
128
129     case EXCEPTION_FLT_OVERFLOW:
130       exception = &constraint_error;
131       msg = "EXCEPTION_FLT_OVERFLOW";
132       break;
133
134     case EXCEPTION_FLT_STACK_CHECK:
135       exception = &program_error;
136       msg = "EXCEPTION_FLT_STACK_CHECK";
137       break;
138
139     case EXCEPTION_FLT_UNDERFLOW:
140       exception = &constraint_error;
141       msg = "EXCEPTION_FLT_UNDERFLOW";
142       break;
143
144     case EXCEPTION_INT_DIVIDE_BY_ZERO:
145       exception = &constraint_error;
146       msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
147       break;
148
149     case EXCEPTION_INT_OVERFLOW:
150       exception = &constraint_error;
151       msg = "EXCEPTION_INT_OVERFLOW";
152       break;
153
154     case EXCEPTION_INVALID_DISPOSITION:
155       exception = &program_error;
156       msg = "EXCEPTION_INVALID_DISPOSITION";
157       break;
158
159     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
160       exception = &program_error;
161       msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
162       break;
163
164     case EXCEPTION_PRIV_INSTRUCTION:
165       exception = &program_error;
166       msg = "EXCEPTION_PRIV_INSTRUCTION";
167       break;
168
169     case EXCEPTION_SINGLE_STEP:
170       exception = &program_error;
171       msg = "EXCEPTION_SINGLE_STEP";
172       break;
173
174     case EXCEPTION_STACK_OVERFLOW:
175       exception = &storage_error;
176       msg = "EXCEPTION_STACK_OVERFLOW";
177       break;
178
179    default:
180       exception = &program_error;
181       msg = "unhandled signal";
182     }
183
184   /* This call is important as it avoids locking the second time we catch a
185      signal. Note that this routine is documented as internal to Windows and
186      should not be used.  */
187
188   _global_unwind2 (EstablisherFrame);
189   /* Call equivalent to RtlUnwind (EstablisherFrame, NULL, NULL, 0); */
190
191   Raise_From_Signal_Handler (exception, msg);
192   return 0; /* This is never reached, avoid compiler warning  */
193 }
194
195 /*  Install the Win32 SEH exception handler. Note that the caller must have
196     allocated 8 bytes on the stack and pass the pointer to this stack
197     space. This is needed as the SEH exception handler must be on the stack of
198     the thread.
199
200        int buf[2];
201
202        __gnat_install_SEH_handler ((void*)buf);
203
204        main();
205
206    This call must be done before calling the main procedure or the thread
207    entry. The stack space must exists during all the main run.  */
208
209 void
210 __gnat_install_SEH_handler (void *ER)
211 {
212   int *ptr;
213
214   /* put current handler in ptr */
215
216   asm ("mov %%fs:(0),%%ecx" : : : "%ecx");
217   asm ("mov %%ecx,%0" : "=m" (ptr));
218
219   ((int *)ER)[0] = (int)ptr;                       /* previous handler */
220   ((int *)ER)[1] = (int)__gnat_SEH_error_handler;  /* new handler */
221
222   /* ptr is the new handler, set fs:(0) with this value */
223
224   ptr = (int *)ER;
225   asm ("mov %0,%%ecx" : : "m" (ptr) : "%ecx");
226   asm ("mov %ecx,%fs:(0)");
227 }
228
229 #else /* _WIN32 */
230 /* For all non Windows targets we provide a dummy SEH install handler.  */
231 void __gnat_install_SEH_handler (void *eh ATTRIBUTE_UNUSED)
232 {
233 }
234 #endif