OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [ada/] [init.c] - Blame information for rev 16

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/****************************************************************************
2
 *                                                                          *
3
 *                         GNAT COMPILER COMPONENTS                         *
4
 *                                                                          *
5
 *                                 I N I T                                  *
6
 *                                                                          *
7
 *                          C Implementation File                           *
8
 *                                                                          *
9
 *          Copyright (C) 1992-2005, Free Software Foundation, Inc.         *
10
 *                                                                          *
11
 * GNAT is free software;  you can  redistribute it  and/or modify it under *
12
 * terms of the  GNU General Public License as published  by the Free Soft- *
13
 * ware  Foundation;  either version 2,  or (at your option) any later ver- *
14
 * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15
 * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License *
17
 * for  more details.  You should have  received  a copy of the GNU General *
18
 * Public License  distributed with GNAT;  see file COPYING.  If not, write *
19
 * to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, *
20
 * Boston, MA 02110-1301, USA.                                              *
21
 *                                                                          *
22
 * As a  special  exception,  if you  link  this file  with other  files to *
23
 * produce an executable,  this file does not by itself cause the resulting *
24
 * executable to be covered by the GNU General Public License. This except- *
25
 * ion does not  however invalidate  any other reasons  why the  executable *
26
 * file might be covered by the  GNU Public License.                        *
27
 *                                                                          *
28
 * GNAT was originally developed  by the GNAT team at  New York University. *
29
 * Extensive contributions were provided by Ada Core Technologies Inc.      *
30
 *                                                                          *
31
 ****************************************************************************/
32
 
33
/*  This unit contains initialization circuits that are system dependent. A
34
    major part of the functionality involved involves stack overflow checking.
35
    The GCC backend generates probe instructions to test for stack overflow.
36
    For details on the exact approach used to generate these probes, see the
37
    "Using and Porting GCC" manual, in particular the "Stack Checking" section
38
    and the subsection "Specifying How Stack Checking is Done". The handlers
39
    installed by this file are used to handle resulting signals that come
40
    from these probes failing (i.e. touching protected pages) */
41
 
42
/* This file should be kept synchronized with 2sinit.ads, 2sinit.adb,
43
   s-init-ae653-cert.adb and s-init-xi-sparc.adb. All these files implement
44
   the required functionality for different targets. */
45
 
46
/* The following include is here to meet the published VxWorks requirement
47
   that the __vxworks header appear before any other include. */
48
#ifdef __vxworks
49
#include "vxWorks.h"
50
#endif
51
 
52
#ifdef IN_RTS
53
#include "tconfig.h"
54
#include "tsystem.h"
55
#include <sys/stat.h>
56
 
57
/* We don't have libiberty, so us malloc.  */
58
#define xmalloc(S) malloc (S)
59
#else
60
#include "config.h"
61
#include "system.h"
62
#endif
63
 
64
#include "adaint.h"
65
#include "raise.h"
66
 
67
extern void __gnat_raise_program_error (const char *, int);
68
 
69
/* Addresses of exception data blocks for predefined exceptions. */
70
extern struct Exception_Data constraint_error;
71
extern struct Exception_Data numeric_error;
72
extern struct Exception_Data program_error;
73
extern struct Exception_Data storage_error;
74
extern struct Exception_Data tasking_error;
75
extern struct Exception_Data _abort_signal;
76
 
77
#define Lock_Task system__soft_links__lock_task
78
extern void (*Lock_Task) (void);
79
 
80
#define Unlock_Task system__soft_links__unlock_task
81
extern void (*Unlock_Task) (void);
82
 
83
#define Check_Abort_Status     \
84
                      system__soft_links__check_abort_status
85
extern int (*Check_Abort_Status) (void);
86
 
87
#define Raise_From_Signal_Handler \
88
                      ada__exceptions__raise_from_signal_handler
89
extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
90
 
91
/* Copies of global values computed by the binder */
92
int   __gl_main_priority            = -1;
93
int   __gl_time_slice_val           = -1;
94
char  __gl_wc_encoding              = 'n';
95
char  __gl_locking_policy           = ' ';
96
char  __gl_queuing_policy           = ' ';
97
char  __gl_task_dispatching_policy  = ' ';
98
char *__gl_restrictions             = 0;
99
char *__gl_interrupt_states         = 0;
100
int   __gl_num_interrupt_states     = 0;
101
int   __gl_unreserve_all_interrupts = 0;
102
int   __gl_exception_tracebacks     = 0;
103
int   __gl_zero_cost_exceptions     = 0;
104
int   __gl_detect_blocking          = 0;
105
 
106
/* Indication of whether synchronous signal handler has already been
107
   installed by a previous call to adainit */
108
int  __gnat_handler_installed      = 0;
109
 
110
#ifndef IN_RTS
111
int __gnat_inside_elab_final_code = 0;
112
/* ??? This variable is obsolete since 2001-08-29 but is kept to allow
113
   bootstrap from old GNAT versions (< 3.15). */
114
#endif
115
 
116
/* HAVE_GNAT_INIT_FLOAT must be set on every targets where a __gnat_init_float
117
   is defined. If this is not set them a void implementation will be defined
118
   at the end of this unit. */
119
#undef HAVE_GNAT_INIT_FLOAT
120
 
121
/******************************/
122
/* __gnat_get_interrupt_state */
123
/******************************/
124
 
125
char __gnat_get_interrupt_state (int);
126
 
127
/* This routine is called from the runtime as needed to determine the state
128
   of an interrupt, as set by an Interrupt_State pragma appearing anywhere
129
   in the current partition. The input argument is the interrupt number,
130
   and the result is one of the following:
131
 
132
       'n'   this interrupt not set by any Interrupt_State pragma
133
       'u'   Interrupt_State pragma set state to User
134
       'r'   Interrupt_State pragma set state to Runtime
135
       's'   Interrupt_State pragma set state to System */
136
 
137
char
138
__gnat_get_interrupt_state (int intrup)
139
{
140
  if (intrup >= __gl_num_interrupt_states)
141
    return 'n';
142
  else
143
    return __gl_interrupt_states [intrup];
144
}
145
 
146
/**********************/
147
/* __gnat_set_globals */
148
/**********************/
149
 
150
/* This routine is called from the binder generated main program.  It copies
151
   the values for global quantities computed by the binder into the following
152
   global locations. The reason that we go through this copy, rather than just
153
   define the global locations in the binder generated file, is that they are
154
   referenced from the runtime, which may be in a shared library, and the
155
   binder file is not in the shared library. Global references across library
156
   boundaries like this are not handled correctly in all systems.  */
157
 
158
/* For detailed description of the parameters to this routine, see the
159
   section titled Run-Time Globals in package Bindgen (bindgen.adb) */
160
 
161
void
162
__gnat_set_globals (int main_priority,
163
                    int time_slice_val,
164
                    char wc_encoding,
165
                    char locking_policy,
166
                    char queuing_policy,
167
                    char task_dispatching_policy,
168
                    char *restrictions,
169
                    char *interrupt_states,
170
                    int num_interrupt_states,
171
                    int unreserve_all_interrupts,
172
                    int exception_tracebacks,
173
                    int zero_cost_exceptions,
174
                    int detect_blocking)
