annotate gcc/ada/init.c @ 143:76e1cf5455ef

add cbc_gc test
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sun, 23 Dec 2018 19:24:05 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /****************************************************************************
kono
parents:
diff changeset
2 * *
kono
parents:
diff changeset
3 * GNAT COMPILER COMPONENTS *
kono
parents:
diff changeset
4 * *
kono
parents:
diff changeset
5 * I N I T *
kono
parents:
diff changeset
6 * *
kono
parents:
diff changeset
7 * C Implementation File *
kono
parents:
diff changeset
8 * *
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
9 * Copyright (C) 1992-2018, Free Software Foundation, Inc. *
111
kono
parents:
diff changeset
10 * *
kono
parents:
diff changeset
11 * GNAT is free software; you can redistribute it and/or modify it under *
kono
parents:
diff changeset
12 * terms of the GNU General Public License as published by the Free Soft- *
kono
parents:
diff changeset
13 * ware Foundation; either version 3, or (at your option) any later ver- *
kono
parents:
diff changeset
14 * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
kono
parents:
diff changeset
15 * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
kono
parents:
diff changeset
16 * or FITNESS FOR A PARTICULAR PURPOSE. *
kono
parents:
diff changeset
17 * *
kono
parents:
diff changeset
18 * As a special exception under Section 7 of GPL version 3, you are granted *
kono
parents:
diff changeset
19 * additional permissions described in the GCC Runtime Library Exception, *
kono
parents:
diff changeset
20 * version 3.1, as published by the Free Software Foundation. *
kono
parents:
diff changeset
21 * *
kono
parents:
diff changeset
22 * You should have received a copy of the GNU General Public License and *
kono
parents:
diff changeset
23 * a copy of the GCC Runtime Library Exception along with this program; *
kono
parents:
diff changeset
24 * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
kono
parents:
diff changeset
25 * <http://www.gnu.org/licenses/>. *
kono
parents:
diff changeset
26 * *
kono
parents:
diff changeset
27 * GNAT was originally developed by the GNAT team at New York University. *
kono
parents:
diff changeset
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
kono
parents:
diff changeset
29 * *
kono
parents:
diff changeset
30 ****************************************************************************/
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 /* This unit contains initialization circuits that are system dependent.
kono
parents:
diff changeset
33 A major part of the functionality involves stack overflow checking.
kono
parents:
diff changeset
34 The GCC backend generates probe instructions to test for stack overflow.
kono
parents:
diff changeset
35 For details on the exact approach used to generate these probes, see the
kono
parents:
diff changeset
36 "Using and Porting GCC" manual, in particular the "Stack Checking" section
kono
parents:
diff changeset
37 and the subsection "Specifying How Stack Checking is Done". The handlers
kono
parents:
diff changeset
38 installed by this file are used to catch the resulting signals that come
kono
parents:
diff changeset
39 from these probes failing (i.e. touching protected pages). */
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 /* This file should be kept synchronized with s-init.ads, s-init.adb and the
kono
parents:
diff changeset
42 s-init-*.adb variants. All these files implement the required functionality
kono
parents:
diff changeset
43 for different targets. */
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 /* The following include is here to meet the published VxWorks requirement
kono
parents:
diff changeset
46 that the __vxworks header appear before any other include. */
kono
parents:
diff changeset
47 #ifdef __vxworks
kono
parents:
diff changeset
48 #include "vxWorks.h"
kono
parents:
diff changeset
49 #include "version.h" /* for _WRS_VXWORKS_MAJOR */
kono
parents:
diff changeset
50 #endif
kono
parents:
diff changeset
51
kono
parents:
diff changeset
52 #ifdef __ANDROID__
kono
parents:
diff changeset
53 #undef __linux__
kono
parents:
diff changeset
54 #endif
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 #ifdef IN_RTS
kono
parents:
diff changeset
57 #include "tconfig.h"
kono
parents:
diff changeset
58 #include "tsystem.h"
kono
parents:
diff changeset
59 #include <sys/stat.h>
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 /* We don't have libiberty, so use malloc. */
kono
parents:
diff changeset
62 #define xmalloc(S) malloc (S)
kono
parents:
diff changeset
63 #else
kono
parents:
diff changeset
64 #include "config.h"
kono
parents:
diff changeset
65 #include "system.h"
kono
parents:
diff changeset
66 #endif
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 #include "adaint.h"
kono
parents:
diff changeset
69 #include "raise.h"
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 #ifdef __cplusplus
kono
parents:
diff changeset
72 extern "C" {
kono
parents:
diff changeset
73 #endif
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 extern void __gnat_raise_program_error (const char *, int);
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 /* Addresses of exception data blocks for predefined exceptions. Tasking_Error
kono
parents:
diff changeset
78 is not used in this unit, and the abort signal is only used on IRIX.
kono
parents:
diff changeset
79 ??? Revisit this part since IRIX is no longer supported. */
kono
parents:
diff changeset
80 extern struct Exception_Data constraint_error;
kono
parents:
diff changeset
81 extern struct Exception_Data numeric_error;
kono
parents:
diff changeset
82 extern struct Exception_Data program_error;
kono
parents:
diff changeset
83 extern struct Exception_Data storage_error;
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 /* For the Cert run time we use the regular raise exception routine because
kono
parents:
diff changeset
86 Raise_From_Signal_Handler is not available. */
kono
parents:
diff changeset
87 #ifdef CERT
kono
parents:
diff changeset
88 #define Raise_From_Signal_Handler \
kono
parents:
diff changeset
89 __gnat_raise_exception
kono
parents:
diff changeset
90 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
kono
parents:
diff changeset
91 #else
kono
parents:
diff changeset
92 #define Raise_From_Signal_Handler \
kono
parents:
diff changeset
93 ada__exceptions__raise_from_signal_handler
kono
parents:
diff changeset
94 extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
kono
parents:
diff changeset
95 #endif
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 /* Global values computed by the binder. Note that these variables are
kono
parents:
diff changeset
98 declared here, not in the binder file, to avoid having unresolved
kono
parents:
diff changeset
99 references in the shared libgnat. */
kono
parents:
diff changeset
100 int __gl_main_priority = -1;
kono
parents:
diff changeset
101 int __gl_main_cpu = -1;
kono
parents:
diff changeset
102 int __gl_time_slice_val = -1;
kono
parents:
diff changeset
103 char __gl_wc_encoding = 'n';
kono
parents:
diff changeset
104 char __gl_locking_policy = ' ';
kono
parents:
diff changeset
105 char __gl_queuing_policy = ' ';
kono
parents:
diff changeset
106 char __gl_task_dispatching_policy = ' ';
kono
parents:
diff changeset
107 char *__gl_priority_specific_dispatching = 0;
kono
parents:
diff changeset
108 int __gl_num_specific_dispatching = 0;
kono
parents:
diff changeset
109 char *__gl_interrupt_states = 0;
kono
parents:
diff changeset
110 int __gl_num_interrupt_states = 0;
kono
parents:
diff changeset
111 int __gl_unreserve_all_interrupts = 0;
kono
parents:
diff changeset
112 int __gl_exception_tracebacks = 0;
kono
parents:
diff changeset
113 int __gl_exception_tracebacks_symbolic = 0;
kono
parents:
diff changeset
114 int __gl_detect_blocking = 0;
kono
parents:
diff changeset
115 int __gl_default_stack_size = -1;
kono
parents:
diff changeset
116 int __gl_leap_seconds_support = 0;
kono
parents:
diff changeset
117 int __gl_canonical_streams = 0;
kono
parents:
diff changeset
118 char *__gl_bind_env_addr = NULL;
kono
parents:
diff changeset
119
kono
parents:
diff changeset
120 /* This value is not used anymore, but kept for bootstrapping purpose. */
kono
parents:
diff changeset
121 int __gl_zero_cost_exceptions = 0;
kono
parents:
diff changeset
122
kono
parents:
diff changeset
123 /* Indication of whether synchronous signal handler has already been
kono
parents:
diff changeset
124 installed by a previous call to adainit. */
kono
parents:
diff changeset
125 int __gnat_handler_installed = 0;
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 #ifndef IN_RTS
kono
parents:
diff changeset
128 int __gnat_inside_elab_final_code = 0;
kono
parents:
diff changeset
129 /* ??? This variable is obsolete since 2001-08-29 but is kept to allow
kono
parents:
diff changeset
130 bootstrap from old GNAT versions (< 3.15). */
kono
parents:
diff changeset
131 #endif
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 /* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
kono
parents:
diff changeset
134 is defined. If this is not set then a void implementation will be defined
kono
parents:
diff changeset
135 at the end of this unit. */
kono
parents:
diff changeset
136 #undef HAVE_GNAT_INIT_FLOAT
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 /******************************/
kono
parents:
diff changeset
139 /* __gnat_get_interrupt_state */
kono
parents:
diff changeset
140 /******************************/
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 char __gnat_get_interrupt_state (int);
kono
parents:
diff changeset
143
kono
parents:
diff changeset
144 /* This routine is called from the runtime as needed to determine the state
kono
parents:
diff changeset
145 of an interrupt, as set by an Interrupt_State pragma appearing anywhere
kono
parents:
diff changeset
146 in the current partition. The input argument is the interrupt number,
kono
parents:
diff changeset
147 and the result is one of the following:
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 'n' this interrupt not set by any Interrupt_State pragma
kono
parents:
diff changeset
150 'u' Interrupt_State pragma set state to User
kono
parents:
diff changeset
151 'r' Interrupt_State pragma set state to Runtime
kono
parents:
diff changeset
152 's' Interrupt_State pragma set state to System */
kono
parents:
diff changeset
153
kono
parents:
diff changeset
154 char
kono
parents:
diff changeset
155 __gnat_get_interrupt_state (int intrup)
kono
parents:
diff changeset
156 {
kono
parents:
diff changeset
157 if (intrup >= __gl_num_interrupt_states)
kono
parents:
diff changeset
158 return 'n';
kono
parents:
diff changeset
159 else
kono
parents:
diff changeset
160 return __gl_interrupt_states [intrup];
kono
parents:
diff changeset
161 }
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163 /***********************************/
kono
parents:
diff changeset
164 /* __gnat_get_specific_dispatching */
kono
parents:
diff changeset
165 /***********************************/
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 char __gnat_get_specific_dispatching (int);
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 /* This routine is called from the runtime as needed to determine the
kono
parents:
diff changeset
170 priority specific dispatching policy, as set by a
kono
parents:
diff changeset
171 Priority_Specific_Dispatching pragma appearing anywhere in the current
kono
parents:
diff changeset
172 partition. The input argument is the priority number, and the result
kono
parents:
diff changeset
173 is the upper case first character of the policy name, e.g. 'F' for
kono
parents:
diff changeset
174 FIFO_Within_Priorities. A space ' ' is returned if no
kono
parents:
diff changeset
175 Priority_Specific_Dispatching pragma is used in the partition. */
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 char
kono
parents:
diff changeset
178 __gnat_get_specific_dispatching (int priority)
kono
parents:
diff changeset
179 {
kono
parents:
diff changeset
180 if (__gl_num_specific_dispatching == 0)
kono
parents:
diff changeset
181 return ' ';
kono
parents:
diff changeset
182 else if (priority >= __gl_num_specific_dispatching)
kono
parents:
diff changeset
183 return 'F';
kono
parents:
diff changeset
184 else
kono
parents:
diff changeset
185 return __gl_priority_specific_dispatching [priority];
kono
parents:
diff changeset
186 }
kono
parents:
diff changeset
187
kono
parents:
diff changeset
188 #ifndef IN_RTS
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 /**********************/
kono
parents:
diff changeset
191 /* __gnat_set_globals */
kono
parents:
diff changeset
192 /**********************/
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 /* This routine is kept for bootstrapping purposes, since the binder generated
kono
parents:
diff changeset
195 file now sets the __gl_* variables directly. */
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 void
kono
parents:
diff changeset
198 __gnat_set_globals (void)
kono
parents:
diff changeset
199 {
kono
parents:
diff changeset
200 }
kono
parents:
diff changeset
201
kono
parents:
diff changeset
202 #endif
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 /***************/
kono
parents:
diff changeset
205 /* AIX Section */
kono
parents:
diff changeset
206 /***************/
kono
parents:
diff changeset
207
kono
parents:
diff changeset
208 #if defined (_AIX)
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 #include <signal.h>
kono
parents:
diff changeset
211 #include <sys/time.h>
kono
parents:
diff changeset
212
kono
parents:
diff changeset
213 /* Some versions of AIX don't define SA_NODEFER. */
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 #ifndef SA_NODEFER
kono
parents:
diff changeset
216 #define SA_NODEFER 0
kono
parents:
diff changeset
217 #endif /* SA_NODEFER */
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 /* Versions of AIX before 4.3 don't have nanosleep but provide
kono
parents:
diff changeset
220 nsleep instead. */
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 #ifndef _AIXVERSION_430
kono
parents:
diff changeset
223
kono
parents:
diff changeset
224 extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 int
kono
parents:
diff changeset
227 nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
kono
parents:
diff changeset
228 {
kono
parents:
diff changeset
229 return nsleep (Rqtp, Rmtp);
kono
parents:
diff changeset
230 }
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 #endif /* _AIXVERSION_430 */
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 static void
kono
parents:
diff changeset
235 __gnat_error_handler (int sig,
kono
parents:
diff changeset
236 siginfo_t *si ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
237 void *ucontext ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
238 {
kono
parents:
diff changeset
239 struct Exception_Data *exception;
kono
parents:
diff changeset
240 const char *msg;
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 switch (sig)
kono
parents:
diff changeset
243 {
kono
parents:
diff changeset
244 case SIGSEGV:
kono
parents:
diff changeset
245 /* FIXME: we need to detect the case of a *real* SIGSEGV. */
kono
parents:
diff changeset
246 exception = &storage_error;
kono
parents:
diff changeset
247 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
248 break;
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 case SIGBUS:
kono
parents:
diff changeset
251 exception = &constraint_error;
kono
parents:
diff changeset
252 msg = "SIGBUS";
kono
parents:
diff changeset
253 break;
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 case SIGFPE:
kono
parents:
diff changeset
256 exception = &constraint_error;
kono
parents:
diff changeset
257 msg = "SIGFPE";
kono
parents:
diff changeset
258 break;
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 default:
kono
parents:
diff changeset
261 exception = &program_error;
kono
parents:
diff changeset
262 msg = "unhandled signal";
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
266 }
kono
parents:
diff changeset
267
kono
parents:
diff changeset
268 void
kono
parents:
diff changeset
269 __gnat_install_handler (void)
kono
parents:
diff changeset
270 {
kono
parents:
diff changeset
271 struct sigaction act;
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 /* Set up signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
274 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
275 signal that might cause a scheduling event! */
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
kono
parents:
diff changeset
278 act.sa_sigaction = __gnat_error_handler;
kono
parents:
diff changeset
279 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 /* Do not install handlers if interrupt state is "System". */
kono
parents:
diff changeset
282 if (__gnat_get_interrupt_state (SIGABRT) != 's')
kono
parents:
diff changeset
283 sigaction (SIGABRT, &act, NULL);
kono
parents:
diff changeset
284 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
285 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
286 if (__gnat_get_interrupt_state (SIGILL) != 's')
kono
parents:
diff changeset
287 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
288 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
289 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
290 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
291 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
292
kono
parents:
diff changeset
293 __gnat_handler_installed = 1;
kono
parents:
diff changeset
294 }
kono
parents:
diff changeset
295
kono
parents:
diff changeset
296 /*****************/
kono
parents:
diff changeset
297 /* HP-UX section */
kono
parents:
diff changeset
298 /*****************/
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 #elif defined (__hpux__)
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 #include <signal.h>
kono
parents:
diff changeset
303 #include <sys/ucontext.h>
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 #if defined (IN_RTS) && defined (__ia64__)
kono
parents:
diff changeset
306
kono
parents:
diff changeset
307 #include <sys/uc_access.h>
kono
parents:
diff changeset
308
kono
parents:
diff changeset
309 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 void
kono
parents:
diff changeset
312 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
kono
parents:
diff changeset
313 {
kono
parents:
diff changeset
314 ucontext_t *uc = (ucontext_t *) ucontext;
kono
parents:
diff changeset
315 uint64_t ip;
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 /* Adjust on itanium, as GetIPInfo is not supported. */
kono
parents:
diff changeset
318 __uc_get_ip (uc, &ip);
kono
parents:
diff changeset
319 __uc_set_ip (uc, ip + 1);
kono
parents:
diff changeset
320 }
kono
parents:
diff changeset
321 #endif /* IN_RTS && __ia64__ */
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
kono
parents:
diff changeset
324 propagation after the required low level adjustments. */
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 static void
kono
parents:
diff changeset
327 __gnat_error_handler (int sig, siginfo_t *si ATTRIBUTE_UNUSED, void *ucontext)
kono
parents:
diff changeset
328 {
kono
parents:
diff changeset
329 struct Exception_Data *exception;
kono
parents:
diff changeset
330 const char *msg;
kono
parents:
diff changeset
331
kono
parents:
diff changeset
332 __gnat_adjust_context_for_raise (sig, ucontext);
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 switch (sig)
kono
parents:
diff changeset
335 {
kono
parents:
diff changeset
336 case SIGSEGV:
kono
parents:
diff changeset
337 /* FIXME: we need to detect the case of a *real* SIGSEGV. */
kono
parents:
diff changeset
338 exception = &storage_error;
kono
parents:
diff changeset
339 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
340 break;
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 case SIGBUS:
kono
parents:
diff changeset
343 exception = &constraint_error;
kono
parents:
diff changeset
344 msg = "SIGBUS";
kono
parents:
diff changeset
345 break;
kono
parents:
diff changeset
346
kono
parents:
diff changeset
347 case SIGFPE:
kono
parents:
diff changeset
348 exception = &constraint_error;
kono
parents:
diff changeset
349 msg = "SIGFPE";
kono
parents:
diff changeset
350 break;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 default:
kono
parents:
diff changeset
353 exception = &program_error;
kono
parents:
diff changeset
354 msg = "unhandled signal";
kono
parents:
diff changeset
355 }
kono
parents:
diff changeset
356
kono
parents:
diff changeset
357 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
358 }
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
kono
parents:
diff changeset
361 #if defined (__hppa__)
kono
parents:
diff changeset
362 char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
kono
parents:
diff changeset
363 #else
kono
parents:
diff changeset
364 char __gnat_alternate_stack[128 * 1024]; /* MINSIGSTKSZ */
kono
parents:
diff changeset
365 #endif
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 void
kono
parents:
diff changeset
368 __gnat_install_handler (void)
kono
parents:
diff changeset
369 {
kono
parents:
diff changeset
370 struct sigaction act;
kono
parents:
diff changeset
371
kono
parents:
diff changeset
372 /* Set up signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
373 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
374 signal that might cause a scheduling event! Also setup an alternate
kono
parents:
diff changeset
375 stack region for the handler execution so that stack overflows can be
kono
parents:
diff changeset
376 handled properly, avoiding a SEGV generation from stack usage by the
kono
parents:
diff changeset
377 handler itself. */
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379 stack_t stack;
kono
parents:
diff changeset
380 stack.ss_sp = __gnat_alternate_stack;
kono
parents:
diff changeset
381 stack.ss_size = sizeof (__gnat_alternate_stack);
kono
parents:
diff changeset
382 stack.ss_flags = 0;
kono
parents:
diff changeset
383 sigaltstack (&stack, NULL);
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 act.sa_sigaction = __gnat_error_handler;
kono
parents:
diff changeset
386 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
kono
parents:
diff changeset
387 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
388
kono
parents:
diff changeset
389 /* Do not install handlers if interrupt state is "System". */
kono
parents:
diff changeset
390 if (__gnat_get_interrupt_state (SIGABRT) != 's')
kono
parents:
diff changeset
391 sigaction (SIGABRT, &act, NULL);
kono
parents:
diff changeset
392 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
393 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
394 if (__gnat_get_interrupt_state (SIGILL) != 's')
kono
parents:
diff changeset
395 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
396 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
397 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
398 act.sa_flags |= SA_ONSTACK;
kono
parents:
diff changeset
399 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
400 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
401
kono
parents:
diff changeset
402 __gnat_handler_installed = 1;
kono
parents:
diff changeset
403 }
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 /*********************/
kono
parents:
diff changeset
406 /* GNU/Linux Section */
kono
parents:
diff changeset
407 /*********************/
kono
parents:
diff changeset
408
kono
parents:
diff changeset
409 #elif defined (__linux__)
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 #include <signal.h>
kono
parents:
diff changeset
412
kono
parents:
diff changeset
413 #define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
kono
parents:
diff changeset
414 #include <sys/ucontext.h>
kono
parents:
diff changeset
415
kono
parents:
diff changeset
416 /* GNU/Linux, which uses glibc, does not define NULL in included
kono
parents:
diff changeset
417 header files. */
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 #if !defined (NULL)
kono
parents:
diff changeset
420 #define NULL ((void *) 0)
kono
parents:
diff changeset
421 #endif
kono
parents:
diff changeset
422
kono
parents:
diff changeset
423 #if defined (MaRTE)
kono
parents:
diff changeset
424
kono
parents:
diff changeset
425 /* MaRTE OS provides its own version of sigaction, sigfillset, and
kono
parents:
diff changeset
426 sigemptyset (overriding these symbol names). We want to make sure that
kono
parents:
diff changeset
427 the versions provided by the underlying C library are used here (these
kono
parents:
diff changeset
428 versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
kono
parents:
diff changeset
429 and fake_linux_sigemptyset, respectively). The MaRTE library will not
kono
parents:
diff changeset
430 always be present (it will not be linked if no tasking constructs are
kono
parents:
diff changeset
431 used), so we use the weak symbol mechanism to point always to the symbols
kono
parents:
diff changeset
432 defined within the C library. */
kono
parents:
diff changeset
433
kono
parents:
diff changeset
434 #pragma weak linux_sigaction
kono
parents:
diff changeset
435 int linux_sigaction (int signum, const struct sigaction *act,
kono
parents:
diff changeset
436 struct sigaction *oldact)
kono
parents:
diff changeset
437 {
kono
parents:
diff changeset
438 return sigaction (signum, act, oldact);
kono
parents:
diff changeset
439 }
kono
parents:
diff changeset
440 #define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
kono
parents:
diff changeset
441
kono
parents:
diff changeset
442 #pragma weak fake_linux_sigfillset
kono
parents:
diff changeset
443 void fake_linux_sigfillset (sigset_t *set)
kono
parents:
diff changeset
444 {
kono
parents:
diff changeset
445 sigfillset (set);
kono
parents:
diff changeset
446 }
kono
parents:
diff changeset
447 #define sigfillset(set) fake_linux_sigfillset (set)
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 #pragma weak fake_linux_sigemptyset
kono
parents:
diff changeset
450 void fake_linux_sigemptyset (sigset_t *set)
kono
parents:
diff changeset
451 {
kono
parents:
diff changeset
452 sigemptyset (set);
kono
parents:
diff changeset
453 }
kono
parents:
diff changeset
454 #define sigemptyset(set) fake_linux_sigemptyset (set)
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 #endif
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 #if defined (__i386__) || defined (__x86_64__) || defined (__ia64__) \
kono
parents:
diff changeset
459 || defined (__ARMEL__)
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
462
kono
parents:
diff changeset
463 void
kono
parents:
diff changeset
464 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
kono
parents:
diff changeset
465 {
kono
parents:
diff changeset
466 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 /* On the i386 and x86-64 architectures, stack checking is performed by
kono
parents:
diff changeset
469 means of probes with moving stack pointer, that is to say the probed
kono
parents:
diff changeset
470 address is always the value of the stack pointer. Upon hitting the
kono
parents:
diff changeset
471 guard page, the stack pointer therefore points to an inaccessible
kono
parents:
diff changeset
472 address and an alternate signal stack is needed to run the handler.
kono
parents:
diff changeset
473 But there is an additional twist: on these architectures, the EH
kono
parents:
diff changeset
474 return code writes the address of the handler at the target CFA's
kono
parents:
diff changeset
475 value on the stack before doing the jump. As a consequence, if
kono
parents:
diff changeset
476 there is an active handler in the frame whose stack has overflowed,
kono
parents:
diff changeset
477 the stack pointer must nevertheless point to an accessible address
kono
parents:
diff changeset
478 by the time the EH return is executed.
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 We therefore adjust the saved value of the stack pointer by the size
kono
parents:
diff changeset
481 of one page + a small dope of 4 words, in order to make sure that it
kono
parents:
diff changeset
482 points to an accessible address in case it's used as the target CFA.
kono
parents:
diff changeset
483 The stack checking code guarantees that this address is unused by the
kono
parents:
diff changeset
484 time this happens. */
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 #if defined (__i386__)
kono
parents:
diff changeset
487 unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
kono
parents:
diff changeset
488 /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode. */
kono
parents:
diff changeset
489 if (signo == SIGSEGV && pc && *pc == 0x00240c83)
kono
parents:
diff changeset
490 mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
kono
parents:
diff changeset
491 #elif defined (__x86_64__)
kono
parents:
diff changeset
492 unsigned long long *pc = (unsigned long long *)mcontext->gregs[REG_RIP];
kono
parents:
diff changeset
493 if (signo == SIGSEGV && pc
kono
parents:
diff changeset
494 /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
kono
parents:
diff changeset
495 && ((*pc & 0xffffffffffLL) == 0x00240c8348LL
kono
parents:
diff changeset
496 /* The pattern may also be "orl $0x0,(%esp)" for a probe in
kono
parents:
diff changeset
497 x32 mode. */
kono
parents:
diff changeset
498 || (*pc & 0xffffffffLL) == 0x00240c83LL))
kono
parents:
diff changeset
499 mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
kono
parents:
diff changeset
500 #elif defined (__ia64__)
kono
parents:
diff changeset
501 /* ??? The IA-64 unwinder doesn't compensate for signals. */
kono
parents:
diff changeset
502 mcontext->sc_ip++;
kono
parents:
diff changeset
503 #elif defined (__ARMEL__)
kono
parents:
diff changeset
504 /* ARM Bump has to be an even number because of odd/even architecture. */
kono
parents:
diff changeset
505 mcontext->arm_pc+=2;
kono
parents:
diff changeset
506 #ifdef __thumb2__
kono
parents:
diff changeset
507 #define CPSR_THUMB_BIT 5
kono
parents:
diff changeset
508 /* For thumb, the return address much have the low order bit set, otherwise
kono
parents:
diff changeset
509 the unwinder will reset to "arm" mode upon return. As long as the
kono
parents:
diff changeset
510 compilation unit containing the landing pad is compiled with the same
kono
parents:
diff changeset
511 mode (arm vs thumb) as the signaling compilation unit, this works. */
kono
parents:
diff changeset
512 if (mcontext->arm_cpsr & (1<<CPSR_THUMB_BIT))
kono
parents:
diff changeset
513 mcontext->arm_pc+=1;
kono
parents:
diff changeset
514 #endif
kono
parents:
diff changeset
515 #endif
kono
parents:
diff changeset
516 }
kono
parents:
diff changeset
517
kono
parents:
diff changeset
518 #endif
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 static void
kono
parents:
diff changeset
521 __gnat_error_handler (int sig, siginfo_t *si ATTRIBUTE_UNUSED, void *ucontext)
kono
parents:
diff changeset
522 {
kono
parents:
diff changeset
523 struct Exception_Data *exception;
kono
parents:
diff changeset
524 const char *msg;
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 /* Adjusting is required for every fault context, so adjust for this one
kono
parents:
diff changeset
527 now, before we possibly trigger a recursive fault below. */
kono
parents:
diff changeset
528 __gnat_adjust_context_for_raise (sig, ucontext);
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530 switch (sig)
kono
parents:
diff changeset
531 {
kono
parents:
diff changeset
532 case SIGSEGV:
kono
parents:
diff changeset
533 /* Here we would like a discrimination test to see whether the page
kono
parents:
diff changeset
534 before the faulting address is accessible. Unfortunately, Linux
kono
parents:
diff changeset
535 seems to have no way of giving us the faulting address.
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 In old versions of init.c, we had a test of the page before the
kono
parents:
diff changeset
538 stack pointer:
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 ((volatile char *)
kono
parents:
diff changeset
541 ((long) si->esp_at_signal & - getpagesize ()))[getpagesize ()];
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 but that's wrong since it tests the stack pointer location and the
kono
parents:
diff changeset
544 stack probing code may not move it until all probes succeed.
kono
parents:
diff changeset
545
kono
parents:
diff changeset
546 For now we simply do not attempt any discrimination at all. Note
kono
parents:
diff changeset
547 that this is quite acceptable, since a "real" SIGSEGV can only
kono
parents:
diff changeset
548 occur as the result of an erroneous program. */
kono
parents:
diff changeset
549 exception = &storage_error;
kono
parents:
diff changeset
550 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
551 break;
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 case SIGBUS:
kono
parents:
diff changeset
554 exception = &storage_error;
kono
parents:
diff changeset
555 msg = "SIGBUS: possible stack overflow";
kono
parents:
diff changeset
556 break;
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 case SIGFPE:
kono
parents:
diff changeset
559 exception = &constraint_error;
kono
parents:
diff changeset
560 msg = "SIGFPE";
kono
parents:
diff changeset
561 break;
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 default:
kono
parents:
diff changeset
564 exception = &program_error;
kono
parents:
diff changeset
565 msg = "unhandled signal";
kono
parents:
diff changeset
566 }
kono
parents:
diff changeset
567
kono
parents:
diff changeset
568 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
569 }
kono
parents:
diff changeset
570
kono
parents:
diff changeset
571 #ifndef __ia64__
kono
parents:
diff changeset
572 #define HAVE_GNAT_ALTERNATE_STACK 1
kono
parents:
diff changeset
573 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.
kono
parents:
diff changeset
574 It must be larger than MINSIGSTKSZ and hopefully near 2 * SIGSTKSZ. */
kono
parents:
diff changeset
575 # if 16 * 1024 < MINSIGSTKSZ
kono
parents:
diff changeset
576 # error "__gnat_alternate_stack too small"
kono
parents:
diff changeset
577 # endif
kono
parents:
diff changeset
578 char __gnat_alternate_stack[16 * 1024];
kono
parents:
diff changeset
579 #endif
kono
parents:
diff changeset
580
kono
parents:
diff changeset
581 #ifdef __XENO__
kono
parents:
diff changeset
582 #include <sys/mman.h>
kono
parents:
diff changeset
583 #include <native/task.h>
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585 RT_TASK main_task;
kono
parents:
diff changeset
586 #endif
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 void
kono
parents:
diff changeset
589 __gnat_install_handler (void)
kono
parents:
diff changeset
590 {
kono
parents:
diff changeset
591 struct sigaction act;
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 #ifdef __XENO__
kono
parents:
diff changeset
594 int prio;
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 if (__gl_main_priority == -1)
kono
parents:
diff changeset
597 prio = 49;
kono
parents:
diff changeset
598 else
kono
parents:
diff changeset
599 prio = __gl_main_priority;
kono
parents:
diff changeset
600
kono
parents:
diff changeset
601 /* Avoid memory swapping for this program */
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 mlockall (MCL_CURRENT|MCL_FUTURE);
kono
parents:
diff changeset
604
kono
parents:
diff changeset
605 /* Turn the current Linux task into a native Xenomai task */
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 rt_task_shadow (&main_task, "environment_task", prio, T_FPU);
kono
parents:
diff changeset
608 #endif
kono
parents:
diff changeset
609
kono
parents:
diff changeset
610 /* Set up signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
611 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
612 signal that might cause a scheduling event! Also setup an alternate
kono
parents:
diff changeset
613 stack region for the handler execution so that stack overflows can be
kono
parents:
diff changeset
614 handled properly, avoiding a SEGV generation from stack usage by the
kono
parents:
diff changeset
615 handler itself. */
kono
parents:
diff changeset
616
kono
parents:
diff changeset
617 act.sa_sigaction = __gnat_error_handler;
kono
parents:
diff changeset
618 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
kono
parents:
diff changeset
619 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 /* Do not install handlers if interrupt state is "System". */
kono
parents:
diff changeset
622 if (__gnat_get_interrupt_state (SIGABRT) != 's')
kono
parents:
diff changeset
623 sigaction (SIGABRT, &act, NULL);
kono
parents:
diff changeset
624 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
625 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
626 if (__gnat_get_interrupt_state (SIGILL) != 's')
kono
parents:
diff changeset
627 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
628 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
629 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
630 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
631 {
kono
parents:
diff changeset
632 #ifdef HAVE_GNAT_ALTERNATE_STACK
kono
parents:
diff changeset
633 /* Setup an alternate stack region for the handler execution so that
kono
parents:
diff changeset
634 stack overflows can be handled properly, avoiding a SEGV generation
kono
parents:
diff changeset
635 from stack usage by the handler itself. */
kono
parents:
diff changeset
636 stack_t stack;
kono
parents:
diff changeset
637
kono
parents:
diff changeset
638 stack.ss_sp = __gnat_alternate_stack;
kono
parents:
diff changeset
639 stack.ss_size = sizeof (__gnat_alternate_stack);
kono
parents:
diff changeset
640 stack.ss_flags = 0;
kono
parents:
diff changeset
641 sigaltstack (&stack, NULL);
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 act.sa_flags |= SA_ONSTACK;
kono
parents:
diff changeset
644 #endif
kono
parents:
diff changeset
645 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
646 }
kono
parents:
diff changeset
647
kono
parents:
diff changeset
648 __gnat_handler_installed = 1;
kono
parents:
diff changeset
649 }
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 /*******************/
kono
parents:
diff changeset
652 /* LynxOS Section */
kono
parents:
diff changeset
653 /*******************/
kono
parents:
diff changeset
654
kono
parents:
diff changeset
655 #elif defined (__Lynx__)
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 #include <signal.h>
kono
parents:
diff changeset
658 #include <unistd.h>
kono
parents:
diff changeset
659
kono
parents:
diff changeset
660 static void
kono
parents:
diff changeset
661 __gnat_error_handler (int sig)
kono
parents:
diff changeset
662 {
kono
parents:
diff changeset
663 struct Exception_Data *exception;
kono
parents:
diff changeset
664 const char *msg;
kono
parents:
diff changeset
665
kono
parents:
diff changeset
666 switch(sig)
kono
parents:
diff changeset
667 {
kono
parents:
diff changeset
668 case SIGFPE:
kono
parents:
diff changeset
669 exception = &constraint_error;
kono
parents:
diff changeset
670 msg = "SIGFPE";
kono
parents:
diff changeset
671 break;
kono
parents:
diff changeset
672 case SIGILL:
kono
parents:
diff changeset
673 exception = &constraint_error;
kono
parents:
diff changeset
674 msg = "SIGILL";
kono
parents:
diff changeset
675 break;
kono
parents:
diff changeset
676 case SIGSEGV:
kono
parents:
diff changeset
677 exception = &storage_error;
kono
parents:
diff changeset
678 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
679 break;
kono
parents:
diff changeset
680 case SIGBUS:
kono
parents:
diff changeset
681 exception = &constraint_error;
kono
parents:
diff changeset
682 msg = "SIGBUS";
kono
parents:
diff changeset
683 break;
kono
parents:
diff changeset
684 default:
kono
parents:
diff changeset
685 exception = &program_error;
kono
parents:
diff changeset
686 msg = "unhandled signal";
kono
parents:
diff changeset
687 }
kono
parents:
diff changeset
688
kono
parents:
diff changeset
689 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
690 }
kono
parents:
diff changeset
691
kono
parents:
diff changeset
692 void
kono
parents:
diff changeset
693 __gnat_install_handler (void)
kono
parents:
diff changeset
694 {
kono
parents:
diff changeset
695 struct sigaction act;
kono
parents:
diff changeset
696
kono
parents:
diff changeset
697 act.sa_handler = __gnat_error_handler;
kono
parents:
diff changeset
698 act.sa_flags = 0x0;
kono
parents:
diff changeset
699 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 /* Do not install handlers if interrupt state is "System". */
kono
parents:
diff changeset
702 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
703 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
704 if (__gnat_get_interrupt_state (SIGILL) != 's')
kono
parents:
diff changeset
705 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
706 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
707 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
708 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
709 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 __gnat_handler_installed = 1;
kono
parents:
diff changeset
712 }
kono
parents:
diff changeset
713
kono
parents:
diff changeset
714 /*******************/
kono
parents:
diff changeset
715 /* Solaris Section */
kono
parents:
diff changeset
716 /*******************/
kono
parents:
diff changeset
717
kono
parents:
diff changeset
718 #elif defined (__sun__) && !defined (__vxworks)
kono
parents:
diff changeset
719
kono
parents:
diff changeset
720 #include <signal.h>
kono
parents:
diff changeset
721 #include <siginfo.h>
kono
parents:
diff changeset
722 #include <sys/ucontext.h>
kono
parents:
diff changeset
723 #include <sys/regset.h>
kono
parents:
diff changeset
724
kono
parents:
diff changeset
725 static void
kono
parents:
diff changeset
726 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
727 {
kono
parents:
diff changeset
728 struct Exception_Data *exception;
kono
parents:
diff changeset
729 static int recurse = 0;
kono
parents:
diff changeset
730 const char *msg;
kono
parents:
diff changeset
731
kono
parents:
diff changeset
732 switch (sig)
kono
parents:
diff changeset
733 {
kono
parents:
diff changeset
734 case SIGSEGV:
kono
parents:
diff changeset
735 /* If the problem was permissions, this is a constraint error.
kono
parents:
diff changeset
736 Likewise if the failing address isn't maximally aligned or if
kono
parents:
diff changeset
737 we've recursed.
kono
parents:
diff changeset
738
kono
parents:
diff changeset
739 ??? Using a static variable here isn't task-safe, but it's
kono
parents:
diff changeset
740 much too hard to do anything else and we're just determining
kono
parents:
diff changeset
741 which exception to raise. */
kono
parents:
diff changeset
742 if (si->si_code == SEGV_ACCERR
kono
parents:
diff changeset
743 || (long) si->si_addr == 0
kono
parents:
diff changeset
744 || (((long) si->si_addr) & 3) != 0
kono
parents:
diff changeset
745 || recurse)
kono
parents:
diff changeset
746 {
kono
parents:
diff changeset
747 exception = &constraint_error;
kono
parents:
diff changeset
748 msg = "SIGSEGV";
kono
parents:
diff changeset
749 }
kono
parents:
diff changeset
750 else
kono
parents:
diff changeset
751 {
kono
parents:
diff changeset
752 /* See if the page before the faulting page is accessible. Do that
kono
parents:
diff changeset
753 by trying to access it. We'd like to simply try to access
kono
parents:
diff changeset
754 4096 + the faulting address, but it's not guaranteed to be
kono
parents:
diff changeset
755 the actual address, just to be on the same page. */
kono
parents:
diff changeset
756 recurse++;
kono
parents:
diff changeset
757 ((volatile char *)
kono
parents:
diff changeset
758 ((long) si->si_addr & - getpagesize ()))[getpagesize ()];
kono
parents:
diff changeset
759 exception = &storage_error;
kono
parents:
diff changeset
760 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
761 }
kono
parents:
diff changeset
762 break;
kono
parents:
diff changeset
763
kono
parents:
diff changeset
764 case SIGBUS:
kono
parents:
diff changeset
765 exception = &program_error;
kono
parents:
diff changeset
766 msg = "SIGBUS";
kono
parents:
diff changeset
767 break;
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 case SIGFPE:
kono
parents:
diff changeset
770 exception = &constraint_error;
kono
parents:
diff changeset
771 msg = "SIGFPE";
kono
parents:
diff changeset
772 break;
kono
parents:
diff changeset
773
kono
parents:
diff changeset
774 default:
kono
parents:
diff changeset
775 exception = &program_error;
kono
parents:
diff changeset
776 msg = "unhandled signal";
kono
parents:
diff changeset
777 }
kono
parents:
diff changeset
778
kono
parents:
diff changeset
779 recurse = 0;
kono
parents:
diff changeset
780 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
781 }
kono
parents:
diff changeset
782
kono
parents:
diff changeset
783 void
kono
parents:
diff changeset
784 __gnat_install_handler (void)
kono
parents:
diff changeset
785 {
kono
parents:
diff changeset
786 struct sigaction act;
kono
parents:
diff changeset
787
kono
parents:
diff changeset
788 /* Set up signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
789 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
790 signal that might cause a scheduling event! */
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 act.sa_sigaction = __gnat_error_handler;
kono
parents:
diff changeset
793 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
kono
parents:
diff changeset
794 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 /* Do not install handlers if interrupt state is "System". */
kono
parents:
diff changeset
797 if (__gnat_get_interrupt_state (SIGABRT) != 's')
kono
parents:
diff changeset
798 sigaction (SIGABRT, &act, NULL);
kono
parents:
diff changeset
799 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
800 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
801 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
802 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
803 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
804 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
805
kono
parents:
diff changeset
806 __gnat_handler_installed = 1;
kono
parents:
diff changeset
807 }
kono
parents:
diff changeset
808
kono
parents:
diff changeset
809 /***************/
kono
parents:
diff changeset
810 /* VMS Section */
kono
parents:
diff changeset
811 /***************/
kono
parents:
diff changeset
812
kono
parents:
diff changeset
813 #elif defined (VMS)
kono
parents:
diff changeset
814
kono
parents:
diff changeset
815 /* Routine called from binder to override default feature values. */
kono
parents:
diff changeset
816 void __gnat_set_features (void);
kono
parents:
diff changeset
817 int __gnat_features_set = 0;
kono
parents:
diff changeset
818 void (*__gnat_ctrl_c_handler) (void) = 0;
kono
parents:
diff changeset
819
kono
parents:
diff changeset
820 #ifdef __IA64
kono
parents:
diff changeset
821 #define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
kono
parents:
diff changeset
822 #define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
kono
parents:
diff changeset
823 #define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
kono
parents:
diff changeset
824 #else
kono
parents:
diff changeset
825 #define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
kono
parents:
diff changeset
826 #define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
kono
parents:
diff changeset
827 #define lib_get_invo_handle LIB$GET_INVO_HANDLE
kono
parents:
diff changeset
828 #endif
kono
parents:
diff changeset
829
kono
parents:
diff changeset
830 /* Masks for facility identification. */
kono
parents:
diff changeset
831 #define FAC_MASK 0x0fff0000
kono
parents:
diff changeset
832 #define DECADA_M_FACILITY 0x00310000
kono
parents:
diff changeset
833
kono
parents:
diff changeset
834 /* Define macro symbols for the VMS conditions that become Ada exceptions.
kono
parents:
diff changeset
835 It would be better to just include <ssdef.h> */
kono
parents:
diff changeset
836
kono
parents:
diff changeset
837 #define SS$_CONTINUE 1
kono
parents:
diff changeset
838 #define SS$_ACCVIO 12
kono
parents:
diff changeset
839 #define SS$_HPARITH 1284
kono
parents:
diff changeset
840 #define SS$_INTDIV 1156
kono
parents:
diff changeset
841 #define SS$_STKOVF 1364
kono
parents:
diff changeset
842 #define SS$_CONTROLC 1617
kono
parents:
diff changeset
843 #define SS$_RESIGNAL 2328
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 #define MTH$_FLOOVEMAT 1475268 /* Some ACVC_21 CXA tests */
kono
parents:
diff changeset
846
kono
parents:
diff changeset
847 /* The following codes must be resignalled, and not handled here. */
kono
parents:
diff changeset
848
kono
parents:
diff changeset
849 /* These codes are in standard message libraries. */
kono
parents:
diff changeset
850 extern int C$_SIGKILL;
kono
parents:
diff changeset
851 extern int C$_SIGINT;
kono
parents:
diff changeset
852 extern int SS$_DEBUG;
kono
parents:
diff changeset
853 extern int LIB$_KEYNOTFOU;
kono
parents:
diff changeset
854 extern int LIB$_ACTIMAGE;
kono
parents:
diff changeset
855
kono
parents:
diff changeset
856 /* These codes are non standard, which is to say the author is
kono
parents:
diff changeset
857 not sure if they are defined in the standard message libraries
kono
parents:
diff changeset
858 so keep them as macros for now. */
kono
parents:
diff changeset
859 #define RDB$_STREAM_EOF 20480426
kono
parents:
diff changeset
860 #define FDL$_UNPRIKW 11829410
kono
parents:
diff changeset
861 #define CMA$_EXIT_THREAD 4227492
kono
parents:
diff changeset
862
kono
parents:
diff changeset
863 struct cond_sigargs
kono
parents:
diff changeset
864 {
kono
parents:
diff changeset
865 unsigned int sigarg;
kono
parents:
diff changeset
866 unsigned int sigargval;
kono
parents:
diff changeset
867 };
kono
parents:
diff changeset
868
kono
parents:
diff changeset
869 struct cond_subtests
kono
parents:
diff changeset
870 {
kono
parents:
diff changeset
871 unsigned int num;
kono
parents:
diff changeset
872 const struct cond_sigargs sigargs[];
kono
parents:
diff changeset
873 };
kono
parents:
diff changeset
874
kono
parents:
diff changeset
875 struct cond_except
kono
parents:
diff changeset
876 {
kono
parents:
diff changeset
877 unsigned int cond;
kono
parents:
diff changeset
878 const struct Exception_Data *except;
kono
parents:
diff changeset
879 unsigned int needs_adjust; /* 1 = adjust PC, 0 = no adjust */
kono
parents:
diff changeset
880 const struct cond_subtests *subtests;
kono
parents:
diff changeset
881 };
kono
parents:
diff changeset
882
kono
parents:
diff changeset
883 struct descriptor_s
kono
parents:
diff changeset
884 {
kono
parents:
diff changeset
885 unsigned short len, mbz;
kono
parents:
diff changeset
886 __char_ptr32 adr;
kono
parents:
diff changeset
887 };
kono
parents:
diff changeset
888
kono
parents:
diff changeset
889 /* Conditions that don't have an Ada exception counterpart must raise
kono
parents:
diff changeset
890 Non_Ada_Error. Since this is defined in s-auxdec, it should only be
kono
parents:
diff changeset
891 referenced by user programs, not the compiler or tools. Hence the
kono
parents:
diff changeset
892 #ifdef IN_RTS. */
kono
parents:
diff changeset
893
kono
parents:
diff changeset
894 #ifdef IN_RTS
kono
parents:
diff changeset
895
kono
parents:
diff changeset
896 #define Status_Error ada__io_exceptions__status_error
kono
parents:
diff changeset
897 extern struct Exception_Data Status_Error;
kono
parents:
diff changeset
898
kono
parents:
diff changeset
899 #define Mode_Error ada__io_exceptions__mode_error
kono
parents:
diff changeset
900 extern struct Exception_Data Mode_Error;
kono
parents:
diff changeset
901
kono
parents:
diff changeset
902 #define Name_Error ada__io_exceptions__name_error
kono
parents:
diff changeset
903 extern struct Exception_Data Name_Error;
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 #define Use_Error ada__io_exceptions__use_error
kono
parents:
diff changeset
906 extern struct Exception_Data Use_Error;
kono
parents:
diff changeset
907
kono
parents:
diff changeset
908 #define Device_Error ada__io_exceptions__device_error
kono
parents:
diff changeset
909 extern struct Exception_Data Device_Error;
kono
parents:
diff changeset
910
kono
parents:
diff changeset
911 #define End_Error ada__io_exceptions__end_error
kono
parents:
diff changeset
912 extern struct Exception_Data End_Error;
kono
parents:
diff changeset
913
kono
parents:
diff changeset
914 #define Data_Error ada__io_exceptions__data_error
kono
parents:
diff changeset
915 extern struct Exception_Data Data_Error;
kono
parents:
diff changeset
916
kono
parents:
diff changeset
917 #define Layout_Error ada__io_exceptions__layout_error
kono
parents:
diff changeset
918 extern struct Exception_Data Layout_Error;
kono
parents:
diff changeset
919
kono
parents:
diff changeset
920 #define Non_Ada_Error system__aux_dec__non_ada_error
kono
parents:
diff changeset
921 extern struct Exception_Data Non_Ada_Error;
kono
parents:
diff changeset
922
kono
parents:
diff changeset
923 #define Coded_Exception system__vms_exception_table__coded_exception
kono
parents:
diff changeset
924 extern struct Exception_Data *Coded_Exception (void *);
kono
parents:
diff changeset
925
kono
parents:
diff changeset
926 #define Base_Code_In system__vms_exception_table__base_code_in
kono
parents:
diff changeset
927 extern void *Base_Code_In (void *);
kono
parents:
diff changeset
928
kono
parents:
diff changeset
929 /* DEC Ada exceptions are not defined in a header file, so they
kono
parents:
diff changeset
930 must be declared. */
kono
parents:
diff changeset
931
kono
parents:
diff changeset
932 #define ADA$_ALREADY_OPEN 0x0031a594
kono
parents:
diff changeset
933 #define ADA$_CONSTRAINT_ERRO 0x00318324
kono
parents:
diff changeset
934 #define ADA$_DATA_ERROR 0x003192c4
kono
parents:
diff changeset
935 #define ADA$_DEVICE_ERROR 0x003195e4
kono
parents:
diff changeset
936 #define ADA$_END_ERROR 0x00319904
kono
parents:
diff changeset
937 #define ADA$_FAC_MODE_MISMAT 0x0031a8b3
kono
parents:
diff changeset
938 #define ADA$_IOSYSFAILED 0x0031af04
kono
parents:
diff changeset
939 #define ADA$_KEYSIZERR 0x0031aa3c
kono
parents:
diff changeset
940 #define ADA$_KEY_MISMATCH 0x0031a8e3
kono
parents:
diff changeset
941 #define ADA$_LAYOUT_ERROR 0x00319c24
kono
parents:
diff changeset
942 #define ADA$_LINEXCMRS 0x0031a8f3
kono
parents:
diff changeset
943 #define ADA$_MAXLINEXC 0x0031a8eb
kono
parents:
diff changeset
944 #define ADA$_MODE_ERROR 0x00319f44
kono
parents:
diff changeset
945 #define ADA$_MRN_MISMATCH 0x0031a8db
kono
parents:
diff changeset
946 #define ADA$_MRS_MISMATCH 0x0031a8d3
kono
parents:
diff changeset
947 #define ADA$_NAME_ERROR 0x0031a264
kono
parents:
diff changeset
948 #define ADA$_NOT_OPEN 0x0031a58c
kono
parents:
diff changeset
949 #define ADA$_ORG_MISMATCH 0x0031a8bb
kono
parents:
diff changeset
950 #define ADA$_PROGRAM_ERROR 0x00318964
kono
parents:
diff changeset
951 #define ADA$_RAT_MISMATCH 0x0031a8cb
kono
parents:
diff changeset
952 #define ADA$_RFM_MISMATCH 0x0031a8c3
kono
parents:
diff changeset
953 #define ADA$_STAOVF 0x00318cac
kono
parents:
diff changeset
954 #define ADA$_STATUS_ERROR 0x0031a584
kono
parents:
diff changeset
955 #define ADA$_STORAGE_ERROR 0x00318c84
kono
parents:
diff changeset
956 #define ADA$_UNSUPPORTED 0x0031a8ab
kono
parents:
diff changeset
957 #define ADA$_USE_ERROR 0x0031a8a4
kono
parents:
diff changeset
958
kono
parents:
diff changeset
959 /* DEC Ada specific conditions. */
kono
parents:
diff changeset
960 static const struct cond_except dec_ada_cond_except_table [] =
kono
parents:
diff changeset
961 {
kono
parents:
diff changeset
962 {ADA$_PROGRAM_ERROR, &program_error, 0, 0},
kono
parents:
diff changeset
963 {ADA$_USE_ERROR, &Use_Error, 0, 0},
kono
parents:
diff changeset
964 {ADA$_KEYSIZERR, &program_error, 0, 0},
kono
parents:
diff changeset
965 {ADA$_STAOVF, &storage_error, 0, 0},
kono
parents:
diff changeset
966 {ADA$_CONSTRAINT_ERRO, &constraint_error, 0, 0},
kono
parents:
diff changeset
967 {ADA$_IOSYSFAILED, &Device_Error, 0, 0},
kono
parents:
diff changeset
968 {ADA$_LAYOUT_ERROR, &Layout_Error, 0, 0},
kono
parents:
diff changeset
969 {ADA$_STORAGE_ERROR, &storage_error, 0, 0},
kono
parents:
diff changeset
970 {ADA$_DATA_ERROR, &Data_Error, 0, 0},
kono
parents:
diff changeset
971 {ADA$_DEVICE_ERROR, &Device_Error, 0, 0},
kono
parents:
diff changeset
972 {ADA$_END_ERROR, &End_Error, 0, 0},
kono
parents:
diff changeset
973 {ADA$_MODE_ERROR, &Mode_Error, 0, 0},
kono
parents:
diff changeset
974 {ADA$_NAME_ERROR, &Name_Error, 0, 0},
kono
parents:
diff changeset
975 {ADA$_STATUS_ERROR, &Status_Error, 0, 0},
kono
parents:
diff changeset
976 {ADA$_NOT_OPEN, &Use_Error, 0, 0},
kono
parents:
diff changeset
977 {ADA$_ALREADY_OPEN, &Use_Error, 0, 0},
kono
parents:
diff changeset
978 {ADA$_USE_ERROR, &Use_Error, 0, 0},
kono
parents:
diff changeset
979 {ADA$_UNSUPPORTED, &Use_Error, 0, 0},
kono
parents:
diff changeset
980 {ADA$_FAC_MODE_MISMAT, &Use_Error, 0, 0},
kono
parents:
diff changeset
981 {ADA$_ORG_MISMATCH, &Use_Error, 0, 0},
kono
parents:
diff changeset
982 {ADA$_RFM_MISMATCH, &Use_Error, 0, 0},
kono
parents:
diff changeset
983 {ADA$_RAT_MISMATCH, &Use_Error, 0, 0},
kono
parents:
diff changeset
984 {ADA$_MRS_MISMATCH, &Use_Error, 0, 0},
kono
parents:
diff changeset
985 {ADA$_MRN_MISMATCH, &Use_Error, 0, 0},
kono
parents:
diff changeset
986 {ADA$_KEY_MISMATCH, &Use_Error, 0, 0},
kono
parents:
diff changeset
987 {ADA$_MAXLINEXC, &constraint_error, 0, 0},
kono
parents:
diff changeset
988 {ADA$_LINEXCMRS, &constraint_error, 0, 0},
kono
parents:
diff changeset
989
kono
parents:
diff changeset
990 #if 0
kono
parents:
diff changeset
991 /* Already handled by a pragma Import_Exception
kono
parents:
diff changeset
992 in Aux_IO_Exceptions */
kono
parents:
diff changeset
993 {ADA$_LOCK_ERROR, &Lock_Error, 0, 0},
kono
parents:
diff changeset
994 {ADA$_EXISTENCE_ERROR, &Existence_Error, 0, 0},
kono
parents:
diff changeset
995 {ADA$_KEY_ERROR, &Key_Error, 0, 0},
kono
parents:
diff changeset
996 #endif
kono
parents:
diff changeset
997
kono
parents:
diff changeset
998 {0, 0, 0, 0}
kono
parents:
diff changeset
999 };
kono
parents:
diff changeset
1000
kono
parents:
diff changeset
1001 #endif /* IN_RTS */
kono
parents:
diff changeset
1002
kono
parents:
diff changeset
1003 /* Non-DEC Ada specific conditions that map to Ada exceptions. */
kono
parents:
diff changeset
1004
kono
parents:
diff changeset
1005 /* Subtest for ACCVIO Constraint_Error, kept for compatibility,
kono
parents:
diff changeset
1006 in hindsight should have just made ACCVIO == Storage_Error. */
kono
parents:
diff changeset
1007 #define ACCVIO_VIRTUAL_ADDR 3
kono
parents:
diff changeset
1008 static const struct cond_subtests accvio_c_e =
kono
parents:
diff changeset
1009 {1, /* number of subtests below */
kono
parents:
diff changeset
1010 {
kono
parents:
diff changeset
1011 { ACCVIO_VIRTUAL_ADDR, 0 }
kono
parents:
diff changeset
1012 }
kono
parents:
diff changeset
1013 };
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 /* Macro flag to adjust PC which gets off by one for some conditions,
kono
parents:
diff changeset
1016 not sure if this is reliably true, PC could be off by more for
kono
parents:
diff changeset
1017 HPARITH for example, unless a trapb is inserted. */
kono
parents:
diff changeset
1018 #define NEEDS_ADJUST 1
kono
parents:
diff changeset
1019
kono
parents:
diff changeset
1020 static const struct cond_except system_cond_except_table [] =
kono
parents:
diff changeset
1021 {
kono
parents:
diff changeset
1022 {MTH$_FLOOVEMAT, &constraint_error, 0, 0},
kono
parents:
diff changeset
1023 {SS$_INTDIV, &constraint_error, 0, 0},
kono
parents:
diff changeset
1024 {SS$_HPARITH, &constraint_error, NEEDS_ADJUST, 0},
kono
parents:
diff changeset
1025 {SS$_ACCVIO, &constraint_error, NEEDS_ADJUST, &accvio_c_e},
kono
parents:
diff changeset
1026 {SS$_ACCVIO, &storage_error, NEEDS_ADJUST, 0},
kono
parents:
diff changeset
1027 {SS$_STKOVF, &storage_error, NEEDS_ADJUST, 0},
kono
parents:
diff changeset
1028 {0, 0, 0, 0}
kono
parents:
diff changeset
1029 };
kono
parents:
diff changeset
1030
kono
parents:
diff changeset
1031 /* To deal with VMS conditions and their mapping to Ada exceptions,
kono
parents:
diff changeset
1032 the __gnat_error_handler routine below is installed as an exception
kono
parents:
diff changeset
1033 vector having precedence over DEC frame handlers. Some conditions
kono
parents:
diff changeset
1034 still need to be handled by such handlers, however, in which case
kono
parents:
diff changeset
1035 __gnat_error_handler needs to return SS$_RESIGNAL. Consider for
kono
parents:
diff changeset
1036 instance the use of a third party library compiled with DECAda and
kono
parents:
diff changeset
1037 performing its own exception handling internally.
kono
parents:
diff changeset
1038
kono
parents:
diff changeset
1039 To allow some user-level flexibility, which conditions should be
kono
parents:
diff changeset
1040 resignaled is controlled by a predicate function, provided with the
kono
parents:
diff changeset
1041 condition value and returning a boolean indication stating whether
kono
parents:
diff changeset
1042 this condition should be resignaled or not.
kono
parents:
diff changeset
1043
kono
parents:
diff changeset
1044 That predicate function is called indirectly, via a function pointer,
kono
parents:
diff changeset
1045 by __gnat_error_handler, and changing that pointer is allowed to the
kono
parents:
diff changeset
1046 user code by way of the __gnat_set_resignal_predicate interface.
kono
parents:
diff changeset
1047
kono
parents:
diff changeset
1048 The user level function may then implement what it likes, including
kono
parents:
diff changeset
1049 for instance the maintenance of a dynamic data structure if the set
kono
parents:
diff changeset
1050 of to be resignalled conditions has to change over the program's
kono
parents:
diff changeset
1051 lifetime.
kono
parents:
diff changeset
1052
kono
parents:
diff changeset
1053 ??? This is not a perfect solution to deal with the possible
kono
parents:
diff changeset
1054 interactions between the GNAT and the DECAda exception handling
kono
parents:
diff changeset
1055 models and better (more general) schemes are studied. This is so
kono
parents:
diff changeset
1056 just provided as a convenient workaround in the meantime, and
kono
parents:
diff changeset
1057 should be use with caution since the implementation has been kept
kono
parents:
diff changeset
1058 very simple. */
kono
parents:
diff changeset
1059
kono
parents:
diff changeset
1060 typedef int resignal_predicate (int code);
kono
parents:
diff changeset
1061
kono
parents:
diff changeset
1062 static const int * const cond_resignal_table [] =
kono
parents:
diff changeset
1063 {
kono
parents:
diff changeset
1064 &C$_SIGKILL,
kono
parents:
diff changeset
1065 (int *)CMA$_EXIT_THREAD,
kono
parents:
diff changeset
1066 &SS$_DEBUG,
kono
parents:
diff changeset
1067 &LIB$_KEYNOTFOU,
kono
parents:
diff changeset
1068 &LIB$_ACTIMAGE,
kono
parents:
diff changeset
1069 (int *) RDB$_STREAM_EOF,
kono
parents:
diff changeset
1070 (int *) FDL$_UNPRIKW,
kono
parents:
diff changeset
1071 0
kono
parents:
diff changeset
1072 };
kono
parents:
diff changeset
1073
kono
parents:
diff changeset
1074 static const int facility_resignal_table [] =
kono
parents:
diff changeset
1075 {
kono
parents:
diff changeset
1076 0x1380000, /* RDB */
kono
parents:
diff changeset
1077 0x2220000, /* SQL */
kono
parents:
diff changeset
1078 0
kono
parents:
diff changeset
1079 };
kono
parents:
diff changeset
1080
kono
parents:
diff changeset
1081 /* Default GNAT predicate for resignaling conditions. */
kono
parents:
diff changeset
1082
kono
parents:
diff changeset
1083 static int
kono
parents:
diff changeset
1084 __gnat_default_resignal_p (int code)
kono
parents:
diff changeset
1085 {
kono
parents:
diff changeset
1086 int i, iexcept;
kono
parents:
diff changeset
1087
kono
parents:
diff changeset
1088 for (i = 0; facility_resignal_table [i]; i++)
kono
parents:
diff changeset
1089 if ((code & FAC_MASK) == facility_resignal_table [i])
kono
parents:
diff changeset
1090 return 1;
kono
parents:
diff changeset
1091
kono
parents:
diff changeset
1092 for (i = 0, iexcept = 0;
kono
parents:
diff changeset
1093 cond_resignal_table [i]
kono
parents:
diff changeset
1094 && !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
kono
parents:
diff changeset
1095 i++);
kono
parents:
diff changeset
1096
kono
parents:
diff changeset
1097 return iexcept;
kono
parents:
diff changeset
1098 }
kono
parents:
diff changeset
1099
kono
parents:
diff changeset
1100 /* Static pointer to predicate that the __gnat_error_handler exception
kono
parents:
diff changeset
1101 vector invokes to determine if it should resignal a condition. */
kono
parents:
diff changeset
1102
kono
parents:
diff changeset
1103 static resignal_predicate *__gnat_resignal_p = __gnat_default_resignal_p;
kono
parents:
diff changeset
1104
kono
parents:
diff changeset
1105 /* User interface to change the predicate pointer to PREDICATE. Reset to
kono
parents:
diff changeset
1106 the default if PREDICATE is null. */
kono
parents:
diff changeset
1107
kono
parents:
diff changeset
1108 void
kono
parents:
diff changeset
1109 __gnat_set_resignal_predicate (resignal_predicate *predicate)
kono
parents:
diff changeset
1110 {
kono
parents:
diff changeset
1111 if (predicate == NULL)
kono
parents:
diff changeset
1112 __gnat_resignal_p = __gnat_default_resignal_p;
kono
parents:
diff changeset
1113 else
kono
parents:
diff changeset
1114 __gnat_resignal_p = predicate;
kono
parents:
diff changeset
1115 }
kono
parents:
diff changeset
1116
kono
parents:
diff changeset
1117 /* Should match System.Parameters.Default_Exception_Msg_Max_Length. */
kono
parents:
diff changeset
1118 #define Default_Exception_Msg_Max_Length 512
kono
parents:
diff changeset
1119
kono
parents:
diff changeset
1120 /* Action routine for SYS$PUTMSG. There may be multiple
kono
parents:
diff changeset
1121 conditions, each with text to be appended to MESSAGE
kono
parents:
diff changeset
1122 and separated by line termination. */
kono
parents:
diff changeset
1123 static int
kono
parents:
diff changeset
1124 copy_msg (struct descriptor_s *msgdesc, char *message)
kono
parents:
diff changeset
1125 {
kono
parents:
diff changeset
1126 int len = strlen (message);
kono
parents:
diff changeset
1127 int copy_len;
kono
parents:
diff changeset
1128
kono
parents:
diff changeset
1129 /* Check for buffer overflow and skip. */
kono
parents:
diff changeset
1130 if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
kono
parents:
diff changeset
1131 {
kono
parents:
diff changeset
1132 strcat (message, "\r\n");
kono
parents:
diff changeset
1133 len += 2;
kono
parents:
diff changeset
1134 }
kono
parents:
diff changeset
1135
kono
parents:
diff changeset
1136 /* Check for buffer overflow and truncate if necessary. */
kono
parents:
diff changeset
1137 copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
kono
parents:
diff changeset
1138 msgdesc->len :
kono
parents:
diff changeset
1139 Default_Exception_Msg_Max_Length - 1 - len);
kono
parents:
diff changeset
1140 strncpy (&message [len], msgdesc->adr, copy_len);
kono
parents:
diff changeset
1141 message [len + copy_len] = 0;
kono
parents:
diff changeset
1142
kono
parents:
diff changeset
1143 return 0;
kono
parents:
diff changeset
1144 }
kono
parents:
diff changeset
1145
kono
parents:
diff changeset
1146 /* Scan TABLE for a match for the condition contained in SIGARGS,
kono
parents:
diff changeset
1147 and return the entry, or the empty entry if no match found. */
kono
parents:
diff changeset
1148 static const struct cond_except *
kono
parents:
diff changeset
1149 scan_conditions ( int *sigargs, const struct cond_except *table [])
kono
parents:
diff changeset
1150 {
kono
parents:
diff changeset
1151 int i;
kono
parents:
diff changeset
1152 struct cond_except entry;
kono
parents:
diff changeset
1153
kono
parents:
diff changeset
1154 /* Scan the exception condition table for a match and fetch
kono
parents:
diff changeset
1155 the associated GNAT exception pointer. */
kono
parents:
diff changeset
1156 for (i = 0; (*table) [i].cond; i++)
kono
parents:
diff changeset
1157 {
kono
parents:
diff changeset
1158 unsigned int match = LIB$MATCH_COND (&sigargs [1], &(*table) [i].cond);
kono
parents:
diff changeset
1159 const struct cond_subtests *subtests = (*table) [i].subtests;
kono
parents:
diff changeset
1160
kono
parents:
diff changeset
1161 if (match)
kono
parents:
diff changeset
1162 {
kono
parents:
diff changeset
1163 if (!subtests)
kono
parents:
diff changeset
1164 {
kono
parents:
diff changeset
1165 return &(*table) [i];
kono
parents:
diff changeset
1166 }
kono
parents:
diff changeset
1167 else
kono
parents:
diff changeset
1168 {
kono
parents:
diff changeset
1169 unsigned int ii;
kono
parents:
diff changeset
1170 int num = (*subtests).num;
kono
parents:
diff changeset
1171
kono
parents:
diff changeset
1172 /* Perform subtests to differentiate exception. */
kono
parents:
diff changeset
1173 for (ii = 0; ii < num; ii++)
kono
parents:
diff changeset
1174 {
kono
parents:
diff changeset
1175 unsigned int arg = (*subtests).sigargs [ii].sigarg;
kono
parents:
diff changeset
1176 unsigned int argval = (*subtests).sigargs [ii].sigargval;
kono
parents:
diff changeset
1177
kono
parents:
diff changeset
1178 if (sigargs [arg] != argval)
kono
parents:
diff changeset
1179 {
kono
parents:
diff changeset
1180 num = 0;
kono
parents:
diff changeset
1181 break;
kono
parents:
diff changeset
1182 }
kono
parents:
diff changeset
1183 }
kono
parents:
diff changeset
1184
kono
parents:
diff changeset
1185 /* All subtests passed. */
kono
parents:
diff changeset
1186 if (num == (*subtests).num)
kono
parents:
diff changeset
1187 return &(*table) [i];
kono
parents:
diff changeset
1188 }
kono
parents:
diff changeset
1189 }
kono
parents:
diff changeset
1190 }
kono
parents:
diff changeset
1191
kono
parents:
diff changeset
1192 /* No match, return the null terminating entry. */
kono
parents:
diff changeset
1193 return &(*table) [i];
kono
parents:
diff changeset
1194 }
kono
parents:
diff changeset
1195
kono
parents:
diff changeset
1196 /* __gnat_handle_vms_condtition is both a frame based handler
kono
parents:
diff changeset
1197 for the runtime, and an exception vector for the compiler. */
kono
parents:
diff changeset
1198 long
kono
parents:
diff changeset
1199 __gnat_handle_vms_condition (int *sigargs, void *mechargs)
kono
parents:
diff changeset
1200 {
kono
parents:
diff changeset
1201 struct Exception_Data *exception = 0;
kono
parents:
diff changeset
1202 unsigned int needs_adjust = 0;
kono
parents:
diff changeset
1203 void *base_code;
kono
parents:
diff changeset
1204 struct descriptor_s gnat_facility = {4, 0, "GNAT"};
kono
parents:
diff changeset
1205 char message [Default_Exception_Msg_Max_Length];
kono
parents:
diff changeset
1206
kono
parents:
diff changeset
1207 const char *msg = "";
kono
parents:
diff changeset
1208
kono
parents:
diff changeset
1209 /* Check for conditions to resignal which aren't effected by pragma
kono
parents:
diff changeset
1210 Import_Exception. */
kono
parents:
diff changeset
1211 if (__gnat_resignal_p (sigargs [1]))
kono
parents:
diff changeset
1212 return SS$_RESIGNAL;
kono
parents:
diff changeset
1213 #ifndef IN_RTS
kono
parents:
diff changeset
1214 /* toplev.c handles this for compiler. */
kono
parents:
diff changeset
1215 if (sigargs [1] == SS$_HPARITH)
kono
parents:
diff changeset
1216 return SS$_RESIGNAL;
kono
parents:
diff changeset
1217 #endif
kono
parents:
diff changeset
1218
kono
parents:
diff changeset
1219 #ifdef IN_RTS
kono
parents:
diff changeset
1220 /* See if it's an imported exception. Beware that registered exceptions
kono
parents:
diff changeset
1221 are bound to their base code, with the severity bits masked off. */
kono
parents:
diff changeset
1222 base_code = Base_Code_In ((void *) sigargs[1]);
kono
parents:
diff changeset
1223 exception = Coded_Exception (base_code);
kono
parents:
diff changeset
1224 #endif
kono
parents:
diff changeset
1225
kono
parents:
diff changeset
1226 if (exception == 0)
kono
parents:
diff changeset
1227 #ifdef IN_RTS
kono
parents:
diff changeset
1228 {
kono
parents:
diff changeset
1229 int i;
kono
parents:
diff changeset
1230 struct cond_except cond;
kono
parents:
diff changeset
1231 const struct cond_except *cond_table;
kono
parents:
diff changeset
1232 const struct cond_except *cond_tables [] = {dec_ada_cond_except_table,
kono
parents:
diff changeset
1233 system_cond_except_table,
kono
parents:
diff changeset
1234 0};
kono
parents:
diff changeset
1235 unsigned int ctrlc = SS$_CONTROLC;
kono
parents:
diff changeset
1236 unsigned int *sigint = &C$_SIGINT;
kono
parents:
diff changeset
1237 int ctrlc_match = LIB$MATCH_COND (&sigargs [1], &ctrlc);
kono
parents:
diff changeset
1238 int sigint_match = LIB$MATCH_COND (&sigargs [1], &sigint);
kono
parents:
diff changeset
1239
kono
parents:
diff changeset
1240 extern int SYS$DCLAST (void (*astadr)(), unsigned long long astprm,
kono
parents:
diff changeset
1241 unsigned int acmode);
kono
parents:
diff changeset
1242
kono
parents:
diff changeset
1243 /* If SS$_CONTROLC has been imported as an exception, it will take
kono
parents:
diff changeset
1244 priority over a Ctrl/C handler. See above. SIGINT has a
kono
parents:
diff changeset
1245 different condition value due to it's DECCCRTL roots and it's
kono
parents:
diff changeset
1246 the condition that gets raised for a "kill -INT". */
kono
parents:
diff changeset
1247 if ((ctrlc_match || sigint_match) && __gnat_ctrl_c_handler)
kono
parents:
diff changeset
1248 {
kono
parents:
diff changeset
1249 SYS$DCLAST (__gnat_ctrl_c_handler, 0, 0);
kono
parents:
diff changeset
1250 return SS$_CONTINUE;
kono
parents:
diff changeset
1251 }
kono
parents:
diff changeset
1252
kono
parents:
diff changeset
1253 i = 0;
kono
parents:
diff changeset
1254 while ((cond_table = cond_tables[i++]) && !exception)
kono
parents:
diff changeset
1255 {
kono
parents:
diff changeset
1256 cond = *scan_conditions (sigargs, &cond_table);
kono
parents:
diff changeset
1257 exception = (struct Exception_Data *) cond.except;
kono
parents:
diff changeset
1258 }
kono
parents:
diff changeset
1259
kono
parents:
diff changeset
1260 if (exception)
kono
parents:
diff changeset
1261 needs_adjust = cond.needs_adjust;
kono
parents:
diff changeset
1262 else
kono
parents:
diff changeset
1263 /* User programs expect Non_Ada_Error to be raised if no match,
kono
parents:
diff changeset
1264 reference DEC Ada test CXCONDHAN. */
kono
parents:
diff changeset
1265 exception = &Non_Ada_Error;
kono
parents:
diff changeset
1266 }
kono
parents:
diff changeset
1267 #else
kono
parents:
diff changeset
1268 {
kono
parents:
diff changeset
1269 /* Pretty much everything is just a program error in the compiler */
kono
parents:
diff changeset
1270 exception = &program_error;
kono
parents:
diff changeset
1271 }
kono
parents:
diff changeset
1272 #endif
kono
parents:
diff changeset
1273
kono
parents:
diff changeset
1274 message[0] = 0;
kono
parents:
diff changeset
1275 /* Subtract PC & PSL fields as per ABI for SYS$PUTMSG. */
kono
parents:
diff changeset
1276 sigargs[0] -= 2;
kono
parents:
diff changeset
1277
kono
parents:
diff changeset
1278 extern int SYS$PUTMSG (void *, int (*)(), void *, unsigned long long);
kono
parents:
diff changeset
1279
kono
parents:
diff changeset
1280 /* If it was a DEC Ada specific condtiion, make it GNAT otherwise
kono
parents:
diff changeset
1281 keep the old facility. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1282 if ((sigargs [1] & FAC_MASK) == DECADA_M_FACILITY)
111
kono
parents:
diff changeset
1283 SYS$PUTMSG (sigargs, copy_msg, &gnat_facility,
kono
parents:
diff changeset
1284 (unsigned long long ) message);
kono
parents:
diff changeset
1285 else
kono
parents:
diff changeset
1286 SYS$PUTMSG (sigargs, copy_msg, 0,
kono
parents:
diff changeset
1287 (unsigned long long ) message);
kono
parents:
diff changeset
1288
kono
parents:
diff changeset
1289 /* Add back PC & PSL fields as per ABI for SYS$PUTMSG. */
kono
parents:
diff changeset
1290 sigargs[0] += 2;
kono
parents:
diff changeset
1291 msg = message;
kono
parents:
diff changeset
1292
kono
parents:
diff changeset
1293 if (needs_adjust)
kono
parents:
diff changeset
1294 __gnat_adjust_context_for_raise (sigargs [1], (void *)mechargs);
kono
parents:
diff changeset
1295
kono
parents:
diff changeset
1296 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
1297 }
kono
parents:
diff changeset
1298
kono
parents:
diff changeset
1299 #if defined (IN_RTS) && defined (__IA64)
kono
parents:
diff changeset
1300 /* Called only from adasigio.b32. This is a band aid to avoid going
kono
parents:
diff changeset
1301 through the VMS signal handling code which results in a 0x8000 per
kono
parents:
diff changeset
1302 handled exception memory leak in P2 space (see VMS source listing
kono
parents:
diff changeset
1303 sys/lis/exception.lis) due to the allocation of working space that
kono
parents:
diff changeset
1304 is expected to be deallocated upon return from the condition handler,
kono
parents:
diff changeset
1305 which doesn't return in GNAT compiled code. */
kono
parents:
diff changeset
1306 void
kono
parents:
diff changeset
1307 GNAT$STOP (int *sigargs)
kono
parents:
diff changeset
1308 {
kono
parents:
diff changeset
1309 /* Note that there are no mechargs. We rely on the fact that condtions
kono
parents:
diff changeset
1310 raised from DEClib I/O do not require an "adjust". Also the count
kono
parents:
diff changeset
1311 will be off by 2, since LIB$STOP didn't get a chance to add the
kono
parents:
diff changeset
1312 PC and PSL fields, so we bump it so PUTMSG comes out right. */
kono
parents:
diff changeset
1313 sigargs [0] += 2;
kono
parents:
diff changeset
1314 __gnat_handle_vms_condition (sigargs, 0);
kono
parents:
diff changeset
1315 }
kono
parents:
diff changeset
1316 #endif
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318 void
kono
parents:
diff changeset
1319 __gnat_install_handler (void)
kono
parents:
diff changeset
1320 {
kono
parents:
diff changeset
1321 long prvhnd ATTRIBUTE_UNUSED;
kono
parents:
diff changeset
1322
kono
parents:
diff changeset
1323 #if !defined (IN_RTS)
kono
parents:
diff changeset
1324 extern int SYS$SETEXV (unsigned int vector, int (*addres)(),
kono
parents:
diff changeset
1325 unsigned int accmode, void *(*(prvhnd)));
kono
parents:
diff changeset
1326 SYS$SETEXV (1, __gnat_handle_vms_condition, 3, &prvhnd);
kono
parents:
diff changeset
1327 #endif
kono
parents:
diff changeset
1328
kono
parents:
diff changeset
1329 __gnat_handler_installed = 1;
kono
parents:
diff changeset
1330 }
kono
parents:
diff changeset
1331
kono
parents:
diff changeset
1332 /* __gnat_adjust_context_for_raise for Alpha - see comments along with the
kono
parents:
diff changeset
1333 default version later in this file. */
kono
parents:
diff changeset
1334
kono
parents:
diff changeset
1335 #if defined (IN_RTS) && defined (__alpha__)
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 #include <vms/chfctxdef.h>
kono
parents:
diff changeset
1338 #include <vms/chfdef.h>
kono
parents:
diff changeset
1339
kono
parents:
diff changeset
1340 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
1341
kono
parents:
diff changeset
1342 void
kono
parents:
diff changeset
1343 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
kono
parents:
diff changeset
1344 {
kono
parents:
diff changeset
1345 if (signo == SS$_HPARITH)
kono
parents:
diff changeset
1346 {
kono
parents:
diff changeset
1347 /* Sub one to the address of the instruction signaling the condition,
kono
parents:
diff changeset
1348 located in the sigargs array. */
kono
parents:
diff changeset
1349
kono
parents:
diff changeset
1350 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
kono
parents:
diff changeset
1351 CHF$SIGNAL_ARRAY * sigargs
kono
parents:
diff changeset
1352 = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
kono
parents:
diff changeset
1353
kono
parents:
diff changeset
1354 int vcount = sigargs->chf$is_sig_args;
kono
parents:
diff changeset
1355 int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
kono
parents:
diff changeset
1356
kono
parents:
diff changeset
1357 (*pc_slot)--;
kono
parents:
diff changeset
1358 }
kono
parents:
diff changeset
1359 }
kono
parents:
diff changeset
1360
kono
parents:
diff changeset
1361 #endif
kono
parents:
diff changeset
1362
kono
parents:
diff changeset
1363 /* __gnat_adjust_context_for_raise for ia64. */
kono
parents:
diff changeset
1364
kono
parents:
diff changeset
1365 #if defined (IN_RTS) && defined (__IA64)
kono
parents:
diff changeset
1366
kono
parents:
diff changeset
1367 #include <vms/chfctxdef.h>
kono
parents:
diff changeset
1368 #include <vms/chfdef.h>
kono
parents:
diff changeset
1369
kono
parents:
diff changeset
1370 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
1371
kono
parents:
diff changeset
1372 typedef unsigned long long u64;
kono
parents:
diff changeset
1373
kono
parents:
diff changeset
1374 void
kono
parents:
diff changeset
1375 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
kono
parents:
diff changeset
1376 {
kono
parents:
diff changeset
1377 /* Add one to the address of the instruction signaling the condition,
kono
parents:
diff changeset
1378 located in the 64bits sigargs array. */
kono
parents:
diff changeset
1379
kono
parents:
diff changeset
1380 CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
kono
parents:
diff changeset
1381
kono
parents:
diff changeset
1382 CHF64$SIGNAL_ARRAY *chfsig64
kono
parents:
diff changeset
1383 = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
kono
parents:
diff changeset
1384
kono
parents:
diff changeset
1385 u64 * post_sigarray
kono
parents:
diff changeset
1386 = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
kono
parents:
diff changeset
1387
kono
parents:
diff changeset
1388 u64 * ih_pc_loc = post_sigarray - 2;
kono
parents:
diff changeset
1389
kono
parents:
diff changeset
1390 (*ih_pc_loc) ++;
kono
parents:
diff changeset
1391 }
kono
parents:
diff changeset
1392
kono
parents:
diff changeset
1393 #endif
kono
parents:
diff changeset
1394
kono
parents:
diff changeset
1395 /* Easier interface for LIB$GET_LOGICAL: put the equivalence of NAME into BUF,
kono
parents:
diff changeset
1396 always NUL terminated. In case of error or if the result is longer than
kono
parents:
diff changeset
1397 LEN (length of BUF) an empty string is written info BUF. */
kono
parents:
diff changeset
1398
kono
parents:
diff changeset
1399 static void
kono
parents:
diff changeset
1400 __gnat_vms_get_logical (const char *name, char *buf, int len)
kono
parents:
diff changeset
1401 {
kono
parents:
diff changeset
1402 struct descriptor_s name_desc, result_desc;
kono
parents:
diff changeset
1403 int status;
kono
parents:
diff changeset
1404 unsigned short rlen;
kono
parents:
diff changeset
1405
kono
parents:
diff changeset
1406 /* Build the descriptor for NAME. */
kono
parents:
diff changeset
1407 name_desc.len = strlen (name);
kono
parents:
diff changeset
1408 name_desc.mbz = 0;
kono
parents:
diff changeset
1409 name_desc.adr = (char *)name;
kono
parents:
diff changeset
1410
kono
parents:
diff changeset
1411 /* Build the descriptor for the result. */
kono
parents:
diff changeset
1412 result_desc.len = len;
kono
parents:
diff changeset
1413 result_desc.mbz = 0;
kono
parents:
diff changeset
1414 result_desc.adr = buf;
kono
parents:
diff changeset
1415
kono
parents:
diff changeset
1416 status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
kono
parents:
diff changeset
1417
kono
parents:
diff changeset
1418 if ((status & 1) == 1 && rlen < len)
kono
parents:
diff changeset
1419 buf[rlen] = 0;
kono
parents:
diff changeset
1420 else
kono
parents:
diff changeset
1421 buf[0] = 0;
kono
parents:
diff changeset
1422 }
kono
parents:
diff changeset
1423
kono
parents:
diff changeset
1424 /* Size of a page on ia64 and alpha VMS. */
kono
parents:
diff changeset
1425 #define VMS_PAGESIZE 8192
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427 /* User mode. */
kono
parents:
diff changeset
1428 #define PSL__C_USER 3
kono
parents:
diff changeset
1429
kono
parents:
diff changeset
1430 /* No access. */
kono
parents:
diff changeset
1431 #define PRT__C_NA 0
kono
parents:
diff changeset
1432
kono
parents:
diff changeset
1433 /* Descending region. */
kono
parents:
diff changeset
1434 #define VA__M_DESCEND 1
kono
parents:
diff changeset
1435
kono
parents:
diff changeset
1436 /* Get by virtual address. */
kono
parents:
diff changeset
1437 #define VA___REGSUM_BY_VA 1
kono
parents:
diff changeset
1438
kono
parents:
diff changeset
1439 /* Memory region summary. */
kono
parents:
diff changeset
1440 struct regsum
kono
parents:
diff changeset
1441 {
kono
parents:
diff changeset
1442 unsigned long long q_region_id;
kono
parents:
diff changeset
1443 unsigned int l_flags;
kono
parents:
diff changeset
1444 unsigned int l_region_protection;
kono
parents:
diff changeset
1445 void *pq_start_va;
kono
parents:
diff changeset
1446 unsigned long long q_region_size;
kono
parents:
diff changeset
1447 void *pq_first_free_va;
kono
parents:
diff changeset
1448 };
kono
parents:
diff changeset
1449
kono
parents:
diff changeset
1450 extern int SYS$GET_REGION_INFO (unsigned int, unsigned long long *,
kono
parents:
diff changeset
1451 void *, void *, unsigned int,
kono
parents:
diff changeset
1452 void *, unsigned int *);
kono
parents:
diff changeset
1453 extern int SYS$EXPREG_64 (unsigned long long *, unsigned long long,
kono
parents:
diff changeset
1454 unsigned int, unsigned int, void **,
kono
parents:
diff changeset
1455 unsigned long long *);
kono
parents:
diff changeset
1456 extern int SYS$SETPRT_64 (void *, unsigned long long, unsigned int,
kono
parents:
diff changeset
1457 unsigned int, void **, unsigned long long *,
kono
parents:
diff changeset
1458 unsigned int *);
kono
parents:
diff changeset
1459
kono
parents:
diff changeset
1460 /* Add a guard page in the memory region containing ADDR at ADDR +/- SIZE.
kono
parents:
diff changeset
1461 (The sign depends on the kind of the memory region). */
kono
parents:
diff changeset
1462
kono
parents:
diff changeset
1463 static int
kono
parents:
diff changeset
1464 __gnat_set_stack_guard_page (void *addr, unsigned long size)
kono
parents:
diff changeset
1465 {
kono
parents:
diff changeset
1466 int status;
kono
parents:
diff changeset
1467 void *ret_va;
kono
parents:
diff changeset
1468 unsigned long long ret_len;
kono
parents:
diff changeset
1469 unsigned int ret_prot;
kono
parents:
diff changeset
1470 void *start_va;
kono
parents:
diff changeset
1471 unsigned long long length;
kono
parents:
diff changeset
1472 unsigned int retlen;
kono
parents:
diff changeset
1473 struct regsum buffer;
kono
parents:
diff changeset
1474
kono
parents:
diff changeset
1475 /* Get the region for ADDR. */
kono
parents:
diff changeset
1476 status = SYS$GET_REGION_INFO
kono
parents:
diff changeset
1477 (VA___REGSUM_BY_VA, NULL, addr, NULL, sizeof (buffer), &buffer, &retlen);
kono
parents:
diff changeset
1478
kono
parents:
diff changeset
1479 if ((status & 1) != 1)
kono
parents:
diff changeset
1480 return -1;
kono
parents:
diff changeset
1481
kono
parents:
diff changeset
1482 /* Extend the region. */
kono
parents:
diff changeset
1483 status = SYS$EXPREG_64 (&buffer.q_region_id,
kono
parents:
diff changeset
1484 size, 0, 0, &start_va, &length);
kono
parents:
diff changeset
1485
kono
parents:
diff changeset
1486 if ((status & 1) != 1)
kono
parents:
diff changeset
1487 return -1;
kono
parents:
diff changeset
1488
kono
parents:
diff changeset
1489 /* Create a guard page. */
kono
parents:
diff changeset
1490 if (!(buffer.l_flags & VA__M_DESCEND))
kono
parents:
diff changeset
1491 start_va = (void *)((unsigned long long)start_va + length - VMS_PAGESIZE);
kono
parents:
diff changeset
1492
kono
parents:
diff changeset
1493 status = SYS$SETPRT_64 (start_va, VMS_PAGESIZE, PSL__C_USER, PRT__C_NA,
kono
parents:
diff changeset
1494 &ret_va, &ret_len, &ret_prot);
kono
parents:
diff changeset
1495
kono
parents:
diff changeset
1496 if ((status & 1) != 1)
kono
parents:
diff changeset
1497 return -1;
kono
parents:
diff changeset
1498 return 0;
kono
parents:
diff changeset
1499 }
kono
parents:
diff changeset
1500
kono
parents:
diff changeset
1501 /* Read logicals to limit the stack(s) size. */
kono
parents:
diff changeset
1502
kono
parents:
diff changeset
1503 static void
kono
parents:
diff changeset
1504 __gnat_set_stack_limit (void)
kono
parents:
diff changeset
1505 {
kono
parents:
diff changeset
1506 #ifdef __ia64__
kono
parents:
diff changeset
1507 void *sp;
kono
parents:
diff changeset
1508 unsigned long size;
kono
parents:
diff changeset
1509 char value[16];
kono
parents:
diff changeset
1510 char *e;
kono
parents:
diff changeset
1511
kono
parents:
diff changeset
1512 /* The main stack. */
kono
parents:
diff changeset
1513 __gnat_vms_get_logical ("GNAT_STACK_SIZE", value, sizeof (value));
kono
parents:
diff changeset
1514 size = strtoul (value, &e, 0);
kono
parents:
diff changeset
1515 if (e > value && *e == 0)
kono
parents:
diff changeset
1516 {
kono
parents:
diff changeset
1517 asm ("mov %0=sp" : "=r" (sp));
kono
parents:
diff changeset
1518 __gnat_set_stack_guard_page (sp, size * 1024);
kono
parents:
diff changeset
1519 }
kono
parents:
diff changeset
1520
kono
parents:
diff changeset
1521 /* The register stack. */
kono
parents:
diff changeset
1522 __gnat_vms_get_logical ("GNAT_RBS_SIZE", value, sizeof (value));
kono
parents:
diff changeset
1523 size = strtoul (value, &e, 0);
kono
parents:
diff changeset
1524 if (e > value && *e == 0)
kono
parents:
diff changeset
1525 {
kono
parents:
diff changeset
1526 asm ("mov %0=ar.bsp" : "=r" (sp));
kono
parents:
diff changeset
1527 __gnat_set_stack_guard_page (sp, size * 1024);
kono
parents:
diff changeset
1528 }
kono
parents:
diff changeset
1529 #endif
kono
parents:
diff changeset
1530 }
kono
parents:
diff changeset
1531
kono
parents:
diff changeset
1532 #ifdef IN_RTS
kono
parents:
diff changeset
1533 extern int SYS$IEEE_SET_FP_CONTROL (void *, void *, void *);
kono
parents:
diff changeset
1534 #define K_TRUE 1
kono
parents:
diff changeset
1535 #define __int64 long long
kono
parents:
diff changeset
1536 #define __NEW_STARLET
kono
parents:
diff changeset
1537 #include <vms/ieeedef.h>
kono
parents:
diff changeset
1538 #endif
kono
parents:
diff changeset
1539
kono
parents:
diff changeset
1540 /* Feature logical name and global variable address pair.
kono
parents:
diff changeset
1541 If we ever add another feature logical to this list, the
kono
parents:
diff changeset
1542 feature struct will need to be enhanced to take into account
kono
parents:
diff changeset
1543 possible values for *gl_addr. */
kono
parents:
diff changeset
1544 struct feature {
kono
parents:
diff changeset
1545 const char *name;
kono
parents:
diff changeset
1546 int *gl_addr;
kono
parents:
diff changeset
1547 };
kono
parents:
diff changeset
1548
kono
parents:
diff changeset
1549 /* Default values for GNAT features set by environment or binder. */
kono
parents:
diff changeset
1550 int __gl_heap_size = 64;
kono
parents:
diff changeset
1551
kono
parents:
diff changeset
1552 /* Default float format is 'I' meaning IEEE. If gnatbind detetcts that a
kono
parents:
diff changeset
1553 VAX Float format is specified, it will set this global variable to 'V'.
kono
parents:
diff changeset
1554 Subsequently __gnat_set_features will test the variable and if set for
kono
parents:
diff changeset
1555 VAX Float will call a Starlet function to enable trapping for invalid
kono
parents:
diff changeset
1556 operation, drivide by zero, and overflow. This will prevent the VMS runtime
kono
parents:
diff changeset
1557 (specifically OTS$CHECK_FP_MODE) from complaining about inconsistent
kono
parents:
diff changeset
1558 floating point settings in a mixed language program. Ideally the setting
kono
parents:
diff changeset
1559 would be determined at link time based on setttings in the object files,
kono
parents:
diff changeset
1560 however the VMS linker seems to take the setting from the first object
kono
parents:
diff changeset
1561 in the link, e.g. pcrt0.o which is float representation neutral. */
kono
parents:
diff changeset
1562 char __gl_float_format = 'I';
kono
parents:
diff changeset
1563
kono
parents:
diff changeset
1564 /* Array feature logical names and global variable addresses. */
kono
parents:
diff changeset
1565 static const struct feature features[] =
kono
parents:
diff changeset
1566 {
kono
parents:
diff changeset
1567 {"GNAT$NO_MALLOC_64", &__gl_heap_size},
kono
parents:
diff changeset
1568 {0, 0}
kono
parents:
diff changeset
1569 };
kono
parents:
diff changeset
1570
kono
parents:
diff changeset
1571 void
kono
parents:
diff changeset
1572 __gnat_set_features (void)
kono
parents:
diff changeset
1573 {
kono
parents:
diff changeset
1574 int i;
kono
parents:
diff changeset
1575 char buff[16];
kono
parents:
diff changeset
1576 #ifdef IN_RTS
kono
parents:
diff changeset
1577 IEEE clrmsk, setmsk, prvmsk;
kono
parents:
diff changeset
1578
kono
parents:
diff changeset
1579 clrmsk.ieee$q_flags = 0LL;
kono
parents:
diff changeset
1580 setmsk.ieee$q_flags = 0LL;
kono
parents:
diff changeset
1581 #endif
kono
parents:
diff changeset
1582
kono
parents:
diff changeset
1583 /* Loop through features array and test name for enable/disable. */
kono
parents:
diff changeset
1584 for (i = 0; features[i].name; i++)
kono
parents:
diff changeset
1585 {
kono
parents:
diff changeset
1586 __gnat_vms_get_logical (features[i].name, buff, sizeof (buff));
kono
parents:
diff changeset
1587
kono
parents:
diff changeset
1588 if (strcmp (buff, "ENABLE") == 0
kono
parents:
diff changeset
1589 || strcmp (buff, "TRUE") == 0
kono
parents:
diff changeset
1590 || strcmp (buff, "1") == 0)
kono
parents:
diff changeset
1591 *features[i].gl_addr = 32;
kono
parents:
diff changeset
1592 else if (strcmp (buff, "DISABLE") == 0
kono
parents:
diff changeset
1593 || strcmp (buff, "FALSE") == 0
kono
parents:
diff changeset
1594 || strcmp (buff, "0") == 0)
kono
parents:
diff changeset
1595 *features[i].gl_addr = 64;
kono
parents:
diff changeset
1596 }
kono
parents:
diff changeset
1597
kono
parents:
diff changeset
1598 /* Features to artificially limit the stack size. */
kono
parents:
diff changeset
1599 __gnat_set_stack_limit ();
kono
parents:
diff changeset
1600
kono
parents:
diff changeset
1601 #ifdef IN_RTS
kono
parents:
diff changeset
1602 if (__gl_float_format == 'V')
kono
parents:
diff changeset
1603 {
kono
parents:
diff changeset
1604 setmsk.ieee$v_trap_enable_inv = K_TRUE;
kono
parents:
diff changeset
1605 setmsk.ieee$v_trap_enable_dze = K_TRUE;
kono
parents:
diff changeset
1606 setmsk.ieee$v_trap_enable_ovf = K_TRUE;
kono
parents:
diff changeset
1607 SYS$IEEE_SET_FP_CONTROL (&clrmsk, &setmsk, &prvmsk);
kono
parents:
diff changeset
1608 }
kono
parents:
diff changeset
1609 #endif
kono
parents:
diff changeset
1610
kono
parents:
diff changeset
1611 __gnat_features_set = 1;
kono
parents:
diff changeset
1612 }
kono
parents:
diff changeset
1613
kono
parents:
diff changeset
1614 /* Return true if the VMS version is 7.x. */
kono
parents:
diff changeset
1615
kono
parents:
diff changeset
1616 extern unsigned int LIB$GETSYI (int *, ...);
kono
parents:
diff changeset
1617
kono
parents:
diff changeset
1618 #define SYI$_VERSION 0x1000
kono
parents:
diff changeset
1619
kono
parents:
diff changeset
1620 int
kono
parents:
diff changeset
1621 __gnat_is_vms_v7 (void)
kono
parents:
diff changeset
1622 {
kono
parents:
diff changeset
1623 struct descriptor_s desc;
kono
parents:
diff changeset
1624 char version[8];
kono
parents:
diff changeset
1625 int status;
kono
parents:
diff changeset
1626 int code = SYI$_VERSION;
kono
parents:
diff changeset
1627
kono
parents:
diff changeset
1628 desc.len = sizeof (version);
kono
parents:
diff changeset
1629 desc.mbz = 0;
kono
parents:
diff changeset
1630 desc.adr = version;
kono
parents:
diff changeset
1631
kono
parents:
diff changeset
1632 status = LIB$GETSYI (&code, 0, &desc);
kono
parents:
diff changeset
1633 if ((status & 1) == 1 && version[1] == '7' && version[2] == '.')
kono
parents:
diff changeset
1634 return 1;
kono
parents:
diff changeset
1635 else
kono
parents:
diff changeset
1636 return 0;
kono
parents:
diff changeset
1637 }
kono
parents:
diff changeset
1638
kono
parents:
diff changeset
1639 /*******************/
kono
parents:
diff changeset
1640 /* FreeBSD Section */
kono
parents:
diff changeset
1641 /*******************/
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 #elif defined (__FreeBSD__) || defined (__DragonFly__)
kono
parents:
diff changeset
1644
kono
parents:
diff changeset
1645 #include <signal.h>
kono
parents:
diff changeset
1646 #include <sys/ucontext.h>
kono
parents:
diff changeset
1647 #include <unistd.h>
kono
parents:
diff changeset
1648
kono
parents:
diff changeset
1649 static void
kono
parents:
diff changeset
1650 __gnat_error_handler (int sig,
kono
parents:
diff changeset
1651 siginfo_t *si ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1652 void *ucontext ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
1653 {
kono
parents:
diff changeset
1654 struct Exception_Data *exception;
kono
parents:
diff changeset
1655 const char *msg;
kono
parents:
diff changeset
1656
kono
parents:
diff changeset
1657 switch (sig)
kono
parents:
diff changeset
1658 {
kono
parents:
diff changeset
1659 case SIGFPE:
kono
parents:
diff changeset
1660 exception = &constraint_error;
kono
parents:
diff changeset
1661 msg = "SIGFPE";
kono
parents:
diff changeset
1662 break;
kono
parents:
diff changeset
1663
kono
parents:
diff changeset
1664 case SIGILL:
kono
parents:
diff changeset
1665 exception = &constraint_error;
kono
parents:
diff changeset
1666 msg = "SIGILL";
kono
parents:
diff changeset
1667 break;
kono
parents:
diff changeset
1668
kono
parents:
diff changeset
1669 case SIGSEGV:
kono
parents:
diff changeset
1670 exception = &storage_error;
kono
parents:
diff changeset
1671 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
1672 break;
kono
parents:
diff changeset
1673
kono
parents:
diff changeset
1674 case SIGBUS:
kono
parents:
diff changeset
1675 exception = &storage_error;
kono
parents:
diff changeset
1676 msg = "SIGBUS: possible stack overflow";
kono
parents:
diff changeset
1677 break;
kono
parents:
diff changeset
1678
kono
parents:
diff changeset
1679 default:
kono
parents:
diff changeset
1680 exception = &program_error;
kono
parents:
diff changeset
1681 msg = "unhandled signal";
kono
parents:
diff changeset
1682 }
kono
parents:
diff changeset
1683
kono
parents:
diff changeset
1684 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
1685 }
kono
parents:
diff changeset
1686
kono
parents:
diff changeset
1687 void
kono
parents:
diff changeset
1688 __gnat_install_handler (void)
kono
parents:
diff changeset
1689 {
kono
parents:
diff changeset
1690 struct sigaction act;
kono
parents:
diff changeset
1691
kono
parents:
diff changeset
1692 /* Set up signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
1693 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
1694 signal that might cause a scheduling event! */
kono
parents:
diff changeset
1695
kono
parents:
diff changeset
1696 act.sa_sigaction
kono
parents:
diff changeset
1697 = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
kono
parents:
diff changeset
1698 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
kono
parents:
diff changeset
1699 (void) sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
1700
kono
parents:
diff changeset
1701 (void) sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
1702 (void) sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
1703 (void) sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
1704 (void) sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
1705
kono
parents:
diff changeset
1706 __gnat_handler_installed = 1;
kono
parents:
diff changeset
1707 }
kono
parents:
diff changeset
1708
kono
parents:
diff changeset
1709 /*************************************/
kono
parents:
diff changeset
1710 /* VxWorks Section (including Vx653) */
kono
parents:
diff changeset
1711 /*************************************/
kono
parents:
diff changeset
1712
kono
parents:
diff changeset
1713 #elif defined(__vxworks)
kono
parents:
diff changeset
1714
kono
parents:
diff changeset
1715 #include <signal.h>
kono
parents:
diff changeset
1716 #include <taskLib.h>
kono
parents:
diff changeset
1717 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
kono
parents:
diff changeset
1718 #include <sysLib.h>
kono
parents:
diff changeset
1719 #endif
kono
parents:
diff changeset
1720
kono
parents:
diff changeset
1721 #include "sigtramp.h"
kono
parents:
diff changeset
1722
kono
parents:
diff changeset
1723 #ifndef __RTP__
kono
parents:
diff changeset
1724 #include <intLib.h>
kono
parents:
diff changeset
1725 #include <iv.h>
kono
parents:
diff changeset
1726 #endif
kono
parents:
diff changeset
1727
kono
parents:
diff changeset
1728 #if ((defined (ARMEL) && (_WRS_VXWORKS_MAJOR == 6)) || defined (__x86_64__)) && !defined(__RTP__)
kono
parents:
diff changeset
1729 #define VXWORKS_FORCE_GUARD_PAGE 1
kono
parents:
diff changeset
1730 #include <vmLib.h>
kono
parents:
diff changeset
1731 extern size_t vxIntStackOverflowSize;
kono
parents:
diff changeset
1732 #define INT_OVERFLOW_SIZE vxIntStackOverflowSize
kono
parents:
diff changeset
1733 #endif
kono
parents:
diff changeset
1734
kono
parents:
diff changeset
1735 #ifdef VTHREADS
kono
parents:
diff changeset
1736 #include "private/vThreadsP.h"
kono
parents:
diff changeset
1737 #endif
kono
parents:
diff changeset
1738
kono
parents:
diff changeset
1739 #ifndef __RTP__
kono
parents:
diff changeset
1740
kono
parents:
diff changeset
1741 /* Directly vectored Interrupt routines are not supported when using RTPs. */
kono
parents:
diff changeset
1742
kono
parents:
diff changeset
1743 extern void * __gnat_inum_to_ivec (int);
kono
parents:
diff changeset
1744
kono
parents:
diff changeset
1745 /* This is needed by the GNAT run time to handle Vxworks interrupts. */
kono
parents:
diff changeset
1746 void *
kono
parents:
diff changeset
1747 __gnat_inum_to_ivec (int num)
kono
parents:
diff changeset
1748 {
kono
parents:
diff changeset
1749 return (void *) INUM_TO_IVEC (num);
kono
parents:
diff changeset
1750 }
kono
parents:
diff changeset
1751 #endif
kono
parents:
diff changeset
1752
kono
parents:
diff changeset
1753 #if !defined(__alpha_vxworks) && ((_WRS_VXWORKS_MAJOR != 6) && (_WRS_VXWORKS_MAJOR != 7)) && !defined(__RTP__)
kono
parents:
diff changeset
1754
kono
parents:
diff changeset
1755 /* getpid is used by s-parint.adb, but is not defined by VxWorks, except
kono
parents:
diff changeset
1756 on Alpha VxWorks and VxWorks 6.x (including RTPs). */
kono
parents:
diff changeset
1757
kono
parents:
diff changeset
1758 extern long getpid (void);
kono
parents:
diff changeset
1759
kono
parents:
diff changeset
1760 long
kono
parents:
diff changeset
1761 getpid (void)
kono
parents:
diff changeset
1762 {
kono
parents:
diff changeset
1763 return taskIdSelf ();
kono
parents:
diff changeset
1764 }
kono
parents:
diff changeset
1765 #endif
kono
parents:
diff changeset
1766
kono
parents:
diff changeset
1767 /* When stack checking is performed by probing a guard page on the stack,
kono
parents:
diff changeset
1768 sometimes this guard page is not properly reset on VxWorks. We need to
kono
parents:
diff changeset
1769 manually reset it in this case.
kono
parents:
diff changeset
1770 This function returns TRUE in case the guard page was hit by the
kono
parents:
diff changeset
1771 signal. */
kono
parents:
diff changeset
1772 static int
kono
parents:
diff changeset
1773 __gnat_reset_guard_page (int sig)
kono
parents:
diff changeset
1774 {
kono
parents:
diff changeset
1775 /* On ARM VxWorks 6.x and x86_64 VxWorks 7, the guard page is left un-armed
kono
parents:
diff changeset
1776 by the kernel after being violated, so subsequent violations aren't
kono
parents:
diff changeset
1777 detected.
kono
parents:
diff changeset
1778 So we retrieve the address of the guard page from the TCB and compare it
kono
parents:
diff changeset
1779 with the page that is violated and re-arm that page if there's a match. */
kono
parents:
diff changeset
1780 #if defined (VXWORKS_FORCE_GUARD_PAGE)
kono
parents:
diff changeset
1781
kono
parents:
diff changeset
1782 /* Ignore signals that are not stack overflow signals */
kono
parents:
diff changeset
1783 if (sig != SIGSEGV && sig != SIGBUS && sig != SIGILL) return FALSE;
kono
parents:
diff changeset
1784
kono
parents:
diff changeset
1785 /* If the target does not support guard pages, INT_OVERFLOW_SIZE will be 0 */
kono
parents:
diff changeset
1786 if (INT_OVERFLOW_SIZE == 0) return FALSE;
kono
parents:
diff changeset
1787
kono
parents:
diff changeset
1788 TASK_ID tid = taskIdSelf ();
kono
parents:
diff changeset
1789 WIND_TCB *pTcb = taskTcb (tid);
kono
parents:
diff changeset
1790 VIRT_ADDR guardPage = (VIRT_ADDR) pTcb->pStackEnd - INT_OVERFLOW_SIZE;
kono
parents:
diff changeset
1791 UINT stateMask = VM_STATE_MASK_VALID;
kono
parents:
diff changeset
1792 UINT guardState = VM_STATE_VALID_NOT;
kono
parents:
diff changeset
1793
kono
parents:
diff changeset
1794 #if (_WRS_VXWORKS_MAJOR >= 7)
kono
parents:
diff changeset
1795 stateMask |= MMU_ATTR_SPL_MSK;
kono
parents:
diff changeset
1796 guardState |= MMU_ATTR_NO_BLOCK;
kono
parents:
diff changeset
1797 #endif
kono
parents:
diff changeset
1798
kono
parents:
diff changeset
1799 UINT nState;
kono
parents:
diff changeset
1800 vmStateGet (NULL, guardPage, &nState);
kono
parents:
diff changeset
1801 if ((nState & VM_STATE_MASK_VALID) != VM_STATE_VALID_NOT)
kono
parents:
diff changeset
1802 {
kono
parents:
diff changeset
1803 /* If the guard page has a valid state, we need to reset to
kono
parents:
diff changeset
1804 invalid state here */
kono
parents:
diff changeset
1805 vmStateSet (NULL, guardPage, INT_OVERFLOW_SIZE, stateMask, guardState);
kono
parents:
diff changeset
1806 return TRUE;
kono
parents:
diff changeset
1807 }
kono
parents:
diff changeset
1808 #endif /* VXWORKS_FORCE_GUARD_PAGE */
kono
parents:
diff changeset
1809 return FALSE;
kono
parents:
diff changeset
1810 }
kono
parents:
diff changeset
1811
kono
parents:
diff changeset
1812 /* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
kono
parents:
diff changeset
1813 handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
kono
parents:
diff changeset
1814 doesn't. */
kono
parents:
diff changeset
1815 void
kono
parents:
diff changeset
1816 __gnat_clear_exception_count (void)
kono
parents:
diff changeset
1817 {
kono
parents:
diff changeset
1818 #ifdef VTHREADS
kono
parents:
diff changeset
1819 WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
kono
parents:
diff changeset
1820
kono
parents:
diff changeset
1821 currentTask->vThreads.excCnt = 0;
kono
parents:
diff changeset
1822 #endif
kono
parents:
diff changeset
1823 }
kono
parents:
diff changeset
1824
kono
parents:
diff changeset
1825 /* Handle different SIGnal to exception mappings in different VxWorks
kono
parents:
diff changeset
1826 versions. */
kono
parents:
diff changeset
1827 void
kono
parents:
diff changeset
1828 __gnat_map_signal (int sig,
kono
parents:
diff changeset
1829 siginfo_t *si ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1830 void *sc ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
1831 {
kono
parents:
diff changeset
1832 struct Exception_Data *exception;
kono
parents:
diff changeset
1833 const char *msg;
kono
parents:
diff changeset
1834
kono
parents:
diff changeset
1835 switch (sig)
kono
parents:
diff changeset
1836 {
kono
parents:
diff changeset
1837 case SIGFPE:
kono
parents:
diff changeset
1838 exception = &constraint_error;
kono
parents:
diff changeset
1839 msg = "SIGFPE";
kono
parents:
diff changeset
1840 break;
kono
parents:
diff changeset
1841 #ifdef VTHREADS
kono
parents:
diff changeset
1842 #ifdef __VXWORKSMILS__
kono
parents:
diff changeset
1843 case SIGILL:
kono
parents:
diff changeset
1844 exception = &storage_error;
kono
parents:
diff changeset
1845 msg = "SIGILL: possible stack overflow";
kono
parents:
diff changeset
1846 break;
kono
parents:
diff changeset
1847 case SIGSEGV:
kono
parents:
diff changeset
1848 exception = &storage_error;
kono
parents:
diff changeset
1849 msg = "SIGSEGV";
kono
parents:
diff changeset
1850 break;
kono
parents:
diff changeset
1851 case SIGBUS:
kono
parents:
diff changeset
1852 exception = &program_error;
kono
parents:
diff changeset
1853 msg = "SIGBUS";
kono
parents:
diff changeset
1854 break;
kono
parents:
diff changeset
1855 #else
kono
parents:
diff changeset
1856 case SIGILL:
kono
parents:
diff changeset
1857 exception = &constraint_error;
kono
parents:
diff changeset
1858 msg = "Floating point exception or SIGILL";
kono
parents:
diff changeset
1859 break;
kono
parents:
diff changeset
1860 case SIGSEGV:
kono
parents:
diff changeset
1861 exception = &storage_error;
kono
parents:
diff changeset
1862 msg = "SIGSEGV";
kono
parents:
diff changeset
1863 break;
kono
parents:
diff changeset
1864 case SIGBUS:
kono
parents:
diff changeset
1865 exception = &storage_error;
kono
parents:
diff changeset
1866 msg = "SIGBUS: possible stack overflow";
kono
parents:
diff changeset
1867 break;
kono
parents:
diff changeset
1868 #endif
kono
parents:
diff changeset
1869 #elif (_WRS_VXWORKS_MAJOR >= 6)
kono
parents:
diff changeset
1870 case SIGILL:
kono
parents:
diff changeset
1871 exception = &constraint_error;
kono
parents:
diff changeset
1872 msg = "SIGILL";
kono
parents:
diff changeset
1873 break;
kono
parents:
diff changeset
1874 #ifdef __RTP__
kono
parents:
diff changeset
1875 /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
kono
parents:
diff changeset
1876 since stack checking uses the probing mechanism. */
kono
parents:
diff changeset
1877 case SIGSEGV:
kono
parents:
diff changeset
1878 exception = &storage_error;
kono
parents:
diff changeset
1879 msg = "SIGSEGV: possible stack overflow";
kono
parents:
diff changeset
1880 break;
kono
parents:
diff changeset
1881 case SIGBUS:
kono
parents:
diff changeset
1882 exception = &program_error;
kono
parents:
diff changeset
1883 msg = "SIGBUS";
kono
parents:
diff changeset
1884 break;
kono
parents:
diff changeset
1885 #else
kono
parents:
diff changeset
1886 /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
kono
parents:
diff changeset
1887 case SIGSEGV:
kono
parents:
diff changeset
1888 exception = &storage_error;
kono
parents:
diff changeset
1889 msg = "SIGSEGV";
kono
parents:
diff changeset
1890 break;
kono
parents:
diff changeset
1891 case SIGBUS:
kono
parents:
diff changeset
1892 exception = &storage_error;
kono
parents:
diff changeset
1893 msg = "SIGBUS: possible stack overflow";
kono
parents:
diff changeset
1894 break;
kono
parents:
diff changeset
1895 #endif
kono
parents:
diff changeset
1896 #else
kono
parents:
diff changeset
1897 /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
kono
parents:
diff changeset
1898 since stack checking uses the stack limit mechanism. */
kono
parents:
diff changeset
1899 case SIGILL:
kono
parents:
diff changeset
1900 exception = &storage_error;
kono
parents:
diff changeset
1901 msg = "SIGILL: possible stack overflow";
kono
parents:
diff changeset
1902 break;
kono
parents:
diff changeset
1903 case SIGSEGV:
kono
parents:
diff changeset
1904 exception = &storage_error;
kono
parents:
diff changeset
1905 msg = "SIGSEGV";
kono
parents:
diff changeset
1906 break;
kono
parents:
diff changeset
1907 case SIGBUS:
kono
parents:
diff changeset
1908 exception = &program_error;
kono
parents:
diff changeset
1909 msg = "SIGBUS";
kono
parents:
diff changeset
1910 break;
kono
parents:
diff changeset
1911 #endif
kono
parents:
diff changeset
1912 default:
kono
parents:
diff changeset
1913 exception = &program_error;
kono
parents:
diff changeset
1914 msg = "unhandled signal";
kono
parents:
diff changeset
1915 }
kono
parents:
diff changeset
1916
kono
parents:
diff changeset
1917 if (__gnat_reset_guard_page (sig))
kono
parents:
diff changeset
1918 {
kono
parents:
diff changeset
1919 /* Set the exception message: we know for sure that we have a
kono
parents:
diff changeset
1920 stack overflow here */
kono
parents:
diff changeset
1921 exception = &storage_error;
kono
parents:
diff changeset
1922
kono
parents:
diff changeset
1923 switch (sig)
kono
parents:
diff changeset
1924 {
kono
parents:
diff changeset
1925 case SIGSEGV:
kono
parents:
diff changeset
1926 msg = "SIGSEGV: stack overflow";
kono
parents:
diff changeset
1927 break;
kono
parents:
diff changeset
1928 case SIGBUS:
kono
parents:
diff changeset
1929 msg = "SIGBUS: stack overflow";
kono
parents:
diff changeset
1930 break;
kono
parents:
diff changeset
1931 case SIGILL:
kono
parents:
diff changeset
1932 msg = "SIGILL: stack overflow";
kono
parents:
diff changeset
1933 break;
kono
parents:
diff changeset
1934 }
kono
parents:
diff changeset
1935 }
kono
parents:
diff changeset
1936 __gnat_clear_exception_count ();
kono
parents:
diff changeset
1937 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
1938 }
kono
parents:
diff changeset
1939
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1940 #if defined (ARMEL) && (_WRS_VXWORKS_MAJOR >= 7) && !defined (__aarch64__)
111
kono
parents:
diff changeset
1941
kono
parents:
diff changeset
1942 /* ARM-vx7 case with arm unwinding exceptions */
kono
parents:
diff changeset
1943 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
1944
kono
parents:
diff changeset
1945 #include <arch/../regs.h>
kono
parents:
diff changeset
1946 #ifndef __RTP__
kono
parents:
diff changeset
1947 #include <sigLib.h>
kono
parents:
diff changeset
1948 #else
kono
parents:
diff changeset
1949 #include <signal.h>
kono
parents:
diff changeset
1950 #include <regs.h>
kono
parents:
diff changeset
1951 #include <ucontext.h>
kono
parents:
diff changeset
1952 #endif /* __RTP__ */
kono
parents:
diff changeset
1953
kono
parents:
diff changeset
1954 void
kono
parents:
diff changeset
1955 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
1956 void *sc ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
1957 {
kono
parents:
diff changeset
1958 /* In case of ARM exceptions, the registers context have the PC pointing
kono
parents:
diff changeset
1959 to the instruction that raised the signal. However the unwinder expects
kono
parents:
diff changeset
1960 the instruction to be in the range ]PC,PC+1]. */
kono
parents:
diff changeset
1961 uintptr_t *pc_addr;
kono
parents:
diff changeset
1962 #ifdef __RTP__
kono
parents:
diff changeset
1963 mcontext_t *mcontext = &((ucontext_t *) sc)->uc_mcontext;
kono
parents:
diff changeset
1964 pc_addr = (uintptr_t*)&mcontext->regs.pc;
kono
parents:
diff changeset
1965 #else
kono
parents:
diff changeset
1966 struct sigcontext * sctx = (struct sigcontext *) sc;
kono
parents:
diff changeset
1967 pc_addr = (uintptr_t*)&sctx->sc_pregs->pc;
kono
parents:
diff changeset
1968 #endif
kono
parents:
diff changeset
1969 /* ARM Bump has to be an even number because of odd/even architecture. */
kono
parents:
diff changeset
1970 *pc_addr += 2;
kono
parents:
diff changeset
1971 }
kono
parents:
diff changeset
1972 #endif /* ARMEL && _WRS_VXWORKS_MAJOR >= 7 */
kono
parents:
diff changeset
1973
kono
parents:
diff changeset
1974 /* Tasking and Non-tasking signal handler. Map SIGnal to Ada exception
kono
parents:
diff changeset
1975 propagation after the required low level adjustments. */
kono
parents:
diff changeset
1976
kono
parents:
diff changeset
1977 static void
kono
parents:
diff changeset
1978 __gnat_error_handler (int sig, siginfo_t *si, void *sc)
kono
parents:
diff changeset
1979 {
kono
parents:
diff changeset
1980 sigset_t mask;
kono
parents:
diff changeset
1981
kono
parents:
diff changeset
1982 /* VxWorks on e500v2 clears the SPE bit of the MSR when entering CPU
kono
parents:
diff changeset
1983 exception state. To allow the handler and exception to work properly
kono
parents:
diff changeset
1984 when they contain SPE instructions, we need to set it back before doing
kono
parents:
diff changeset
1985 anything else.
kono
parents:
diff changeset
1986 This mechanism is only need in kernel mode. */
kono
parents:
diff changeset
1987 #if !(defined (__RTP__) || defined (VTHREADS)) && ((CPU == PPCE500V2) || (CPU == PPC85XX))
kono
parents:
diff changeset
1988 register unsigned msr;
kono
parents:
diff changeset
1989 /* Read the MSR value */
kono
parents:
diff changeset
1990 asm volatile ("mfmsr %0" : "=r" (msr));
kono
parents:
diff changeset
1991 /* Force the SPE bit if not set. */
kono
parents:
diff changeset
1992 if ((msr & 0x02000000) == 0)
kono
parents:
diff changeset
1993 {
kono
parents:
diff changeset
1994 msr |= 0x02000000;
kono
parents:
diff changeset
1995 /* Store to MSR */
kono
parents:
diff changeset
1996 asm volatile ("mtmsr %0" : : "r" (msr));
kono
parents:
diff changeset
1997 }
kono
parents:
diff changeset
1998 #endif
kono
parents:
diff changeset
1999
kono
parents:
diff changeset
2000 /* VxWorks will always mask out the signal during the signal handler and
kono
parents:
diff changeset
2001 will reenable it on a longjmp. GNAT does not generate a longjmp to
kono
parents:
diff changeset
2002 return from a signal handler so the signal will still be masked unless
kono
parents:
diff changeset
2003 we unmask it. */
kono
parents:
diff changeset
2004 sigprocmask (SIG_SETMASK, NULL, &mask);
kono
parents:
diff changeset
2005 sigdelset (&mask, sig);
kono
parents:
diff changeset
2006 sigprocmask (SIG_SETMASK, &mask, NULL);
kono
parents:
diff changeset
2007
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2008 #if defined (__ARMEL__) || defined (__PPC__) || defined (__i386__) || defined (__x86_64__) || defined (__aarch64__)
111
kono
parents:
diff changeset
2009 /* On certain targets, kernel mode, we process signals through a Call Frame
kono
parents:
diff changeset
2010 Info trampoline, voiding the need for myriads of fallback_frame_state
kono
parents:
diff changeset
2011 variants in the ZCX runtime. We have no simple way to distinguish ZCX
kono
parents:
diff changeset
2012 from SJLJ here, so we do this for SJLJ as well even though this is not
kono
parents:
diff changeset
2013 necessary. This only incurs a few extra instructions and a tiny
kono
parents:
diff changeset
2014 amount of extra stack usage. */
kono
parents:
diff changeset
2015
kono
parents:
diff changeset
2016 #ifdef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
2017 /* We need to sometimes to adjust the PC in case of signals so that it
kono
parents:
diff changeset
2018 doesn't reference the exception that actually raised the signal but the
kono
parents:
diff changeset
2019 instruction before it. */
kono
parents:
diff changeset
2020 __gnat_adjust_context_for_raise (sig, sc);
kono
parents:
diff changeset
2021 #endif
kono
parents:
diff changeset
2022
kono
parents:
diff changeset
2023 __gnat_sigtramp (sig, (void *)si, (void *)sc,
kono
parents:
diff changeset
2024 (__sigtramphandler_t *)&__gnat_map_signal);
kono
parents:
diff changeset
2025
kono
parents:
diff changeset
2026 #else
kono
parents:
diff changeset
2027 __gnat_map_signal (sig, si, sc);
kono
parents:
diff changeset
2028 #endif
kono
parents:
diff changeset
2029 }
kono
parents:
diff changeset
2030
kono
parents:
diff changeset
2031 #if defined(__leon__) && defined(_WRS_KERNEL)
kono
parents:
diff changeset
2032 /* For LEON VxWorks we need to install a trap handler for stack overflow */
kono
parents:
diff changeset
2033
kono
parents:
diff changeset
2034 extern void excEnt (void);
kono
parents:
diff changeset
2035 /* VxWorks exception handler entry */
kono
parents:
diff changeset
2036
kono
parents:
diff changeset
2037 struct trap_entry {
kono
parents:
diff changeset
2038 unsigned long inst_first;
kono
parents:
diff changeset
2039 unsigned long inst_second;
kono
parents:
diff changeset
2040 unsigned long inst_third;
kono
parents:
diff changeset
2041 unsigned long inst_fourth;
kono
parents:
diff changeset
2042 };
kono
parents:
diff changeset
2043 /* Four instructions representing entries in the trap table */
kono
parents:
diff changeset
2044
kono
parents:
diff changeset
2045 struct trap_entry *trap_0_entry;
kono
parents:
diff changeset
2046 /* We will set the location of the entry for software trap 0 in the trap
kono
parents:
diff changeset
2047 table. */
kono
parents:
diff changeset
2048 #endif
kono
parents:
diff changeset
2049
kono
parents:
diff changeset
2050 void
kono
parents:
diff changeset
2051 __gnat_install_handler (void)
kono
parents:
diff changeset
2052 {
kono
parents:
diff changeset
2053 struct sigaction act;
kono
parents:
diff changeset
2054
kono
parents:
diff changeset
2055 /* Setup signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
2056 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
2057 signal that might cause a scheduling event! */
kono
parents:
diff changeset
2058
kono
parents:
diff changeset
2059 act.sa_sigaction = __gnat_error_handler;
kono
parents:
diff changeset
2060 act.sa_flags = SA_SIGINFO | SA_ONSTACK;
kono
parents:
diff changeset
2061 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
2062
kono
parents:
diff changeset
2063 /* For VxWorks, install all signal handlers, since pragma Interrupt_State
kono
parents:
diff changeset
2064 applies to vectored hardware interrupts, not signals. */
kono
parents:
diff changeset
2065 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
2066 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
2067 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
2068 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
2069
kono
parents:
diff changeset
2070 #if defined(__leon__) && defined(_WRS_KERNEL)
kono
parents:
diff changeset
2071 /* Specific to the LEON VxWorks kernel run-time library */
kono
parents:
diff changeset
2072
kono
parents:
diff changeset
2073 /* For stack checking the compiler triggers a software trap 0 (ta 0) in
kono
parents:
diff changeset
2074 case of overflow (we use the stack limit mechanism). We need to install
kono
parents:
diff changeset
2075 the trap handler here for this software trap (the OS does not handle
kono
parents:
diff changeset
2076 it) as if it were a data_access_exception (trap 9). We do the same as
kono
parents:
diff changeset
2077 if we put in the trap table a VXSPARC_BAD_TRAP(9). Software trap 0 is
kono
parents:
diff changeset
2078 located at vector 0x80, and each entry takes 4 words. */
kono
parents:
diff changeset
2079
kono
parents:
diff changeset
2080 trap_0_entry = (struct trap_entry *)(intVecBaseGet () + 0x80 * 4);
kono
parents:
diff changeset
2081
kono
parents:
diff changeset
2082 /* mov 0x9, %l7 */
kono
parents:
diff changeset
2083
kono
parents:
diff changeset
2084 trap_0_entry->inst_first = 0xae102000 + 9;
kono
parents:
diff changeset
2085
kono
parents:
diff changeset
2086 /* sethi %hi(excEnt), %l6 */
kono
parents:
diff changeset
2087
kono
parents:
diff changeset
2088 /* The 22 most significant bits of excEnt are obtained shifting 10 times
kono
parents:
diff changeset
2089 to the right. */
kono
parents:
diff changeset
2090
kono
parents:
diff changeset
2091 trap_0_entry->inst_second = 0x2d000000 + ((unsigned long)excEnt >> 10);
kono
parents:
diff changeset
2092
kono
parents:
diff changeset
2093 /* jmp %l6+%lo(excEnt) */
kono
parents:
diff changeset
2094
kono
parents:
diff changeset
2095 /* The 10 least significant bits of excEnt are obtained by masking */
kono
parents:
diff changeset
2096
kono
parents:
diff changeset
2097 trap_0_entry->inst_third = 0x81c5a000 + ((unsigned long)excEnt & 0x3ff);
kono
parents:
diff changeset
2098
kono
parents:
diff changeset
2099 /* rd %psr, %l0 */
kono
parents:
diff changeset
2100
kono
parents:
diff changeset
2101 trap_0_entry->inst_fourth = 0xa1480000;
kono
parents:
diff changeset
2102 #endif
kono
parents:
diff changeset
2103
kono
parents:
diff changeset
2104 #ifdef __HANDLE_VXSIM_SC
kono
parents:
diff changeset
2105 /* By experiment, found that sysModel () returns the following string
kono
parents:
diff changeset
2106 prefix for vxsim when running on Linux and Windows. */
kono
parents:
diff changeset
2107 {
kono
parents:
diff changeset
2108 char *model = sysModel ();
kono
parents:
diff changeset
2109 if ((strncmp (model, "Linux", 5) == 0)
kono
parents:
diff changeset
2110 || (strncmp (model, "Windows", 7) == 0)
kono
parents:
diff changeset
2111 || (strncmp (model, "SIMLINUX", 8) == 0) /* vx7 */
kono
parents:
diff changeset
2112 || (strncmp (model, "SIMNT", 5) == 0)) /* ditto */
kono
parents:
diff changeset
2113 __gnat_set_is_vxsim (TRUE);
kono
parents:
diff changeset
2114 }
kono
parents:
diff changeset
2115 #endif
kono
parents:
diff changeset
2116
kono
parents:
diff changeset
2117 __gnat_handler_installed = 1;
kono
parents:
diff changeset
2118 }
kono
parents:
diff changeset
2119
kono
parents:
diff changeset
2120 #define HAVE_GNAT_INIT_FLOAT
kono
parents:
diff changeset
2121
kono
parents:
diff changeset
2122 void
kono
parents:
diff changeset
2123 __gnat_init_float (void)
kono
parents:
diff changeset
2124 {
kono
parents:
diff changeset
2125 /* Disable overflow/underflow exceptions on the PPC processor, needed
kono
parents:
diff changeset
2126 to get correct Ada semantics. Note that for AE653 vThreads, the HW
kono
parents:
diff changeset
2127 overflow settings are an OS configuration issue. The instructions
kono
parents:
diff changeset
2128 below have no effect. */
kono
parents:
diff changeset
2129 #if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && (!defined (VTHREADS) || defined (__VXWORKSMILS__))
kono
parents:
diff changeset
2130 #if defined (__SPE__)
kono
parents:
diff changeset
2131 {
kono
parents:
diff changeset
2132 /* For e500v2, do nothing and leave the responsibility to install the
kono
parents:
diff changeset
2133 handler and enable the exceptions to the BSP. */
kono
parents:
diff changeset
2134 }
kono
parents:
diff changeset
2135 #else
kono
parents:
diff changeset
2136 asm ("mtfsb0 25");
kono
parents:
diff changeset
2137 asm ("mtfsb0 26");
kono
parents:
diff changeset
2138 #endif
kono
parents:
diff changeset
2139 #endif
kono
parents:
diff changeset
2140
kono
parents:
diff changeset
2141 #if (defined (__i386__) || defined (__x86_64__)) && !defined (VTHREADS)
kono
parents:
diff changeset
2142 /* This is used to properly initialize the FPU on an x86 for each
kono
parents:
diff changeset
2143 process thread. */
kono
parents:
diff changeset
2144 asm ("finit");
kono
parents:
diff changeset
2145 #endif
kono
parents:
diff changeset
2146
kono
parents:
diff changeset
2147 /* Similarly for SPARC64. Achieved by masking bits in the Trap Enable Mask
kono
parents:
diff changeset
2148 field of the Floating-point Status Register (see the SPARC Architecture
kono
parents:
diff changeset
2149 Manual Version 9, p 48). */
kono
parents:
diff changeset
2150 #if defined (sparc64)
kono
parents:
diff changeset
2151
kono
parents:
diff changeset
2152 #define FSR_TEM_NVM (1 << 27) /* Invalid operand */
kono
parents:
diff changeset
2153 #define FSR_TEM_OFM (1 << 26) /* Overflow */
kono
parents:
diff changeset
2154 #define FSR_TEM_UFM (1 << 25) /* Underflow */
kono
parents:
diff changeset
2155 #define FSR_TEM_DZM (1 << 24) /* Division by Zero */
kono
parents:
diff changeset
2156 #define FSR_TEM_NXM (1 << 23) /* Inexact result */
kono
parents:
diff changeset
2157 {
kono
parents:
diff changeset
2158 unsigned int fsr;
kono
parents:
diff changeset
2159
kono
parents:
diff changeset
2160 __asm__("st %%fsr, %0" : "=m" (fsr));
kono
parents:
diff changeset
2161 fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
kono
parents:
diff changeset
2162 __asm__("ld %0, %%fsr" : : "m" (fsr));
kono
parents:
diff changeset
2163 }
kono
parents:
diff changeset
2164 #endif
kono
parents:
diff changeset
2165 }
kono
parents:
diff changeset
2166
kono
parents:
diff changeset
2167 /* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
kono
parents:
diff changeset
2168 (if not null) when a new task is created. It is initialized by
kono
parents:
diff changeset
2169 System.Stack_Checking.Operations.Initialize_Stack_Limit.
kono
parents:
diff changeset
2170 The use of a hook avoids to drag stack checking subprograms if stack
kono
parents:
diff changeset
2171 checking is not used. */
kono
parents:
diff changeset
2172 void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
kono
parents:
diff changeset
2173
kono
parents:
diff changeset
2174 /******************/
kono
parents:
diff changeset
2175 /* NetBSD Section */
kono
parents:
diff changeset
2176 /******************/
kono
parents:
diff changeset
2177
kono
parents:
diff changeset
2178 #elif defined(__NetBSD__)
kono
parents:
diff changeset
2179
kono
parents:
diff changeset
2180 #include <signal.h>
kono
parents:
diff changeset
2181 #include <unistd.h>
kono
parents:
diff changeset
2182
kono
parents:
diff changeset
2183 static void
kono
parents:
diff changeset
2184 __gnat_error_handler (int sig)
kono
parents:
diff changeset
2185 {
kono
parents:
diff changeset
2186 struct Exception_Data *exception;
kono
parents:
diff changeset
2187 const char *msg;
kono
parents:
diff changeset
2188
kono
parents:
diff changeset
2189 switch(sig)
kono
parents:
diff changeset
2190 {
kono
parents:
diff changeset
2191 case SIGFPE:
kono
parents:
diff changeset
2192 exception = &constraint_error;
kono
parents:
diff changeset
2193 msg = "SIGFPE";
kono
parents:
diff changeset
2194 break;
kono
parents:
diff changeset
2195 case SIGILL:
kono
parents:
diff changeset
2196 exception = &constraint_error;
kono
parents:
diff changeset
2197 msg = "SIGILL";
kono
parents:
diff changeset
2198 break;
kono
parents:
diff changeset
2199 case SIGSEGV:
kono
parents:
diff changeset
2200 exception = &storage_error;
kono
parents:
diff changeset
2201 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
2202 break;
kono
parents:
diff changeset
2203 case SIGBUS:
kono
parents:
diff changeset
2204 exception = &constraint_error;
kono
parents:
diff changeset
2205 msg = "SIGBUS";
kono
parents:
diff changeset
2206 break;
kono
parents:
diff changeset
2207 default:
kono
parents:
diff changeset
2208 exception = &program_error;
kono
parents:
diff changeset
2209 msg = "unhandled signal";
kono
parents:
diff changeset
2210 }
kono
parents:
diff changeset
2211
kono
parents:
diff changeset
2212 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
2213 }
kono
parents:
diff changeset
2214
kono
parents:
diff changeset
2215 void
kono
parents:
diff changeset
2216 __gnat_install_handler (void)
kono
parents:
diff changeset
2217 {
kono
parents:
diff changeset
2218 struct sigaction act;
kono
parents:
diff changeset
2219
kono
parents:
diff changeset
2220 act.sa_handler = __gnat_error_handler;
kono
parents:
diff changeset
2221 act.sa_flags = SA_NODEFER | SA_RESTART;
kono
parents:
diff changeset
2222 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
2223
kono
parents:
diff changeset
2224 /* Do not install handlers if interrupt state is "System". */
kono
parents:
diff changeset
2225 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
2226 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
2227 if (__gnat_get_interrupt_state (SIGILL) != 's')
kono
parents:
diff changeset
2228 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
2229 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
2230 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
2231 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
2232 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
2233
kono
parents:
diff changeset
2234 __gnat_handler_installed = 1;
kono
parents:
diff changeset
2235 }
kono
parents:
diff changeset
2236
kono
parents:
diff changeset
2237 /*******************/
kono
parents:
diff changeset
2238 /* OpenBSD Section */
kono
parents:
diff changeset
2239 /*******************/
kono
parents:
diff changeset
2240
kono
parents:
diff changeset
2241 #elif defined(__OpenBSD__)
kono
parents:
diff changeset
2242
kono
parents:
diff changeset
2243 #include <signal.h>
kono
parents:
diff changeset
2244 #include <unistd.h>
kono
parents:
diff changeset
2245
kono
parents:
diff changeset
2246 static void
kono
parents:
diff changeset
2247 __gnat_error_handler (int sig)
kono
parents:
diff changeset
2248 {
kono
parents:
diff changeset
2249 struct Exception_Data *exception;
kono
parents:
diff changeset
2250 const char *msg;
kono
parents:
diff changeset
2251
kono
parents:
diff changeset
2252 switch(sig)
kono
parents:
diff changeset
2253 {
kono
parents:
diff changeset
2254 case SIGFPE:
kono
parents:
diff changeset
2255 exception = &constraint_error;
kono
parents:
diff changeset
2256 msg = "SIGFPE";
kono
parents:
diff changeset
2257 break;
kono
parents:
diff changeset
2258 case SIGILL:
kono
parents:
diff changeset
2259 exception = &constraint_error;
kono
parents:
diff changeset
2260 msg = "SIGILL";
kono
parents:
diff changeset
2261 break;
kono
parents:
diff changeset
2262 case SIGSEGV:
kono
parents:
diff changeset
2263 exception = &storage_error;
kono
parents:
diff changeset
2264 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
2265 break;
kono
parents:
diff changeset
2266 case SIGBUS:
kono
parents:
diff changeset
2267 exception = &constraint_error;
kono
parents:
diff changeset
2268 msg = "SIGBUS";
kono
parents:
diff changeset
2269 break;
kono
parents:
diff changeset
2270 default:
kono
parents:
diff changeset
2271 exception = &program_error;
kono
parents:
diff changeset
2272 msg = "unhandled signal";
kono
parents:
diff changeset
2273 }
kono
parents:
diff changeset
2274
kono
parents:
diff changeset
2275 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
2276 }
kono
parents:
diff changeset
2277
kono
parents:
diff changeset
2278 void
kono
parents:
diff changeset
2279 __gnat_install_handler (void)
kono
parents:
diff changeset
2280 {
kono
parents:
diff changeset
2281 struct sigaction act;
kono
parents:
diff changeset
2282
kono
parents:
diff changeset
2283 act.sa_handler = __gnat_error_handler;
kono
parents:
diff changeset
2284 act.sa_flags = SA_NODEFER | SA_RESTART;
kono
parents:
diff changeset
2285 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
2286
kono
parents:
diff changeset
2287 /* Do not install handlers if interrupt state is "System" */
kono
parents:
diff changeset
2288 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
2289 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
2290 if (__gnat_get_interrupt_state (SIGILL) != 's')
kono
parents:
diff changeset
2291 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
2292 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
2293 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
2294 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
2295 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
2296
kono
parents:
diff changeset
2297 __gnat_handler_installed = 1;
kono
parents:
diff changeset
2298 }
kono
parents:
diff changeset
2299
kono
parents:
diff changeset
2300 /******************/
kono
parents:
diff changeset
2301 /* Darwin Section */
kono
parents:
diff changeset
2302 /******************/
kono
parents:
diff changeset
2303
kono
parents:
diff changeset
2304 #elif defined(__APPLE__)
kono
parents:
diff changeset
2305
kono
parents:
diff changeset
2306 #include <TargetConditionals.h>
kono
parents:
diff changeset
2307 #include <signal.h>
kono
parents:
diff changeset
2308 #include <stdlib.h>
kono
parents:
diff changeset
2309 #include <sys/syscall.h>
kono
parents:
diff changeset
2310 #include <sys/sysctl.h>
kono
parents:
diff changeset
2311
kono
parents:
diff changeset
2312 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
kono
parents:
diff changeset
2313 char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
kono
parents:
diff changeset
2314
kono
parents:
diff changeset
2315 /* Defined in xnu unix_signal.c.
kono
parents:
diff changeset
2316 Tell the kernel to re-use alt stack when delivering a signal. */
kono
parents:
diff changeset
2317 #define UC_RESET_ALT_STACK 0x80000000
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
kono
parents:
diff changeset
2320 #include <mach/mach_vm.h>
kono
parents:
diff changeset
2321 #include <mach/mach_init.h>
kono
parents:
diff changeset
2322 #include <mach/vm_statistics.h>
kono
parents:
diff changeset
2323 #endif
kono
parents:
diff changeset
2324
kono
parents:
diff changeset
2325 #ifdef __arm64__
kono
parents:
diff changeset
2326 #include <sys/ucontext.h>
kono
parents:
diff changeset
2327 #include "sigtramp.h"
kono
parents:
diff changeset
2328 #endif
kono
parents:
diff changeset
2329
kono
parents:
diff changeset
2330 /* Return true if ADDR is within a stack guard area. */
kono
parents:
diff changeset
2331 static int
kono
parents:
diff changeset
2332 __gnat_is_stack_guard (mach_vm_address_t addr)
kono
parents:
diff changeset
2333 {
kono
parents:
diff changeset
2334 #if !(defined (__arm__) || defined (__arm64__) || TARGET_IPHONE_SIMULATOR)
kono
parents:
diff changeset
2335 kern_return_t kret;
kono
parents:
diff changeset
2336 vm_region_submap_info_data_64_t info;
kono
parents:
diff changeset
2337 mach_vm_address_t start;
kono
parents:
diff changeset
2338 mach_vm_size_t size;
kono
parents:
diff changeset
2339 natural_t depth;
kono
parents:
diff changeset
2340 mach_msg_type_number_t count;
kono
parents:
diff changeset
2341
kono
parents:
diff changeset
2342 count = VM_REGION_SUBMAP_INFO_COUNT_64;
kono
parents:
diff changeset
2343 start = addr;
kono
parents:
diff changeset
2344 size = -1;
kono
parents:
diff changeset
2345 depth = 9999;
kono
parents:
diff changeset
2346 kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
kono
parents:
diff changeset
2347 (vm_region_recurse_info_t) &info, &count);
kono
parents:
diff changeset
2348 if (kret == KERN_SUCCESS
kono
parents:
diff changeset
2349 && addr >= start && addr < (start + size)
kono
parents:
diff changeset
2350 && info.protection == VM_PROT_NONE
kono
parents:
diff changeset
2351 && info.user_tag == VM_MEMORY_STACK)
kono
parents:
diff changeset
2352 return 1;
kono
parents:
diff changeset
2353 return 0;
kono
parents:
diff changeset
2354 #else
kono
parents:
diff changeset
2355 /* Pagezero for arm. */
kono
parents:
diff changeset
2356 return addr >= 4096;
kono
parents:
diff changeset
2357 #endif
kono
parents:
diff changeset
2358 }
kono
parents:
diff changeset
2359
kono
parents:
diff changeset
2360 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
2361
kono
parents:
diff changeset
2362 #if defined (__x86_64__)
kono
parents:
diff changeset
2363 static int
kono
parents:
diff changeset
2364 __darwin_major_version (void)
kono
parents:
diff changeset
2365 {
kono
parents:
diff changeset
2366 static int cache = -1;
kono
parents:
diff changeset
2367 if (cache < 0)
kono
parents:
diff changeset
2368 {
kono
parents:
diff changeset
2369 int mib[2] = {CTL_KERN, KERN_OSRELEASE};
kono
parents:
diff changeset
2370 size_t len;
kono
parents:
diff changeset
2371
kono
parents:
diff changeset
2372 /* Find out how big the buffer needs to be (and set cache to 0
kono
parents:
diff changeset
2373 on failure). */
kono
parents:
diff changeset
2374 if (sysctl (mib, 2, NULL, &len, NULL, 0) == 0)
kono
parents:
diff changeset
2375 {
kono
parents:
diff changeset
2376 char release[len];
kono
parents:
diff changeset
2377 sysctl (mib, 2, release, &len, NULL, 0);
kono
parents:
diff changeset
2378 /* Darwin releases are of the form L.M.N where L is the major
kono
parents:
diff changeset
2379 version, so strtol will return L. */
kono
parents:
diff changeset
2380 cache = (int) strtol (release, NULL, 10);
kono
parents:
diff changeset
2381 }
kono
parents:
diff changeset
2382 else
kono
parents:
diff changeset
2383 {
kono
parents:
diff changeset
2384 cache = 0;
kono
parents:
diff changeset
2385 }
kono
parents:
diff changeset
2386 }
kono
parents:
diff changeset
2387 return cache;
kono
parents:
diff changeset
2388 }
kono
parents:
diff changeset
2389 #endif
kono
parents:
diff changeset
2390
kono
parents:
diff changeset
2391 void
kono
parents:
diff changeset
2392 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
2393 void *ucontext ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2394 {
kono
parents:
diff changeset
2395 #if defined (__x86_64__)
kono
parents:
diff changeset
2396 if (__darwin_major_version () < 12)
kono
parents:
diff changeset
2397 {
kono
parents:
diff changeset
2398 /* Work around radar #10302855, where the unwinders (libunwind or
kono
parents:
diff changeset
2399 libgcc_s depending on the system revision) and the DWARF unwind
kono
parents:
diff changeset
2400 data for sigtramp have different ideas about register numbering,
kono
parents:
diff changeset
2401 causing rbx and rdx to be transposed. */
kono
parents:
diff changeset
2402 ucontext_t *uc = (ucontext_t *)ucontext;
kono
parents:
diff changeset
2403 unsigned long t = uc->uc_mcontext->__ss.__rbx;
kono
parents:
diff changeset
2404
kono
parents:
diff changeset
2405 uc->uc_mcontext->__ss.__rbx = uc->uc_mcontext->__ss.__rdx;
kono
parents:
diff changeset
2406 uc->uc_mcontext->__ss.__rdx = t;
kono
parents:
diff changeset
2407 }
kono
parents:
diff changeset
2408 #elif defined(__arm64__)
kono
parents:
diff changeset
2409 /* Even though the CFI is marked as a signal frame, we need this. */
kono
parents:
diff changeset
2410 ucontext_t *uc = (ucontext_t *)ucontext;
kono
parents:
diff changeset
2411 uc->uc_mcontext->__ss.__pc++;
kono
parents:
diff changeset
2412 #endif
kono
parents:
diff changeset
2413 }
kono
parents:
diff changeset
2414
kono
parents:
diff changeset
2415 static void
kono
parents:
diff changeset
2416 __gnat_map_signal (int sig, siginfo_t *si, void *mcontext ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2417 {
kono
parents:
diff changeset
2418 struct Exception_Data *exception;
kono
parents:
diff changeset
2419 const char *msg;
kono
parents:
diff changeset
2420
kono
parents:
diff changeset
2421 switch (sig)
kono
parents:
diff changeset
2422 {
kono
parents:
diff changeset
2423 case SIGSEGV:
kono
parents:
diff changeset
2424 case SIGBUS:
kono
parents:
diff changeset
2425 if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
kono
parents:
diff changeset
2426 {
kono
parents:
diff changeset
2427 #ifdef __arm64__
kono
parents:
diff changeset
2428 /* ??? This is a kludge to make stack checking work. The problem is
kono
parents:
diff changeset
2429 that the trampoline doesn't restore LR and, consequently, doesn't
kono
parents:
diff changeset
2430 make it possible to unwind past an interrupted frame which hasn"t
kono
parents:
diff changeset
2431 saved LR on the stack yet. Therefore, for probes in the prologue
kono
parents:
diff changeset
2432 (32-bit probes as opposed to standard 64-bit probes), we make the
kono
parents:
diff changeset
2433 unwinder skip the not-yet-established frame altogether. */
kono
parents:
diff changeset
2434 mcontext_t mc = (mcontext_t)mcontext;
kono
parents:
diff changeset
2435 if (!(*(unsigned int *)(mc->__ss.__pc-1) & ((unsigned int)1 << 30)))
kono
parents:
diff changeset
2436 mc->__ss.__pc = mc->__ss.__lr;
kono
parents:
diff changeset
2437 #endif
kono
parents:
diff changeset
2438 exception = &storage_error;
kono
parents:
diff changeset
2439 msg = "stack overflow";
kono
parents:
diff changeset
2440 }
kono
parents:
diff changeset
2441 else
kono
parents:
diff changeset
2442 {
kono
parents:
diff changeset
2443 exception = &constraint_error;
kono
parents:
diff changeset
2444 msg = "erroneous memory access";
kono
parents:
diff changeset
2445 }
kono
parents:
diff changeset
2446
kono
parents:
diff changeset
2447 /* Reset the use of alt stack, so that the alt stack will be used
kono
parents:
diff changeset
2448 for the next signal delivery.
kono
parents:
diff changeset
2449 The stack can't be used in case of stack checking. */
kono
parents:
diff changeset
2450 syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
kono
parents:
diff changeset
2451 break;
kono
parents:
diff changeset
2452
kono
parents:
diff changeset
2453 case SIGFPE:
kono
parents:
diff changeset
2454 exception = &constraint_error;
kono
parents:
diff changeset
2455 msg = "SIGFPE";
kono
parents:
diff changeset
2456 break;
kono
parents:
diff changeset
2457
kono
parents:
diff changeset
2458 default:
kono
parents:
diff changeset
2459 exception = &program_error;
kono
parents:
diff changeset
2460 msg = "unhandled signal";
kono
parents:
diff changeset
2461 }
kono
parents:
diff changeset
2462
kono
parents:
diff changeset
2463 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
2464 }
kono
parents:
diff changeset
2465
kono
parents:
diff changeset
2466 static void
kono
parents:
diff changeset
2467 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
kono
parents:
diff changeset
2468 {
kono
parents:
diff changeset
2469 __gnat_adjust_context_for_raise (sig, ucontext);
kono
parents:
diff changeset
2470
kono
parents:
diff changeset
2471 /* The Darwin libc comes with a signal trampoline, except for ARM64. */
kono
parents:
diff changeset
2472 #ifdef __arm64__
kono
parents:
diff changeset
2473 __gnat_sigtramp (sig, (void *)si, ucontext,
kono
parents:
diff changeset
2474 (__sigtramphandler_t *)&__gnat_map_signal);
kono
parents:
diff changeset
2475 #else
kono
parents:
diff changeset
2476 __gnat_map_signal (sig, si, ucontext);
kono
parents:
diff changeset
2477 #endif
kono
parents:
diff changeset
2478 }
kono
parents:
diff changeset
2479
kono
parents:
diff changeset
2480 void
kono
parents:
diff changeset
2481 __gnat_install_handler (void)
kono
parents:
diff changeset
2482 {
kono
parents:
diff changeset
2483 struct sigaction act;
kono
parents:
diff changeset
2484
kono
parents:
diff changeset
2485 /* Set up signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
2486 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
2487 signal that might cause a scheduling event! Also setup an alternate
kono
parents:
diff changeset
2488 stack region for the handler execution so that stack overflows can be
kono
parents:
diff changeset
2489 handled properly, avoiding a SEGV generation from stack usage by the
kono
parents:
diff changeset
2490 handler itself (and it is required by Darwin). */
kono
parents:
diff changeset
2491
kono
parents:
diff changeset
2492 stack_t stack;
kono
parents:
diff changeset
2493 stack.ss_sp = __gnat_alternate_stack;
kono
parents:
diff changeset
2494 stack.ss_size = sizeof (__gnat_alternate_stack);
kono
parents:
diff changeset
2495 stack.ss_flags = 0;
kono
parents:
diff changeset
2496 sigaltstack (&stack, NULL);
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
kono
parents:
diff changeset
2499 act.sa_sigaction = __gnat_error_handler;
kono
parents:
diff changeset
2500 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
2501
kono
parents:
diff changeset
2502 /* Do not install handlers if interrupt state is "System". */
kono
parents:
diff changeset
2503 if (__gnat_get_interrupt_state (SIGABRT) != 's')
kono
parents:
diff changeset
2504 sigaction (SIGABRT, &act, NULL);
kono
parents:
diff changeset
2505 if (__gnat_get_interrupt_state (SIGFPE) != 's')
kono
parents:
diff changeset
2506 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
2507 if (__gnat_get_interrupt_state (SIGILL) != 's')
kono
parents:
diff changeset
2508 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
2509
kono
parents:
diff changeset
2510 act.sa_flags |= SA_ONSTACK;
kono
parents:
diff changeset
2511 if (__gnat_get_interrupt_state (SIGSEGV) != 's')
kono
parents:
diff changeset
2512 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
2513 if (__gnat_get_interrupt_state (SIGBUS) != 's')
kono
parents:
diff changeset
2514 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
2515
kono
parents:
diff changeset
2516 __gnat_handler_installed = 1;
kono
parents:
diff changeset
2517 }
kono
parents:
diff changeset
2518
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2519 #elif defined(__QNX__)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2520
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2521 /***************/
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2522 /* QNX Section */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2523 /***************/
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2524
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2525 #include <signal.h>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2526 #include <unistd.h>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2527 #include <string.h>
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2528 #include "sigtramp.h"
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2529
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2530 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2531 __gnat_map_signal (int sig,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2532 siginfo_t *si ATTRIBUTE_UNUSED,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2533 void *mcontext ATTRIBUTE_UNUSED)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2534 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2535 struct Exception_Data *exception;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2536 const char *msg;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2537
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2538 switch(sig)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2539 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2540 case SIGFPE:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2541 exception = &constraint_error;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2542 msg = "SIGFPE";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2543 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2544 case SIGILL:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2545 exception = &constraint_error;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2546 msg = "SIGILL";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2547 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2548 case SIGSEGV:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2549 exception = &storage_error;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2550 msg = "stack overflow or erroneous memory access";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2551 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2552 case SIGBUS:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2553 exception = &constraint_error;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2554 msg = "SIGBUS";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2555 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2556 default:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2557 exception = &program_error;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2558 msg = "unhandled signal";
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2559 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2560
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2561 Raise_From_Signal_Handler (exception, msg);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2562 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2563
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2564 static void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2565 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2566 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2567 __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2568 (__sigtramphandler_t *)&__gnat_map_signal);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2569 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2570
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2571 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2572 /* sigaltstack is currently not supported by QNX7 */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2573 char __gnat_alternate_stack[0];
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2574
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2575 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2576 __gnat_install_handler (void)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2577 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2578 struct sigaction act;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2579 int err;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2580
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2581 act.sa_handler = __gnat_error_handler;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2582 act.sa_flags = SA_NODEFER | SA_SIGINFO;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2583 sigemptyset (&act.sa_mask);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2584
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2585 /* Do not install handlers if interrupt state is "System" */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2586 if (__gnat_get_interrupt_state (SIGFPE) != 's') {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2587 err = sigaction (SIGFPE, &act, NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2588 if (err == -1) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2589 err = errno;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2590 perror ("error while attaching SIGFPE");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2591 perror (strerror (err));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2592 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2593 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2594 if (__gnat_get_interrupt_state (SIGILL) != 's') {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2595 sigaction (SIGILL, &act, NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2596 if (err == -1) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2597 err = errno;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2598 perror ("error while attaching SIGFPE");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2599 perror (strerror (err));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2600 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2601 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2602 if (__gnat_get_interrupt_state (SIGSEGV) != 's') {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2603 sigaction (SIGSEGV, &act, NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2604 if (err == -1) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2605 err = errno;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2606 perror ("error while attaching SIGFPE");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2607 perror (strerror (err));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2608 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2609 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2610 if (__gnat_get_interrupt_state (SIGBUS) != 's') {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2611 sigaction (SIGBUS, &act, NULL);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2612 if (err == -1) {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2613 err = errno;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2614 perror ("error while attaching SIGFPE");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2615 perror (strerror (err));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2616 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2617 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2618 __gnat_handler_installed = 1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2619 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2620
111
kono
parents:
diff changeset
2621 #elif defined (__DJGPP__)
kono
parents:
diff changeset
2622
kono
parents:
diff changeset
2623 void
kono
parents:
diff changeset
2624 __gnat_install_handler ()
kono
parents:
diff changeset
2625 {
kono
parents:
diff changeset
2626 __gnat_handler_installed = 1;
kono
parents:
diff changeset
2627 }
kono
parents:
diff changeset
2628
kono
parents:
diff changeset
2629 #elif defined(__ANDROID__)
kono
parents:
diff changeset
2630
kono
parents:
diff changeset
2631 /*******************/
kono
parents:
diff changeset
2632 /* Android Section */
kono
parents:
diff changeset
2633 /*******************/
kono
parents:
diff changeset
2634
kono
parents:
diff changeset
2635 #include <signal.h>
kono
parents:
diff changeset
2636 #include <sys/ucontext.h>
kono
parents:
diff changeset
2637 #include "sigtramp.h"
kono
parents:
diff changeset
2638
kono
parents:
diff changeset
2639 #define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
2640
kono
parents:
diff changeset
2641 void
kono
parents:
diff changeset
2642 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
kono
parents:
diff changeset
2643 {
kono
parents:
diff changeset
2644 mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
kono
parents:
diff changeset
2645
kono
parents:
diff changeset
2646 /* ARM Bump has to be an even number because of odd/even architecture. */
kono
parents:
diff changeset
2647 ((mcontext_t *) mcontext)->arm_pc += 2;
kono
parents:
diff changeset
2648 }
kono
parents:
diff changeset
2649
kono
parents:
diff changeset
2650 static void
kono
parents:
diff changeset
2651 __gnat_map_signal (int sig,
kono
parents:
diff changeset
2652 siginfo_t *si ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
2653 void *mcontext ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2654 {
kono
parents:
diff changeset
2655 struct Exception_Data *exception;
kono
parents:
diff changeset
2656 const char *msg;
kono
parents:
diff changeset
2657
kono
parents:
diff changeset
2658 switch (sig)
kono
parents:
diff changeset
2659 {
kono
parents:
diff changeset
2660 case SIGSEGV:
kono
parents:
diff changeset
2661 exception = &storage_error;
kono
parents:
diff changeset
2662 msg = "stack overflow or erroneous memory access";
kono
parents:
diff changeset
2663 break;
kono
parents:
diff changeset
2664
kono
parents:
diff changeset
2665 case SIGBUS:
kono
parents:
diff changeset
2666 exception = &constraint_error;
kono
parents:
diff changeset
2667 msg = "SIGBUS";
kono
parents:
diff changeset
2668 break;
kono
parents:
diff changeset
2669
kono
parents:
diff changeset
2670 case SIGFPE:
kono
parents:
diff changeset
2671 exception = &constraint_error;
kono
parents:
diff changeset
2672 msg = "SIGFPE";
kono
parents:
diff changeset
2673 break;
kono
parents:
diff changeset
2674
kono
parents:
diff changeset
2675 default:
kono
parents:
diff changeset
2676 exception = &program_error;
kono
parents:
diff changeset
2677 msg = "unhandled signal";
kono
parents:
diff changeset
2678 }
kono
parents:
diff changeset
2679
kono
parents:
diff changeset
2680 Raise_From_Signal_Handler (exception, msg);
kono
parents:
diff changeset
2681 }
kono
parents:
diff changeset
2682
kono
parents:
diff changeset
2683 static void
kono
parents:
diff changeset
2684 __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
kono
parents:
diff changeset
2685 {
kono
parents:
diff changeset
2686 __gnat_adjust_context_for_raise (sig, ucontext);
kono
parents:
diff changeset
2687
kono
parents:
diff changeset
2688 __gnat_sigtramp (sig, (void *) si, (void *) ucontext,
kono
parents:
diff changeset
2689 (__sigtramphandler_t *)&__gnat_map_signal);
kono
parents:
diff changeset
2690 }
kono
parents:
diff changeset
2691
kono
parents:
diff changeset
2692 /* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
kono
parents:
diff changeset
2693 char __gnat_alternate_stack[16 * 1024];
kono
parents:
diff changeset
2694
kono
parents:
diff changeset
2695 void
kono
parents:
diff changeset
2696 __gnat_install_handler (void)
kono
parents:
diff changeset
2697 {
kono
parents:
diff changeset
2698 struct sigaction act;
kono
parents:
diff changeset
2699
kono
parents:
diff changeset
2700 /* Set up signal handler to map synchronous signals to appropriate
kono
parents:
diff changeset
2701 exceptions. Make sure that the handler isn't interrupted by another
kono
parents:
diff changeset
2702 signal that might cause a scheduling event! Also setup an alternate
kono
parents:
diff changeset
2703 stack region for the handler execution so that stack overflows can be
kono
parents:
diff changeset
2704 handled properly, avoiding a SEGV generation from stack usage by the
kono
parents:
diff changeset
2705 handler itself. */
kono
parents:
diff changeset
2706
kono
parents:
diff changeset
2707 stack_t stack;
kono
parents:
diff changeset
2708 stack.ss_sp = __gnat_alternate_stack;
kono
parents:
diff changeset
2709 stack.ss_size = sizeof (__gnat_alternate_stack);
kono
parents:
diff changeset
2710 stack.ss_flags = 0;
kono
parents:
diff changeset
2711 sigaltstack (&stack, NULL);
kono
parents:
diff changeset
2712
kono
parents:
diff changeset
2713 act.sa_sigaction = __gnat_error_handler;
kono
parents:
diff changeset
2714 act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
kono
parents:
diff changeset
2715 sigemptyset (&act.sa_mask);
kono
parents:
diff changeset
2716
kono
parents:
diff changeset
2717 sigaction (SIGABRT, &act, NULL);
kono
parents:
diff changeset
2718 sigaction (SIGFPE, &act, NULL);
kono
parents:
diff changeset
2719 sigaction (SIGILL, &act, NULL);
kono
parents:
diff changeset
2720 sigaction (SIGBUS, &act, NULL);
kono
parents:
diff changeset
2721 act.sa_flags |= SA_ONSTACK;
kono
parents:
diff changeset
2722 sigaction (SIGSEGV, &act, NULL);
kono
parents:
diff changeset
2723
kono
parents:
diff changeset
2724 __gnat_handler_installed = 1;
kono
parents:
diff changeset
2725 }
kono
parents:
diff changeset
2726
kono
parents:
diff changeset
2727 #else
kono
parents:
diff changeset
2728
kono
parents:
diff changeset
2729 /* For all other versions of GNAT, the handler does nothing. */
kono
parents:
diff changeset
2730
kono
parents:
diff changeset
2731 /*******************/
kono
parents:
diff changeset
2732 /* Default Section */
kono
parents:
diff changeset
2733 /*******************/
kono
parents:
diff changeset
2734
kono
parents:
diff changeset
2735 void
kono
parents:
diff changeset
2736 __gnat_install_handler (void)
kono
parents:
diff changeset
2737 {
kono
parents:
diff changeset
2738 __gnat_handler_installed = 1;
kono
parents:
diff changeset
2739 }
kono
parents:
diff changeset
2740
kono
parents:
diff changeset
2741 #endif
kono
parents:
diff changeset
2742
kono
parents:
diff changeset
2743 /*********************/
kono
parents:
diff changeset
2744 /* __gnat_init_float */
kono
parents:
diff changeset
2745 /*********************/
kono
parents:
diff changeset
2746
kono
parents:
diff changeset
2747 /* This routine is called as each process thread is created, for possible
kono
parents:
diff changeset
2748 initialization of the FP processor. This version is used under INTERIX
kono
parents:
diff changeset
2749 and WIN32. */
kono
parents:
diff changeset
2750
kono
parents:
diff changeset
2751 #if defined (_WIN32) || defined (__INTERIX) \
kono
parents:
diff changeset
2752 || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2753 || defined (__OpenBSD__) || defined (__DragonFly__) || defined(__QNX__)
111
kono
parents:
diff changeset
2754
kono
parents:
diff changeset
2755 #define HAVE_GNAT_INIT_FLOAT
kono
parents:
diff changeset
2756
kono
parents:
diff changeset
2757 void
kono
parents:
diff changeset
2758 __gnat_init_float (void)
kono
parents:
diff changeset
2759 {
kono
parents:
diff changeset
2760 #if defined (__i386__) || defined (__x86_64__)
kono
parents:
diff changeset
2761
kono
parents:
diff changeset
2762 /* This is used to properly initialize the FPU on an x86 for each
kono
parents:
diff changeset
2763 process thread. */
kono
parents:
diff changeset
2764
kono
parents:
diff changeset
2765 asm ("finit");
kono
parents:
diff changeset
2766
kono
parents:
diff changeset
2767 #endif /* Defined __i386__ */
kono
parents:
diff changeset
2768 }
kono
parents:
diff changeset
2769 #endif
kono
parents:
diff changeset
2770
kono
parents:
diff changeset
2771 #ifndef HAVE_GNAT_INIT_FLOAT
kono
parents:
diff changeset
2772
kono
parents:
diff changeset
2773 /* All targets without a specific __gnat_init_float will use an empty one. */
kono
parents:
diff changeset
2774 void
kono
parents:
diff changeset
2775 __gnat_init_float (void)
kono
parents:
diff changeset
2776 {
kono
parents:
diff changeset
2777 }
kono
parents:
diff changeset
2778 #endif
kono
parents:
diff changeset
2779
kono
parents:
diff changeset
2780 /***********************************/
kono
parents:
diff changeset
2781 /* __gnat_adjust_context_for_raise */
kono
parents:
diff changeset
2782 /***********************************/
kono
parents:
diff changeset
2783
kono
parents:
diff changeset
2784 #ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
kono
parents:
diff changeset
2785
kono
parents:
diff changeset
2786 /* All targets without a specific version will use an empty one. */
kono
parents:
diff changeset
2787
kono
parents:
diff changeset
2788 /* Given UCONTEXT a pointer to a context structure received by a signal
kono
parents:
diff changeset
2789 handler for SIGNO, perform the necessary adjustments to let the handler
kono
parents:
diff changeset
2790 raise an exception. Calls to this routine are not conditioned by the
kono
parents:
diff changeset
2791 propagation scheme in use. */
kono
parents:
diff changeset
2792
kono
parents:
diff changeset
2793 void
kono
parents:
diff changeset
2794 __gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
kono
parents:
diff changeset
2795 void *ucontext ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2796 {
kono
parents:
diff changeset
2797 /* We used to compensate here for the raised from call vs raised from signal
kono
parents:
diff changeset
2798 exception discrepancy with the GCC ZCX scheme, but this now can be dealt
kono
parents:
diff changeset
2799 with generically in the unwinder (see GCC PR other/26208). This however
kono
parents:
diff changeset
2800 requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
kono
parents:
diff changeset
2801 is predicated on the definition of HAVE_GETIPINFO at compile time. Only
kono
parents:
diff changeset
2802 the VMS ports still do the compensation described in the few lines below.
kono
parents:
diff changeset
2803
kono
parents:
diff changeset
2804 *** Call vs signal exception discrepancy with GCC ZCX scheme ***
kono
parents:
diff changeset
2805
kono
parents:
diff changeset
2806 The GCC unwinder expects to be dealing with call return addresses, since
kono
parents:
diff changeset
2807 this is the "nominal" case of what we retrieve while unwinding a regular
kono
parents:
diff changeset
2808 call chain.
kono
parents:
diff changeset
2809
kono
parents:
diff changeset
2810 To evaluate if a handler applies at some point identified by a return
kono
parents:
diff changeset
2811 address, the propagation engine needs to determine what region the
kono
parents:
diff changeset
2812 corresponding call instruction pertains to. Because the return address
kono
parents:
diff changeset
2813 may not be attached to the same region as the call, the unwinder always
kono
parents:
diff changeset
2814 subtracts "some" amount from a return address to search the region
kono
parents:
diff changeset
2815 tables, amount chosen to ensure that the resulting address is inside the
kono
parents:
diff changeset
2816 call instruction.
kono
parents:
diff changeset
2817
kono
parents:
diff changeset
2818 When we raise an exception from a signal handler, e.g. to transform a
kono
parents:
diff changeset
2819 SIGSEGV into Storage_Error, things need to appear as if the signal
kono
parents:
diff changeset
2820 handler had been "called" by the instruction which triggered the signal,
kono
parents:
diff changeset
2821 so that exception handlers that apply there are considered. What the
kono
parents:
diff changeset
2822 unwinder will retrieve as the return address from the signal handler is
kono
parents:
diff changeset
2823 what it will find as the faulting instruction address in the signal
kono
parents:
diff changeset
2824 context pushed by the kernel. Leaving this address untouched looses, if
kono
parents:
diff changeset
2825 the triggering instruction happens to be the very first of a region, as
kono
parents:
diff changeset
2826 the later adjustments performed by the unwinder would yield an address
kono
parents:
diff changeset
2827 outside that region. We need to compensate for the unwinder adjustments
kono
parents:
diff changeset
2828 at some point, and this is what this routine is expected to do.
kono
parents:
diff changeset
2829
kono
parents:
diff changeset
2830 signo is passed because on some targets for some signals the PC in
kono
parents:
diff changeset
2831 context points to the instruction after the faulting one, in which case
kono
parents:
diff changeset
2832 the unwinder adjustment is still desired. */
kono
parents:
diff changeset
2833 }
kono
parents:
diff changeset
2834
kono
parents:
diff changeset
2835 #endif
kono
parents:
diff changeset
2836
kono
parents:
diff changeset
2837 #ifdef __cplusplus
kono
parents:
diff changeset
2838 }
kono
parents:
diff changeset
2839 #endif