annotate gcc/ada/init.c @ 158:494b0b89df80 default tip

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