175
{
176
  static int already_called = 0;
177
 
178
  /* If this procedure has been already called once, check that the
179
     arguments in this call are consistent with the ones in the previous
180
     calls. Otherwise, raise a Program_Error exception.
181
 
182
     We do not check for consistency of the wide character encoding
183
     method. This default affects only Wide_Text_IO where no explicit
184
     coding method is given, and there is no particular reason to let
185
     this default be affected by the source representation of a library
186
     in any case.
187
 
188
     We do not check either for the consistency of exception tracebacks,
189
     because exception tracebacks are not normally set in Stand-Alone
190
     libraries. If a library or the main program set the exception
191
     tracebacks, then they are never reset afterwards (see below).
192
 
193
     The value of main_priority is meaningful only when we are invoked
194
     from the main program elaboration routine of an Ada application.
195
     Checking the consistency of this parameter should therefore not be
196
     done. Since it is assured that the main program elaboration will
197
     always invoke this procedure before any library elaboration
198
     routine, only the value of main_priority during the first call
199
     should be taken into account and all the subsequent ones should be
200
     ignored. Note that the case where the main program is not written
201
     in Ada is also properly handled, since the default value will then
202
     be used for this parameter.
203
 
204
     For identical reasons, the consistency of time_slice_val should not
205
     be checked. */
206
 
207
  if (already_called)
208
    {
209
      if (__gl_locking_policy              != locking_policy
210
          || __gl_queuing_policy           != queuing_policy
211
          || __gl_task_dispatching_policy  != task_dispatching_policy
212
          || __gl_unreserve_all_interrupts != unreserve_all_interrupts
213
          || __gl_zero_cost_exceptions     != zero_cost_exceptions)
214
        __gnat_raise_program_error (__FILE__, __LINE__);
215
 
216
      /* If either a library or the main program set the exception traceback
217
         flag, it is never reset later */
218
 
219
      if (exception_tracebacks != 0)
220
         __gl_exception_tracebacks = exception_tracebacks;
221
 
222
      return;
223
    }
224
  already_called = 1;
225
 
226
  __gl_main_priority            = main_priority;
227
  __gl_time_slice_val           = time_slice_val;
228
  __gl_wc_encoding              = wc_encoding;
229
  __gl_locking_policy           = locking_policy;
230
  __gl_queuing_policy           = queuing_policy;
231
  __gl_restrictions             = restrictions;
232
  __gl_interrupt_states         = interrupt_states;
233
  __gl_num_interrupt_states     = num_interrupt_states;
234
  __gl_task_dispatching_policy  = task_dispatching_policy;
235
  __gl_unreserve_all_interrupts = unreserve_all_interrupts;
236
  __gl_exception_tracebacks     = exception_tracebacks;
237
  __gl_detect_blocking          = detect_blocking;
238
 
239
  /* ??? __gl_zero_cost_exceptions is new in 3.15 and is referenced from
240
     a-except.adb, which is also part of the compiler sources. Since the
241
     compiler is built with an older release of GNAT, the call generated by
242
     the old binder to this function does not provide any value for the
243
     corresponding argument, so the global has to be initialized in some
244
     reasonable other way. This could be removed as soon as the next major
245
     release is out.  */
246
 
247
#ifdef IN_RTS
248
  __gl_zero_cost_exceptions = zero_cost_exceptions;
249
#else
250
  __gl_zero_cost_exceptions = 0;
251
  /* We never build the compiler to run in ZCX mode currently anyway.  */
252
#endif
253
}
254
 
255
/* Notes on the Zero Cost Exceptions scheme and its impact on the signal
256
   handlers implemented below :
257
 
258
   What we call Zero Cost Exceptions is implemented using the GCC eh
259
   circuitry, even if the underlying implementation is setjmp/longjmp
260
   based. In any case ...
261
 
262
   The GCC unwinder expects to be dealing with call return addresses, since
263
   this is the "nominal" case of what we retrieve while unwinding a regular
264
   call chain. To evaluate if a handler applies at some point in this chain,
265
   the propagation engine needs to determine what region the corresponding
266
   call instruction pertains to. The return address may not be attached to the
267
   same region as the call, so the unwinder unconditionally subtracts "some"
268
   amount to the return addresses it gets to search the region tables. The
269
   exact amount is computed to ensure that the resulting address is inside the
270
   call instruction, and is thus target dependent (think about delay slots for
271
   instance).
272
 
273
   When we raise an exception from a signal handler, e.g. to transform a
274
   SIGSEGV into Storage_Error, things need to appear as if the signal handler
275
   had been "called" by the instruction which triggered the signal, so that
276
   exception handlers that apply there are considered. What the unwinder will
277
   retrieve as the return address from the signal handler is what it will find
278
   as the faulting instruction address in the corresponding signal context
279
   pushed by the kernel. Leaving this address untouched may loose, because if
280
   the triggering instruction happens to be the very first of a region, the
281
   later adjustments performed by the unwinder would yield an address outside
282
   that region. We need to compensate for those adjustments at some point,
283
   which we currently do in the GCC unwinding fallback macro.
284
 
285
   The thread at http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00343.html
286
   describes a couple of issues with our current approach. Basically: on some
287
   targets the adjustment to apply depends on the triggering signal, which is
288
   not easily accessible from the macro, and we actually do not tackle this as
289
   of today. Besides, other languages, e.g. Java, deal with this by performing
290
   the adjustment in the signal handler before the raise, so our adjustments
291
   may break those front-ends.
292
 
293
   To have it all right, we should either find a way to deal with the signal
294
   variants from the macro and convert Java on all targets (ugh), or remove
295
   our macro adjustments and update our signal handlers a-la-java way.  The
296
   latter option appears the simplest, although some targets have their share
297
   of subtleties to account for.  See for instance the syscall(SYS_sigaction)
298
   story in libjava/include/i386-signal.h.  */
299
 
300
/***************/
301
/* AIX Section */
302
/***************/
303
 
304
#if defined (_AIX)
305
 
306
#include <signal.h>
307
#include <sys/time.h>
308
 
309
/* Some versions of AIX don't define SA_NODEFER. */
310
 
311
#ifndef SA_NODEFER
312
#define SA_NODEFER 0
313
#endif /* SA_NODEFER */
314
 
315
/* Versions of AIX before 4.3 don't have nanosleep but provide
316
   nsleep instead. */
317
 
318
#ifndef _AIXVERSION_430
319
 
320
extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
321
 
322
int
323
nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
324
{
325
  return nsleep (Rqtp, Rmtp);
326
}
327
 
328
#endif /* _AIXVERSION_430 */
329
 
330
static void __gnat_error_handler (int);
331
 
332
static void
333
__gnat_error_handler (int sig)
334
{
335
  struct Exception_Data *exception;
336
  const char *msg;
337
 
338
  switch (sig)
339
    {
340
    case SIGSEGV:
341
      /* FIXME: we need to detect the case of a *real* SIGSEGV */
342
      exception = &storage_error;
343
      msg = "stack overflow or erroneous memory access";
344
      break;
345
 
346
    case SIGBUS:
347
      exception = &constraint_error;
348
      msg = "SIGBUS";
349
      break;
350
 
351
    case SIGFPE:
352
      exception = &constraint_error;
353
      msg = "SIGFPE";
354
      break;
355
 
356
    default:
357
      exception = &program_error;
358
      msg = "unhandled signal";
359
    }
360
 
361
  Raise_From_Signal_Handler (exception, msg);
362
}
363
 
364
void
365
__gnat_install_handler (void)
366
{
367
  struct sigaction act;
368
 
369
  /* Set up signal handler to map synchronous signals to appropriate
370
     exceptions.  Make sure that the handler isn't interrupted by another
371
     signal that might cause a scheduling event! */
372
 
373
  act.sa_handler = __gnat_error_handler;
374
  act.sa_flags = SA_NODEFER | SA_RESTART;
375
  sigemptyset (&act.sa_mask);
376
 
377
  /* Do not install handlers if interrupt state is "System" */
378
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
379
    sigaction (SIGABRT, &act, NULL);
380
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
381
    sigaction (SIGFPE,  &act, NULL);
382
  if (__gnat_get_interrupt_state (SIGILL) != 's')
383
    sigaction (SIGILL,  &act, NULL);
384
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
385
    sigaction (SIGSEGV, &act, NULL);
386
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
387
    sigaction (SIGBUS,  &act, NULL);
388
 
389
  __gnat_handler_installed = 1;
390
}
391
 
392
/*****************/
393
/* Tru64 section */
394
/*****************/
395
 
396
#elif defined(__alpha__) && defined(__osf__)
397
 
398
#include <signal.h>
399
#include <sys/siginfo.h>
400
 
401
static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
402
extern char *__gnat_get_code_loc (struct sigcontext *);
403
extern void __gnat_set_code_loc (struct sigcontext *, char *);
404
extern size_t __gnat_machine_state_length (void);
405
 
406
static void
407
__gnat_error_handler
408
  (int sig, siginfo_t *sip, struct sigcontext *context ATTRIBUTE_UNUSED)
