OSDN Git Service

* gcc.dg/attr-weakref-1.c: Add exit (0) to avoid spurious
[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,  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  ****************************************************************************/
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
40 /* We don't have libiberty, so us malloc.  */
41 #define xmalloc(S) malloc (S)
42
43 #else
44 #include "config.h"
45 #include "system.h"
46 #endif
47
48 #include "raise.h"
49
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;
57
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 *);
61
62
63 #ifdef _WIN32
64
65 #include <windows.h>
66 #include <excpt.h>
67
68 extern void _global_unwind2 (void *);
69
70 EXCEPTION_DISPOSITION __gnat_SEH_error_handler
71 (struct _EXCEPTION_RECORD*, void*, struct _CONTEXT*, void*);
72
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)
78 {
79   struct Exception_Data *exception;
80   const char *msg;
81
82   switch (ExceptionRecord->ExceptionCode)
83     {
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.
87       */
88       if ((ExceptionRecord->ExceptionInformation[1] & 3) != 0
89           || IsBadCodePtr
90           ((void *)(ExceptionRecord->ExceptionInformation[1] + 4096)))
91         {
92           exception = &program_error;
93           msg = "EXCEPTION_ACCESS_VIOLATION";
94         }
95       else
96         {
97           /* otherwise it is a stack overflow  */
98           exception = &storage_error;
99           msg = "stack overflow (or erroneous memory access)";
100         }
101       break;
102
103     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
104       exception = &constraint_error;
105       msg = "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
106       break;
107
108     case EXCEPTION_DATATYPE_MISALIGNMENT:
109       exception = &constraint_error;
110       msg = "EXCEPTION_DATATYPE_MISALIGNMENT";
111       break;
112
113     case EXCEPTION_FLT_DENORMAL_OPERAND:
114       exception = &constraint_error;
115       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
116       break;
117
118     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
119       exception = &constraint_error;
120       msg = "EXCEPTION_FLT_DENORMAL_OPERAND";
121       break;
122
123     case EXCEPTION_FLT_INVALID_OPERATION:
124       exception = &constraint_error;
125       msg = "EXCEPTION_FLT_INVALID_OPERATION";
126       break;
127
128     case EXCEPTION_FLT_OVERFLOW:
129       exception = &constraint_error;
130       msg = "EXCEPTION_FLT_OVERFLOW";
131       break;
132
133     case EXCEPTION_FLT_STACK_CHECK:
134       exception = &program_error;
135       msg = "EXCEPTION_FLT_STACK_CHECK";
136       break;
137
138     case EXCEPTION_FLT_UNDERFLOW:
139       exception = &constraint_error;
140       msg = "EXCEPTION_FLT_UNDERFLOW";
141       break;
142
143     case EXCEPTION_INT_DIVIDE_BY_ZERO:
144       exception = &constraint_error;
145       msg = "EXCEPTION_INT_DIVIDE_BY_ZERO";
146       break;
147
148     case EXCEPTION_INT_OVERFLOW:
149       exception = &constraint_error;
150       msg = "EXCEPTION_INT_OVERFLOW";
151       break;
152
153     case EXCEPTION_INVALID_DISPOSITION:
154       exception = &program_error;
155       msg = "EXCEPTION_INVALID_DISPOSITION";
156       break;
157
158     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
159       exception = &program_error;
160       msg = "EXCEPTION_NONCONTINUABLE_EXCEPTION";
161       break;
162
163     case EXCEPTION_PRIV_INSTRUCTION:
164       exception = &program_error;
165       msg = "EXCEPTION_PRIV_INSTRUCTION";
166       break;
167
168     case EXCEPTION_SINGLE_STEP:
169       exception = &program_error;
170       msg = "EXCEPTION_SINGLE_STEP";
171       break;
172
173     case EXCEPTION_STACK_OVERFLOW:
174       exception = &storage_error;
175       msg = "EXCEPTION_STACK_OVERFLOW";
176       break;
177
178    default:
179       exception = &program_error;
180       msg = "unhandled signal";
181     }
182
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.  */
186
187   _global_unwind2 (EstablisherFrame);
188   /* Call equivalent to RtlUnwind (EstablisherFrame, NULL, NULL, 0); */
189
190   Raise_From_Signal_Handler (exception, msg);
191   return 0; /* This is never reached, avoid compiler warning  */
192 }
193
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.
198
199        int buf[2];
200
201        __gnat_install_SEH_handler ((void*)buf);
202
203        main();
204
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.  */
207
208 void
209 __gnat_install_SEH_handler (void *ER)
210 {
211   int *ptr;
212
213   /* put current handler in ptr */
214
215   asm ("mov %%fs:(0),%%ecx" : : : "%ecx");
216   asm ("mov %%ecx,%0" : "=m" (ptr));
217
218   ((int *)ER)[0] = (int)ptr;                       /* previous handler */
219   ((int *)ER)[1] = (int)__gnat_SEH_error_handler;  /* new handler */
220
221   /* ptr is the new handler, set fs:(0) with this value */
222
223   ptr = (int *)ER;
224   asm ("mov %0,%%ecx" : : "m" (ptr) : "%ecx");
225   asm ("mov %ecx,%fs:(0)");
226 }
227
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)
231 {
232 }
233 #endif