409
{
410
  struct Exception_Data *exception;
411
  static int recurse = 0;
412
  const char *msg;
413
 
414
  /* If this was an explicit signal from a "kill", just resignal it.  */
415
  if (SI_FROMUSER (sip))
416
    {
417
      signal (sig, SIG_DFL);
418
      kill (getpid(), sig);
419
    }
420
 
421
  /* Otherwise, treat it as something we handle.  */
422
  switch (sig)
423
    {
424
    case SIGSEGV:
425
      /* If the problem was permissions, this is a constraint error.
426
         Likewise if the failing address isn't maximally aligned or if
427
         we've recursed.
428
 
429
         ??? Using a static variable here isn't task-safe, but it's
430
         much too hard to do anything else and we're just determining
431
         which exception to raise.  */
432
      if (sip->si_code == SEGV_ACCERR
433
          || (((long) sip->si_addr) & 3) != 0
434
          || recurse)
435
        {
436
          exception = &constraint_error;
437
          msg = "SIGSEGV";
438
        }
439
      else
440
        {
441
          /* See if the page before the faulting page is accessible.  Do that
442
             by trying to access it.  We'd like to simply try to access
443
             4096 + the faulting address, but it's not guaranteed to be
444
             the actual address, just to be on the same page.  */
445
          recurse++;
446
          ((volatile char *)
447
           ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
448
          msg = "stack overflow (or erroneous memory access)";
449
          exception = &storage_error;
450
        }
451
      break;
452
 
453
    case SIGBUS:
454
      exception = &program_error;
455
      msg = "SIGBUS";
456
      break;
457
 
458
    case SIGFPE:
459
      exception = &constraint_error;
460
      msg = "SIGFPE";
461
      break;
462
 
463
    default:
464
      exception = &program_error;
465
      msg = "unhandled signal";
466
    }
467
 
468
  recurse = 0;
469
  Raise_From_Signal_Handler (exception, (char *) msg);
470
}
471
 
472
void
473
__gnat_install_handler (void)
474
{
475
  struct sigaction act;
476
 
477
  /* Setup signal handler to map synchronous signals to appropriate
478
     exceptions. Make sure that the handler isn't interrupted by another
479
     signal that might cause a scheduling event! */
480
 
481
  act.sa_handler = (void (*) (int)) __gnat_error_handler;
482
  act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
483
  sigemptyset (&act.sa_mask);
484
 
485
  /* Do not install handlers if interrupt state is "System" */
486
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
487
    sigaction (SIGABRT, &act, NULL);
488
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
489
    sigaction (SIGFPE,  &act, NULL);
490
  if (__gnat_get_interrupt_state (SIGILL) != 's')
491
    sigaction (SIGILL,  &act, NULL);
492
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
493
    sigaction (SIGSEGV, &act, NULL);
494
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
495
    sigaction (SIGBUS,  &act, NULL);
496
 
497
  __gnat_handler_installed = 1;
498
}
499
 
500
/* Routines called by s-mastop-tru64.adb.  */
501
 
502
#define SC_GP 29
503
 
504
char *
505
__gnat_get_code_loc (struct sigcontext *context)
506
{
507
  return (char *) context->sc_pc;
508
}
509
 
510
void
511
__gnat_set_code_loc (struct sigcontext *context, char *pc)
512
{
513
  context->sc_pc = (long) pc;
514
}
515
 
516
 
517
size_t
518
__gnat_machine_state_length (void)
519
{
520
  return sizeof (struct sigcontext);
521
}
522
 
523
/********************/
524
/* PA HP-UX section */
525
/********************/
526
 
527
#elif defined (__hppa__) && defined (__hpux__)
528
 
529
#include <signal.h>
530
#include <sys/ucontext.h>
531
 
532
static void
533
__gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
534
 
535
/* __gnat_adjust_context_for_raise - see comments along with the default
536
   version later in this file.  */
537
 
538
#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
539
 
540
void
541
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
542
{
543
  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
544
 
545
  if (UseWideRegs (mcontext))
546
    mcontext->ss_wide.ss_32.ss_pcoq_head_lo ++;
547
  else
548
    mcontext->ss_narrow.ss_pcoq_head ++;
549
}
550
 
551
static void
552
__gnat_error_handler
553
  (int sig, siginfo_t *siginfo ATTRIBUTE_UNUSED, void *ucontext)
554
{
555
  struct Exception_Data *exception;
556
  const char *msg;
557
 
558
  switch (sig)
559
    {
560
    case SIGSEGV:
561
      /* FIXME: we need to detect the case of a *real* SIGSEGV */
562
      exception = &storage_error;
563
      msg = "stack overflow or erroneous memory access";
564
      break;
565
 
566
    case SIGBUS:
567
      exception = &constraint_error;
568
      msg = "SIGBUS";
569
      break;
570
 
571
    case SIGFPE:
572
      exception = &constraint_error;
573
      msg = "SIGFPE";
574
      break;
575
 
576
    default:
577
      exception = &program_error;
578
      msg = "unhandled signal";
579
    }
580
 
581
  __gnat_adjust_context_for_raise (sig, ucontext);
582
 
583
  Raise_From_Signal_Handler (exception, msg);
584
}
585
 
586
void
587
__gnat_install_handler (void)
588
{
589
  struct sigaction act;
590
 
591
  /* Set up signal handler to map synchronous signals to appropriate
592
     exceptions.  Make sure that the handler isn't interrupted by another
593
     signal that might cause a scheduling event! Also setup an alternate
594
     stack region for the handler execution so that stack overflows can be
595
     handled properly, avoiding a SEGV generation from stack usage by the
596
     handler itself. */
597
 
598
  static char handler_stack[SIGSTKSZ*2];
599
  /* SIGSTKSZ appeared to be "short" for the needs in some contexts
600
     (e.g. experiments with GCC ZCX exceptions).  */
601
 
602
  stack_t stack;
603
 
604
  stack.ss_sp    = handler_stack;
605
  stack.ss_size  = sizeof (handler_stack);
606
  stack.ss_flags = 0;
607
 
608
  sigaltstack (&stack, NULL);
609
 
610
  act.sa_sigaction = __gnat_error_handler;
611
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_ONSTACK | SA_SIGINFO;
612
  sigemptyset (&act.sa_mask);
613
 
614
  /* Do not install handlers if interrupt state is "System" */
615
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
616
    sigaction (SIGABRT, &act, NULL);
617
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
618
    sigaction (SIGFPE,  &act, NULL);
619
  if (__gnat_get_interrupt_state (SIGILL) != 's')
620
    sigaction (SIGILL,  &act, NULL);
621
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
622
    sigaction (SIGSEGV, &act, NULL);
623
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
624
    sigaction (SIGBUS,  &act, NULL);
625
 
626
  __gnat_handler_installed = 1;
627
}
628
 
629
/*********************/
630
/* GNU/Linux Section */
631
/*********************/
632
 
633
#elif defined (linux) && (defined (i386) || defined (__x86_64__) \
634
                          || defined (__ia64__))
635
 
636
#include <signal.h>
637
 
638
#define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
639
#include <sys/ucontext.h>
640
 
641
/* GNU/Linux, which uses glibc, does not define NULL in included
642
   header files */
643
 
644
#if !defined (NULL)
645
#define NULL ((void *) 0)
646
#endif
647
 
648
static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
649
 
650
/* __gnat_adjust_context_for_raise - see comments along with the default
651
   version later in this file.  */
652
 
653
#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
654
 
655
void
656
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
657
{
658
  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
659
 
660
#if defined (i386)
661
  mcontext->gregs[REG_EIP]++;
662
#elif defined (__x86_64__)
663
  mcontext->gregs[REG_RIP]++;
664
#elif defined (__ia64__)
665
  mcontext->sc_ip++;
666
#endif
667
}
668
 
669
static void
670
__gnat_error_handler (int sig,
671
                      siginfo_t *siginfo ATTRIBUTE_UNUSED,
672
                      void *ucontext)
673
{
674
  struct Exception_Data *exception;
675
  const char *msg;
676
  static int recurse = 0;
677
 
678
  switch (sig)
679
    {
680
    case SIGSEGV:
681
      /* If the problem was permissions, this is a constraint error.
682
       Likewise if the failing address isn't maximally aligned or if
683
       we've recursed.
684
 
685
       ??? Using a static variable here isn't task-safe, but it's
686
       much too hard to do anything else and we're just determining
687
       which exception to raise.  */
688
      if (recurse)
689
      {
690
        exception = &constraint_error;
691
        msg = "SIGSEGV";
692
      }
693
      else
694
      {
695
        /* Here we would like a discrimination test to see whether the
696
           page before the faulting address is accessible. Unfortunately
697
           Linux seems to have no way of giving us the faulting address.
698
 
699
           In versions of a-init.c before 1.95, we had a test of the page
700
           before the stack pointer using:
701
 
702
            recurse++;
703
             ((volatile char *)
704
              ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
705
 
706
           but that's wrong, since it tests the stack pointer location, and
707
           the current stack probe code does not move the stack pointer
708
           until all probes succeed.
709
 
710
           For now we simply do not attempt any discrimination at all. Note
711
           that this is quite acceptable, since a "real" SIGSEGV can only
712
           occur as the result of an erroneous program */
713
 
714
        msg = "stack overflow (or erroneous memory access)";
715
        exception = &storage_error;
716
      }
717
      break;
718
 
719
    case SIGBUS:
720
      exception = &constraint_error;
721
      msg = "SIGBUS";
722
      break;
723
 
724
    case SIGFPE:
725
      exception = &constraint_error;
726
      msg = "SIGFPE";
727
      break;
728
 
729
    default:
730
      exception = &program_error;
731
      msg = "unhandled signal";
732
    }
733
  recurse = 0;
734
 
735
  /* We adjust the interrupted context here (and not in the
736
     MD_FALLBACK_FRAME_STATE_FOR macro) because recent versions of the Native
737
     POSIX Thread Library (NPTL) are compiled with DWARF 2 unwind information,
738
     and hence the later macro is never executed for signal frames. */
739
 
740
  __gnat_adjust_context_for_raise (sig, ucontext);
741
 
742
  Raise_From_Signal_Handler (exception, msg);
743
}
744
 
745
void
746
__gnat_install_handler (void)
747
{
748
  struct sigaction act;
749
 
750
  /* Set up signal handler to map synchronous signals to appropriate
751
     exceptions.  Make sure that the handler isn't interrupted by another
752
     signal that might cause a scheduling event! */
753
 
754
  act.sa_sigaction = __gnat_error_handler;
755
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
756
  sigemptyset (&act.sa_mask);
757
 
758
  /* Do not install handlers if interrupt state is "System" */
759
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
760
    sigaction (SIGABRT, &act, NULL);
761
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
762
    sigaction (SIGFPE,  &act, NULL);
763
  if (__gnat_get_interrupt_state (SIGILL) != 's')
764
    sigaction (SIGILL,  &act, NULL);
765
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
766
    sigaction (SIGSEGV, &act, NULL);
767
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
768
    sigaction (SIGBUS,  &act, NULL);
769
 
770
  __gnat_handler_installed = 1;
771
}
772
 
773
/*******************/
774
/* Interix Section */
775
/*******************/
776
 
777
#elif defined (__INTERIX)
778
 
779
#include <signal.h>
780
 
781
static void __gnat_error_handler (int);
782
 
783
static void
784
__gnat_error_handler (int sig)
785
{
786
  struct Exception_Data *exception;
787
  const char *msg;
788
 
789
  switch (sig)
790
    {
791
    case SIGSEGV:
792
      exception = &storage_error;
793
      msg = "stack overflow or erroneous memory access";
794
      break;
795
 
796
    case SIGBUS:
797
      exception = &constraint_error;
798
      msg = "SIGBUS";
799
      break;
800
 
801
    case SIGFPE:
802
      exception = &constraint_error;
803
      msg = "SIGFPE";
804
      break;
805
 
806
    default:
807
      exception = &program_error;
808
      msg = "unhandled signal";
809
    }
810
 
811
  Raise_From_Signal_Handler (exception, msg);
812
}
813
 
814
void
815
__gnat_install_handler (void)
816
{
817
  struct sigaction act;
818
 
819
  /* Set up signal handler to map synchronous signals to appropriate
820
     exceptions.  Make sure that the handler isn't interrupted by another
821
     signal that might cause a scheduling event! */
822
 
823
  act.sa_handler = __gnat_error_handler;
824
  act.sa_flags = 0;
825
  sigemptyset (&act.sa_mask);
826
 
827
  /* Handlers for signals besides SIGSEGV cause c974013 to hang */
828
/*  sigaction (SIGILL,  &act, NULL); */
829
/*  sigaction (SIGABRT, &act, NULL); */
830
/*  sigaction (SIGFPE,  &act, NULL); */
831
/*  sigaction (SIGBUS,  &act, NULL); */
832
 
833
  /* Do not install handlers if interrupt state is "System" */
834
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
835
    sigaction (SIGSEGV, &act, NULL);
836
 
837
  __gnat_handler_installed = 1;
838
}
839
 
840
/****************/
841
/* IRIX Section */
842
/****************/
843
 
844
#elif defined (sgi)
845
 
846
#include <signal.h>
847
#include <siginfo.h>
848
 
849
#ifndef NULL
850
#define NULL 0
851
#endif
852
 
853
#define SIGADAABORT 48
854
#define SIGNAL_STACK_SIZE 4096
855
#define SIGNAL_STACK_ALIGNMENT 64
856
 
857
static void __gnat_error_handler (int, int, sigcontext_t *);
858
 
859
/* We are not setting the SA_SIGINFO bit in the sigaction flags when
860
   connecting that handler, with the effects described in the sigaction
861
   man page:
862
 
863
          SA_SIGINFO [...]
864
          If cleared and the signal is caught, the first argument is
865
          also the signal number but the second argument is the signal
866
          code identifying the cause of the signal. The third argument
867
          points to a sigcontext_t structure containing the receiving
868
          process's context when the signal was delivered.
869
*/
870
 
871
static void
872
__gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
873
{
874
  struct Exception_Data *exception;
875
  const char *msg;
876
 
877
  switch (sig)
878
    {
879
    case SIGSEGV:
880
      if (code == EFAULT)
881
        {
882
          exception = &program_error;
883
          msg = "SIGSEGV: (Invalid virtual address)";
884
        }
885
      else if (code == ENXIO)
886
        {
887
          exception = &program_error;
888
          msg = "SIGSEGV: (Read beyond mapped object)";
889
        }
890
      else if (code == ENOSPC)
891
        {
892
          exception = &program_error; /* ??? storage_error ??? */
893
          msg = "SIGSEGV: (Autogrow for file failed)";
894
        }
895
      else if (code == EACCES || code == EEXIST)
896
        {
897
          /* ??? We handle stack overflows here, some of which do trigger
898
                 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
899
                 the documented valid codes for SEGV in the signal(5) man
900
                 page.  */
901
 
902
          /* ??? Re-add smarts to further verify that we launched
903
                 the stack into a guard page, not an attempt to
904
                 write to .text or something */
905
          exception = &storage_error;
906
          msg = "SIGSEGV: (stack overflow or erroneous memory access)";
907
        }
908
      else
909
        {
910
          /* Just in case the OS guys did it to us again.  Sometimes
911
             they fail to document all of the valid codes that are
912
             passed to signal handlers, just in case someone depends
913
             on knowing all the codes */
914
          exception = &program_error;
915
          msg = "SIGSEGV: (Undocumented reason)";
916
        }
917
      break;
918
 
919
    case SIGBUS:
920
      /* Map all bus errors to Program_Error.  */
921
      exception = &program_error;
922
      msg = "SIGBUS";
923
      break;
924
 
925
    case SIGFPE:
926
      /* Map all fpe errors to Constraint_Error.  */
927
      exception = &constraint_error;
928
      msg = "SIGFPE";
929
      break;
930
 
931
    case SIGADAABORT:
932
      if ((*Check_Abort_Status) ())
933
        {
934
          exception = &_abort_signal;
935
          msg = "";
936
        }
937
      else
938
        return;
939
 
940
      break;
941
 
942
    default:
943
      /* Everything else is a Program_Error. */
944
      exception = &program_error;
945
      msg = "unhandled signal";
946
    }
947
 
948
  Raise_From_Signal_Handler (exception, msg);
949
}
950
 
951
void
952
__gnat_install_handler (void)
953
{
954
  struct sigaction act;
955
 
956
  /* Setup signal handler to map synchronous signals to appropriate
957
     exceptions.  Make sure that the handler isn't interrupted by another
958
     signal that might cause a scheduling event! */
959
 
960
  act.sa_handler = __gnat_error_handler;
961
  act.sa_flags = SA_NODEFER + SA_RESTART;
962
  sigfillset (&act.sa_mask);
963
  sigemptyset (&act.sa_mask);
964
 
965
  /* Do not install handlers if interrupt state is "System" */
966
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
967
    sigaction (SIGABRT, &act, NULL);
968
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
969
    sigaction (SIGFPE,  &act, NULL);
970
  if (__gnat_get_interrupt_state (SIGILL) != 's')
971
    sigaction (SIGILL,  &act, NULL);
972
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
973
    sigaction (SIGSEGV, &act, NULL);
974
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
975
    sigaction (SIGBUS,  &act, NULL);
976
  if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
977
    sigaction (SIGADAABORT,  &act, NULL);
978
 
979
  __gnat_handler_installed = 1;
980
}
981
 
982
/*******************/
983
/* Solaris Section */
984
/*******************/
985
 
986
#elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
987
 
988
#include <signal.h>
989
#include <siginfo.h>
990
 
991
static void __gnat_error_handler (int, siginfo_t *);
992
 
993
static void
994
__gnat_error_handler (int sig, siginfo_t *sip)
995
{
996
  struct Exception_Data *exception;
997
  static int recurse = 0;
998
  const char *msg;
999
 
1000
  /* If this was an explicit signal from a "kill", just resignal it.  */
1001
  if (SI_FROMUSER (sip))
1002
    {
1003
      signal (sig, SIG_DFL);
1004
      kill (getpid(), sig);
1005
    }
1006
 
1007
  /* Otherwise, treat it as something we handle.  */
1008
  switch (sig)
1009
    {
1010
    case SIGSEGV:
1011
      /* If the problem was permissions, this is a constraint error.
1012
         Likewise if the failing address isn't maximally aligned or if
1013
         we've recursed.
1014
 
1015
         ??? Using a static variable here isn't task-safe, but it's
1016
         much too hard to do anything else and we're just determining
1017
         which exception to raise.  */
1018
      if (sip->si_code == SEGV_ACCERR
1019
          || (((long) sip->si_addr) & 3) != 0
1020
          || recurse)
1021
        {
1022
          exception = &constraint_error;
1023
          msg = "SIGSEGV";
1024
        }
1025
      else
1026
        {
1027
          /* See if the page before the faulting page is accessible.  Do that
1028
             by trying to access it.  We'd like to simply try to access
1029
             4096 + the faulting address, but it's not guaranteed to be
1030
             the actual address, just to be on the same page.  */
1031
          recurse++;
1032
          ((volatile char *)
1033
           ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1034
          exception = &storage_error;
1035
          msg = "stack overflow (or erroneous memory access)";
1036
        }
1037
      break;
1038
 
1039
    case SIGBUS:
1040
      exception = &program_error;
1041
      msg = "SIGBUS";
1042
      break;
1043
 
1044
    case SIGFPE:
1045
      exception = &constraint_error;
1046
      msg = "SIGFPE";
1047
      break;
1048
 
1049
    default:
1050
      exception = &program_error;
1051
      msg = "unhandled signal";
1052
    }
1053
 
1054
  recurse = 0;
1055
 
1056
  Raise_From_Signal_Handler (exception, msg);
1057
}
1058
 
1059
void
1060
__gnat_install_handler (void)
1061
{
1062
  struct sigaction act;
1063
 
1064
  /* Set up signal handler to map synchronous signals to appropriate
1065
     exceptions.  Make sure that the handler isn't interrupted by another
1066
     signal that might cause a scheduling event! */
1067
 
1068
  act.sa_handler = __gnat_error_handler;
1069
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1070
  sigemptyset (&act.sa_mask);
1071
 
1072
  /* Do not install handlers if interrupt state is "System" */
1073
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
1074
    sigaction (SIGABRT, &act, NULL);
1075
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
1076
    sigaction (SIGFPE,  &act, NULL);
1077
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1078
    sigaction (SIGSEGV, &act, NULL);
1079
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
1080
    sigaction (SIGBUS,  &act, NULL);
1081
 
1082
  __gnat_handler_installed = 1;
1083
}
1084
 
1085
/***************/
1086
/* VMS Section */
1087
/***************/
1088
 
1089
#elif defined (VMS)
1090
 
1091
long __gnat_error_handler (int *, void *);
1092
 
1093
#ifdef __IA64
1094
#define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1095
#define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1096
#define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1097
#else
1098
#define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1099
#define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1100
#define lib_get_invo_handle LIB$GET_INVO_HANDLE
1101
#endif
1102
 
1103
#if defined (IN_RTS) && !defined (__IA64)
1104
 
1105
/* The prehandler actually gets control first on a condition. It swaps the
1106
   stack pointer and calls the handler (__gnat_error_handler). */
1107
extern long __gnat_error_prehandler (void);
1108
 
1109
extern char *__gnat_error_prehandler_stack;   /* Alternate signal stack */
1110
#endif
1111
 
1112
/* Define macro symbols for the VMS conditions that become Ada exceptions.
1113
   Most of these are also defined in the header file ssdef.h which has not
1114
   yet been converted to be recognized by Gnu C. */
1115
 
1116
/* Defining these as macros, as opposed to external addresses, allows
1117
   them to be used in a case statement (below */
1118
#define SS$_ACCVIO            12
1119
#define SS$_HPARITH         1284
1120
#define SS$_STKOVF          1364
1121
#define SS$_RESIGNAL        2328
1122
 
1123
/* These codes are in standard message libraries */
1124
extern int CMA$_EXIT_THREAD;
1125
extern int SS$_DEBUG;
1126
extern int SS$_INTDIV;
1127
extern int LIB$_KEYNOTFOU;
1128
extern int LIB$_ACTIMAGE;
1129
extern int MTH$_FLOOVEMAT;       /* Some ACVC_21 CXA tests */
1130
 
1131
/* These codes are non standard, which is to say the author is
1132
   not sure if they are defined in the standard message libraries
1133
   so keep them as macros for now. */
1134
#define RDB$_STREAM_EOF 20480426
1135
#define FDL$_UNPRIKW 11829410
1136
 
1137
struct cond_except {
1138
  const int *cond;
1139
  const struct Exception_Data *except;
1140
};
1141
 
1142
struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1143
 
1144
/* Conditions that don't have an Ada exception counterpart must raise
1145
   Non_Ada_Error.  Since this is defined in s-auxdec, it should only be
1146
   referenced by user programs, not the compiler or tools. Hence the
1147
   #ifdef IN_RTS. */
1148
 
1149
#ifdef IN_RTS
1150
 
1151
#define Status_Error ada__io_exceptions__status_error
1152
extern struct Exception_Data Status_Error;
1153
 
1154
#define Mode_Error ada__io_exceptions__mode_error
1155
extern struct Exception_Data Mode_Error;
1156
 
1157
#define Name_Error ada__io_exceptions__name_error
1158
extern struct Exception_Data Name_Error;
1159
 
1160
#define Use_Error ada__io_exceptions__use_error
1161
extern struct Exception_Data Use_Error;
1162
 
1163
#define Device_Error ada__io_exceptions__device_error
1164
extern struct Exception_Data Device_Error;
1165
 
1166
#define End_Error ada__io_exceptions__end_error
1167
extern struct Exception_Data End_Error;
1168
 
1169
#define Data_Error ada__io_exceptions__data_error
1170
extern struct Exception_Data Data_Error;
1171
 
1172
#define Layout_Error ada__io_exceptions__layout_error
1173
extern struct Exception_Data Layout_Error;
1174
 
1175
#define Non_Ada_Error system__aux_dec__non_ada_error
1176
extern struct Exception_Data Non_Ada_Error;
1177
 
1178
#define Coded_Exception system__vms_exception_table__coded_exception
1179
extern struct Exception_Data *Coded_Exception (Exception_Code);
1180
 
1181
#define Base_Code_In system__vms_exception_table__base_code_in
1182
extern Exception_Code Base_Code_In (Exception_Code);
1183
 
1184
/* DEC Ada exceptions are not defined in a header file, so they
1185
   must be declared as external addresses */
1186
 
1187
extern int ADA$_PROGRAM_ERROR __attribute__ ((weak));
1188
extern int ADA$_LOCK_ERROR __attribute__ ((weak));
1189
extern int ADA$_EXISTENCE_ERROR __attribute__ ((weak));
1190
extern int ADA$_KEY_ERROR __attribute__ ((weak));
1191
extern int ADA$_KEYSIZERR __attribute__ ((weak));
1192
extern int ADA$_STAOVF __attribute__ ((weak));
1193
extern int ADA$_CONSTRAINT_ERRO __attribute__ ((weak));
1194
extern int ADA$_IOSYSFAILED __attribute__ ((weak));
1195
extern int ADA$_LAYOUT_ERROR __attribute__ ((weak));
1196
extern int ADA$_STORAGE_ERROR __attribute__ ((weak));
1197
extern int ADA$_DATA_ERROR __attribute__ ((weak));
1198
extern int ADA$_DEVICE_ERROR __attribute__ ((weak));
1199
extern int ADA$_END_ERROR __attribute__ ((weak));
1200
extern int ADA$_MODE_ERROR __attribute__ ((weak));
1201
extern int ADA$_NAME_ERROR __attribute__ ((weak));
1202
extern int ADA$_STATUS_ERROR __attribute__ ((weak));
1203
extern int ADA$_NOT_OPEN __attribute__ ((weak));
1204
extern int ADA$_ALREADY_OPEN __attribute__ ((weak));
1205
extern int ADA$_USE_ERROR __attribute__ ((weak));
1206
extern int ADA$_UNSUPPORTED __attribute__ ((weak));
1207
extern int ADA$_FAC_MODE_MISMAT __attribute__ ((weak));
1208
extern int ADA$_ORG_MISMATCH __attribute__ ((weak));
1209
extern int ADA$_RFM_MISMATCH __attribute__ ((weak));
1210
extern int ADA$_RAT_MISMATCH __attribute__ ((weak));
1211
extern int ADA$_MRS_MISMATCH __attribute__ ((weak));
1212
extern int ADA$_MRN_MISMATCH __attribute__ ((weak));
1213
extern int ADA$_KEY_MISMATCH __attribute__ ((weak));
1214
extern int ADA$_MAXLINEXC __attribute__ ((weak));
1215
extern int ADA$_LINEXCMRS __attribute__ ((weak));
1216
 
1217
/* DEC Ada specific conditions */
1218
static const struct cond_except dec_ada_cond_except_table [] = {
1219
  {&ADA$_PROGRAM_ERROR,   &program_error},
1220
  {&ADA$_USE_ERROR,       &Use_Error},
1221
  {&ADA$_KEYSIZERR,       &program_error},
1222
  {&ADA$_STAOVF,          &storage_error},
1223
  {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1224
  {&ADA$_IOSYSFAILED,     &Device_Error},
1225
  {&ADA$_LAYOUT_ERROR,    &Layout_Error},
1226
  {&ADA$_STORAGE_ERROR,   &storage_error},
1227
  {&ADA$_DATA_ERROR,      &Data_Error},
1228
  {&ADA$_DEVICE_ERROR,    &Device_Error},
1229
  {&ADA$_END_ERROR,       &End_Error},
1230
  {&ADA$_MODE_ERROR,      &Mode_Error},
1231
  {&ADA$_NAME_ERROR,      &Name_Error},
1232
  {&ADA$_STATUS_ERROR,    &Status_Error},
1233
  {&ADA$_NOT_OPEN,        &Use_Error},
1234
  {&ADA$_ALREADY_OPEN,    &Use_Error},
1235
  {&ADA$_USE_ERROR,       &Use_Error},
1236
  {&ADA$_UNSUPPORTED,     &Use_Error},
1237
  {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1238
  {&ADA$_ORG_MISMATCH,    &Use_Error},
1239
  {&ADA$_RFM_MISMATCH,    &Use_Error},
1240
  {&ADA$_RAT_MISMATCH,    &Use_Error},
1241
  {&ADA$_MRS_MISMATCH,    &Use_Error},
1242
  {&ADA$_MRN_MISMATCH,    &Use_Error},
1243
  {&ADA$_KEY_MISMATCH,    &Use_Error},
1244
  {&ADA$_MAXLINEXC,       &constraint_error},
1245
  {&ADA$_LINEXCMRS,       &constraint_error},
1246
  {0,                     0}
1247
};
1248
 
1249
#if 0
1250
   /* Already handled by a pragma Import_Exception
1251
      in Aux_IO_Exceptions */
1252
  {&ADA$_LOCK_ERROR,      &Lock_Error},
1253
  {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1254
  {&ADA$_KEY_ERROR,       &Key_Error},
1255
#endif
1256
 
1257
#endif /* IN_RTS */
1258
 
1259
/* Non DEC Ada specific conditions. We could probably also put
1260
   SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF. */
1261
static const struct cond_except cond_except_table [] = {
1262
  {&MTH$_FLOOVEMAT, &constraint_error},
1263
  {&SS$_INTDIV,     &constraint_error},
1264
  {0,               0}
1265
};
1266
 
1267
/* To deal with VMS conditions and their mapping to Ada exceptions,
1268
   the __gnat_error_handler routine below is installed as an exception
1269
   vector having precedence over DEC frame handlers.  Some conditions
1270
   still need to be handled by such handlers, however, in which case
1271
   __gnat_error_handler needs to return SS$_RESIGNAL.  Consider for
1272
   instance the use of a third party library compiled with DECAda and
1273
   performing it's own exception handling internally.
1274
 
1275
   To allow some user-level flexibility, which conditions should be
1276
   resignaled is controlled by a predicate function, provided with the
1277
   condition value and returning a boolean indication stating whether
1278
   this condition should be resignaled or not.
1279
 
1280
   That predicate function is called indirectly, via a function pointer,
1281
   by __gnat_error_handler, and changing that pointer is allowed to the
1282
   the user code by way of the __gnat_set_resignal_predicate interface.
1283
 
1284
   The user level function may then implement what it likes, including
1285
   for instance the maintenance of a dynamic data structure if the set
1286
   of to be resignalled conditions has to change over the program's
1287
   lifetime.
1288
 
1289
   ??? This is not a perfect solution to deal with the possible
1290
   interactions between the GNAT and the DECAda exception handling
1291
   models and better (more general) schemes are studied.  This is so
1292
   just provided as a convenient workaround in the meantime, and
1293
   should be use with caution since the implementation has been kept
1294
   very simple.  */
1295
 
1296
typedef int
1297
resignal_predicate (int code);
1298
 
1299
const int *cond_resignal_table [] = {
1300
  &CMA$_EXIT_THREAD,
1301
  &SS$_DEBUG,
1302
  &LIB$_KEYNOTFOU,
1303
  &LIB$_ACTIMAGE,
1304
  (int *) RDB$_STREAM_EOF,
1305
  (int *) FDL$_UNPRIKW,
1306
 
1307
};
1308
 
1309
/* Default GNAT predicate for resignaling conditions.  */
1310
 
1311
static int
1312
__gnat_default_resignal_p (int code)
1313
{
1314
  int i, iexcept;
1315
 
1316
  for (i = 0, iexcept = 0;
1317
       cond_resignal_table [i] &&
1318
       !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1319
       i++);
1320
 
1321
  return iexcept;
1322
}
1323
 
1324
/* Static pointer to predicate that the __gnat_error_handler exception
1325
   vector invokes to determine if it should resignal a condition.  */
1326
 
1327
static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1328
 
1329
/* User interface to change the predicate pointer to PREDICATE. Reset to
1330
   the default if PREDICATE is null.  */
1331
 
1332
void
1333
__gnat_set_resignal_predicate (resignal_predicate * predicate)
1334
{
1335
  if (predicate == 0)
1336
    __gnat_resignal_p = __gnat_default_resignal_p;
1337
  else
1338
    __gnat_resignal_p = predicate;
1339
}
1340
 
1341
/* Should match System.Parameters.Default_Exception_Msg_Max_Length */
1342
#define Default_Exception_Msg_Max_Length 512
1343
 
1344
/* Action routine for SYS$PUTMSG. There may be
1345
   multiple conditions, each with text to be appended to
1346
   MESSAGE and separated by line termination. */
1347
 
1348
static int
1349
copy_msg (msgdesc, message)
1350
     struct descriptor_s *msgdesc;
1351
     char *message;
1352
{
1353
  int len = strlen (message);
1354
  int copy_len;
1355
 
1356
  /* Check for buffer overflow and skip */
1357
  if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1358
    {
1359
      strcat (message, "\r\n");
1360
      len += 2;
1361
    }
1362
 
1363
  /* Check for buffer overflow and truncate if necessary */
1364
  copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1365
              msgdesc->len :
1366
              Default_Exception_Msg_Max_Length - 1 - len);
1367
  strncpy (&message [len], msgdesc->adr, copy_len);
1368
  message [len + copy_len] = 0;
1369
 
1370
  return 0;
1371
}
1372
 
1373
long
1374
__gnat_error_handler (int *sigargs, void *mechargs)
1375
{
1376
  struct Exception_Data *exception = 0;
1377
  Exception_Code base_code;
1378
  struct descriptor_s gnat_facility = {4,0,"GNAT"};
1379
  char message [Default_Exception_Msg_Max_Length];
1380
 
1381
  const char *msg = "";
1382
  char curr_icb[544];
1383
  long curr_invo_handle;
1384
 
1385
  /* Check for conditions to resignal which aren't effected by pragma
1386
     Import_Exception.  */
1387
  if (__gnat_resignal_p (sigargs [1]))
1388
    return SS$_RESIGNAL;
1389
 
1390
#ifdef IN_RTS
1391
  /* See if it's an imported exception. Beware that registered exceptions
1392
     are bound to their base code, with the severity bits masked off.  */
1393
  base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1394
  exception = Coded_Exception (base_code);
1395
 
1396
  if (exception)
1397
    {
1398
      message [0] = 0;
1399
 
1400
      /* Subtract PC & PSL fields which messes with PUTMSG */
1401
      sigargs [0] -= 2;
1402
      SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1403
      sigargs [0] += 2;
1404
      msg = message;
1405
 
1406
      exception->Name_Length = 19;
1407
      /* The full name really should be get sys$getmsg returns. ??? */
1408
      exception->Full_Name = "IMPORTED_EXCEPTION";
1409
      exception->Import_Code = base_code;
1410
    }
1411
#endif
1412
 
1413
  if (exception == 0)
1414
    switch (sigargs[1])
1415
      {
1416
      case SS$_ACCVIO:
1417
        if (sigargs[3] == 0)
1418
          {
1419
            exception = &constraint_error;
1420
            msg = "access zero";
1421
          }
1422
        else
1423
          {
1424
            exception = &storage_error;
1425
            msg = "stack overflow (or erroneous memory access)";
1426
          }
1427
        break;
1428
 
1429
      case SS$_STKOVF:
1430
        exception = &storage_error;
1431
        msg = "stack overflow";
1432
        break;
1433
 
1434
      case SS$_HPARITH:
1435
#ifndef IN_RTS
1436
        return SS$_RESIGNAL; /* toplev.c handles for compiler */
1437
#else
1438
        {
1439
          exception = &constraint_error;
1440
          msg = "arithmetic error";
1441
        }
1442
#endif
1443
        break;
1444
 
1445
      default:
1446
#ifdef IN_RTS
1447
        {
1448
          int i;
1449
 
1450
          /* Scan the DEC Ada exception condition table for a match and fetch
1451
             the associated GNAT exception pointer */
1452
          for (i = 0;
1453
               dec_ada_cond_except_table [i].cond &&
1454
               !LIB$MATCH_COND (&sigargs [1],
1455
                                &dec_ada_cond_except_table [i].cond);
1456
               i++);
1457
          exception = (struct Exception_Data *)
1458
            dec_ada_cond_except_table [i].except;
1459
 
1460
          if (!exception)
1461
            {
1462
              /* Scan the VMS standard condition table for a match and fetch
1463
                 the associated GNAT exception pointer */
1464
              for (i = 0;
1465
                   cond_except_table [i].cond &&
1466
                   !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1467
                   i++);
1468
              exception =(struct Exception_Data *) cond_except_table [i].except;
1469
 
1470
              if (!exception)
1471
                /* User programs expect Non_Ada_Error to be raised, reference
1472
                   DEC Ada test CXCONDHAN. */
1473
                exception = &Non_Ada_Error;
1474
            }
1475
        }
1476
#else
1477
        exception = &program_error;
1478
#endif
1479
        message [0] = 0;
1480
        /* Subtract PC & PSL fields which messes with PUTMSG */
1481
        sigargs [0] -= 2;
1482
        SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1483
        sigargs [0] += 2;
1484
        msg = message;
1485
        break;
1486
      }
1487
 
1488
  Raise_From_Signal_Handler (exception, msg);
1489
}
1490
 
1491
void
1492
__gnat_install_handler (void)
1493
{
1494
  long prvhnd;
1495
#if defined (IN_RTS) && !defined (__IA64)
1496
  char *c;
1497
 
1498
  c = (char *) xmalloc (2049);
1499
 
1500
  __gnat_error_prehandler_stack = &c[2048];
1501
 
1502
  /* __gnat_error_prehandler is an assembly function.  */
1503
  SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1504
#else
1505
#if defined (IN_RTS) && defined (__IA64)
1506
  if (getenv ("DBG$TDBG"))
1507
    printf ("DBG$TDBG defined, __gnat_error_handler not installed!\n");
1508
  else
1509
#endif
1510
    SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1511
#endif
1512
 
1513
  __gnat_handler_installed = 1;
1514
}
1515
 
1516
/*******************/
1517
/* FreeBSD Section */
1518
/*******************/
1519
 
1520
#elif defined (__FreeBSD__)
1521
 
1522
#include <signal.h>
1523
#include <unistd.h>
1524
 
1525
static void __gnat_error_handler (int, int, struct sigcontext *);
1526
 
1527
static void
1528
__gnat_error_handler (int sig, int code __attribute__ ((unused)),
1529
                      struct sigcontext *sc __attribute__ ((unused)))
1530
{
1531
  struct Exception_Data *exception;
1532
  const char *msg;
1533
 
1534
  switch (sig)
1535
    {
1536
    case SIGFPE:
1537
      exception = &constraint_error;
1538
      msg = "SIGFPE";
1539
      break;
1540
 
1541
    case SIGILL:
1542
      exception = &constraint_error;
1543
      msg = "SIGILL";
1544
      break;
1545
 
1546
    case SIGSEGV:
1547
      exception = &storage_error;
1548
      msg = "stack overflow or erroneous memory access";
1549
      break;
1550
 
1551
    case SIGBUS:
1552
      exception = &constraint_error;
1553
      msg = "SIGBUS";
1554
      break;
1555
 
1556
    default:
1557
      exception = &program_error;
1558
      msg = "unhandled signal";
1559
    }
1560
 
1561
  Raise_From_Signal_Handler (exception, msg);
1562
}
1563
 
1564
void
1565
__gnat_install_handler ()
1566
{
1567
  struct sigaction act;
1568
 
1569
  /* Set up signal handler to map synchronous signals to appropriate
1570
     exceptions.  Make sure that the handler isn't interrupted by another
1571
     signal that might cause a scheduling event! */
1572
 
1573
  act.sa_handler = __gnat_error_handler;
1574
  act.sa_flags = SA_NODEFER | SA_RESTART;
1575
  (void) sigemptyset (&act.sa_mask);
1576
 
1577
  (void) sigaction (SIGILL,  &act, NULL);
1578
  (void) sigaction (SIGFPE,  &act, NULL);
1579
  (void) sigaction (SIGSEGV, &act, NULL);
1580
  (void) sigaction (SIGBUS,  &act, NULL);
1581
 
1582
  __gnat_handler_installed = 1;
1583
}
1584
 
1585
/*******************/
1586
/* VxWorks Section */
1587
/*******************/
1588
 
1589
#elif defined(__vxworks)
1590
 
1591
#include <signal.h>
1592
#include <taskLib.h>
1593
 
1594
#ifndef __RTP__
1595
#include <intLib.h>
1596
#include <iv.h>
1597
#endif
1598
 
1599
#ifdef VTHREADS
1600
#include "private/vThreadsP.h"
1601
#endif
1602
 
1603
static void __gnat_error_handler (int, int, struct sigcontext *);
1604
void __gnat_map_signal (int);
1605
 
1606
#ifndef __RTP__
1607
 
1608
/* Directly vectored Interrupt routines are not supported when using RTPs */
1609
 
1610
extern int __gnat_inum_to_ivec (int);
1611
 
1612
/* This is needed by the GNAT run time to handle Vxworks interrupts */
1613
int
1614
__gnat_inum_to_ivec (int num)
1615
{
1616
  return INUM_TO_IVEC (num);
1617
}
1618
#endif
1619
 
1620
#if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1621
 
1622
/* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1623
   on Alpha VxWorks and VxWorks 6.x (including RTPs). */
1624
 
1625
extern long getpid (void);
1626
 
1627
long
1628
getpid (void)
1629
{
1630
  return taskIdSelf ();
1631
}
1632
#endif
1633
 
1634
/* VxWorks expects the field excCnt to be zeroed when a signal is handled.
1635
   The VxWorks version of longjmp does this; gcc's builtin_longjmp does not */
1636
void
1637
__gnat_clear_exception_count (void)
1638
{
1639
#ifdef VTHREADS
1640
  WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1641
 
1642
  currentTask->vThreads.excCnt = 0;
1643
#endif
1644
}
1645
 
1646
/* Exported to s-intman-vxworks.adb in order to handle different signal
1647
   to exception mappings in different VxWorks versions */
1648
void
1649
__gnat_map_signal (int sig)
1650
{
1651
  struct Exception_Data *exception;
1652
  const char *msg;
1653
 
1654
  switch (sig)
1655
    {
1656
    case SIGFPE:
1657
      exception = &constraint_error;
1658
      msg = "SIGFPE";
1659
      break;
1660
#ifdef VTHREADS
1661
    case SIGILL:
1662
      exception = &constraint_error;
1663
      msg = "Floating point exception or SIGILL";
1664
      break;
1665
    case SIGSEGV:
1666
      exception = &storage_error;
1667
      msg = "SIGSEGV: possible stack overflow";
1668
      break;
1669
    case SIGBUS:
1670
      exception = &storage_error;
1671
      msg = "SIGBUS: possible stack overflow";
1672
      break;
1673
#else
1674
    case SIGILL:
1675
      exception = &constraint_error;
1676
      msg = "SIGILL";
1677
      break;
1678
    case SIGSEGV:
1679
      exception = &program_error;
1680
      msg = "SIGSEGV";
1681
      break;
1682
    case SIGBUS:
1683
      exception = &program_error;
1684
      msg = "SIGBUS";
1685
      break;
1686
#endif
1687
    default:
1688
      exception = &program_error;
1689
      msg = "unhandled signal";
1690
    }
1691
 
1692
  __gnat_clear_exception_count ();
1693
  Raise_From_Signal_Handler (exception, msg);
1694
}
1695
 
1696
static void
1697
__gnat_error_handler (int sig, int code, struct sigcontext *sc)
1698
{
1699
  sigset_t mask;
1700
  int result;
1701
 
1702
  /* VxWorks will always mask out the signal during the signal handler and
1703
     will reenable it on a longjmp.  GNAT does not generate a longjmp to
1704
     return from a signal handler so the signal will still be masked unless
1705
     we unmask it. */
1706
  sigprocmask (SIG_SETMASK, NULL, &mask);
1707
  sigdelset (&mask, sig);
1708
  sigprocmask (SIG_SETMASK, &mask, NULL);
1709
 
1710
  __gnat_map_signal (sig);
1711
 
1712
}
1713
 
1714
void
1715
__gnat_install_handler (void)
1716
{
1717
  struct sigaction act;
1718
 
1719
  /* Setup signal handler to map synchronous signals to appropriate
1720
     exceptions.  Make sure that the handler isn't interrupted by another
1721
     signal that might cause a scheduling event! */
1722
 
1723
  act.sa_handler = __gnat_error_handler;
1724
  act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1725
  sigemptyset (&act.sa_mask);
1726
 
1727
  /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1728
     applies to vectored hardware interrupts, not signals */
1729
  sigaction (SIGFPE,  &act, NULL);
1730
  sigaction (SIGILL,  &act, NULL);
1731
  sigaction (SIGSEGV, &act, NULL);
1732
  sigaction (SIGBUS,  &act, NULL);
1733
 
1734
  __gnat_handler_installed = 1;
1735
}
1736
 
1737
#define HAVE_GNAT_INIT_FLOAT
1738
 
1739
void
1740
__gnat_init_float (void)
1741
{
1742
  /* Disable overflow/underflow exceptions on the PPC processor, this is needed
1743
     to get correct Ada semantics.  Note that for AE653 vThreads, the HW
1744
     overflow settings are an OS configuration issue.  The instructions
1745
     below have no effect */
1746
#if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1747
  asm ("mtfsb0 25");
1748
  asm ("mtfsb0 26");
1749
#endif
1750
 
1751
  /* Similarly for sparc64. Achieved by masking bits in the Trap Enable Mask
1752
     field of the Floating-point Status Register (see the Sparc Architecture
1753
     Manual Version 9, p 48).  */
1754
#if defined (sparc64)
1755
 
1756
#define FSR_TEM_NVM (1 << 27)  /* Invalid operand  */
1757
#define FSR_TEM_OFM (1 << 26)  /* Overflow  */
1758
#define FSR_TEM_UFM (1 << 25)  /* Underflow  */
1759
#define FSR_TEM_DZM (1 << 24)  /* Division by Zero  */
1760
#define FSR_TEM_NXM (1 << 23)  /* Inexact result  */
1761
  {
1762
    unsigned int fsr;
1763
 
1764
    __asm__("st %%fsr, %0" : "=m" (fsr));
1765
    fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
1766
    __asm__("ld %0, %%fsr" : : "m" (fsr));
1767
  }
1768
#endif
1769
}
1770
 
1771
/******************/
1772
/* NetBSD Section */
1773
/******************/
1774
 
1775
#elif defined(__NetBSD__)
1776
 
1777
#include <signal.h>
1778
#include <unistd.h>
1779
 
1780
static void
1781
__gnat_error_handler (int sig)
1782
{
1783
  struct Exception_Data *exception;
1784
  const char *msg;
1785
 
1786
  switch(sig)
1787
  {
1788
    case SIGFPE:
1789
      exception = &constraint_error;
1790
      msg = "SIGFPE";
1791
      break;
1792
    case SIGILL:
1793
      exception = &constraint_error;
1794
      msg = "SIGILL";
1795
      break;
1796
    case SIGSEGV:
1797
      exception = &storage_error;
1798
      msg = "stack overflow or erroneous memory access";
1799
      break;
1800
    case SIGBUS:
1801
      exception = &constraint_error;
1802
      msg = "SIGBUS";
1803
      break;
1804
    default:
1805
      exception = &program_error;
1806
      msg = "unhandled signal";
1807
    }
1808
 
1809
    Raise_From_Signal_Handler(exception, msg);
1810
}
1811
 
1812
void
1813
__gnat_install_handler(void)
1814
{
1815
  struct sigaction act;
1816
 
1817
  act.sa_handler = __gnat_error_handler;
1818
  act.sa_flags = SA_NODEFER | SA_RESTART;
1819
  sigemptyset (&act.sa_mask);
1820
 
1821
  /* Do not install handlers if interrupt state is "System" */
1822
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
1823
    sigaction (SIGFPE,  &act, NULL);
1824
  if (__gnat_get_interrupt_state (SIGILL) != 's')
1825
    sigaction (SIGILL,  &act, NULL);
1826
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1827
    sigaction (SIGSEGV, &act, NULL);
1828
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
1829
    sigaction (SIGBUS,  &act, NULL);
1830
 
1831
  __gnat_handler_installed = 1;
1832
}
1833
 
1834
#else
1835
 
1836
/* For all other versions of GNAT, the handler does nothing */
1837
 
1838
/*******************/
1839
/* Default Section */
1840
/*******************/
1841
 
1842
void
1843
__gnat_install_handler (void)
1844
{
1845
  __gnat_handler_installed = 1;
1846
}
1847
 
1848
#endif
1849
 
1850
/*********************/
1851
/* __gnat_init_float */
1852
/*********************/
1853
 
1854
/* This routine is called as each process thread is created, for possible
1855
   initialization of the FP processor. This version is used under INTERIX,
1856
   WIN32 and could be used under OS/2 */
1857
 
1858
#if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
1859
  || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__)
1860
 
1861
#define HAVE_GNAT_INIT_FLOAT
1862
 
1863
void
1864
__gnat_init_float (void)
1865
{
1866
#if defined (__i386__) || defined (i386)
1867
 
1868
  /* This is used to properly initialize the FPU on an x86 for each
1869
     process thread. */
1870
 
1871
  asm ("finit");
1872
 
1873
#endif  /* Defined __i386__ */
1874
}
1875
#endif
1876
 
1877
#ifndef HAVE_GNAT_INIT_FLOAT
1878
 
1879
/* All targets without a specific __gnat_init_float will use an empty one */
1880
void
1881
__gnat_init_float (void)
1882
{
1883
}
1884
#endif
1885
 
1886
/***********************************/
1887
/* __gnat_adjust_context_for_raise */
1888
/***********************************/
1889
 
1890
#ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1891
 
1892
/* All targets without a specific version will use an empty one */
1893
 
1894
/* UCONTEXT is a pointer to a context structure received by a signal handler
1895
   about to propagate an exception. Adjust it to compensate the fact that the
1896
   generic unwinder thinks the corresponding PC is a call return address.  */
1897
 
1898
void
1899
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
1900
                                 void *ucontext ATTRIBUTE_UNUSED)
1901
{
1902
  /* The point is that the interrupted context PC typically is the address
1903
     that we should search an EH region for, which is different from the call
1904
     return address case. The target independent part of the GCC unwinder
1905
     don't differentiate the two situations, so we compensate here for the
1906
     adjustments it will blindly make.
1907
 
1908
     signo is passed because on some targets for some signals the PC in
1909
     context points to the instruction after the faulting one, in which case
1910
     the unwinder adjustment is still desired.  */
1911
 
1912
  /* On a number of targets, we have arranged for the adjustment to be
1913
     performed by the MD_FALLBACK_FRAME_STATE circuitry, so we don't provide a
1914
     specific instance of this routine.  The MD_FALLBACK doesn't have access
1915
     to the signal number, though, so the compensation is systematic there and
1916
     might be wrong in some cases.  */
1917
 
1918
  /* Having the compensation wrong leads to potential failures.  A very
1919
     typical case is what happens when there is no compensation and a signal
1920
     triggers for the first instruction in a region : the unwinder adjustment
1921
     has it search in the wrong EH region.  */
1922
}
1923
 
1924
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.