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

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc1/] [gcc/] [ada/] [init.c] - Blame information for rev 513

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

Line No. Rev Author Line
1 281 jeremybenn
/****************************************************************************
2
 *                                                                          *
3
 *                         GNAT COMPILER COMPONENTS                         *
4
 *                                                                          *
5
 *                                 I N I T                                  *
6
 *                                                                          *
7
 *                          C Implementation File                           *
8
 *                                                                          *
9
 *          Copyright (C) 1992-2009, 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 3,  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.                                     *
17
 *                                                                          *
18
 * As a special exception under Section 7 of GPL version 3, you are granted *
19
 * additional permissions described in the GCC Runtime Library Exception,   *
20
 * version 3.1, as published by the Free Software Foundation.               *
21
 *                                                                          *
22
 * You should have received a copy of the GNU General Public License and    *
23
 * a copy of the GCC Runtime Library Exception along with this program;     *
24
 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
25
 * <http://www.gnu.org/licenses/>.                                          *
26
 *                                                                          *
27
 * GNAT was originally developed  by the GNAT team at  New York University. *
28
 * Extensive contributions were provided by Ada Core Technologies Inc.      *
29
 *                                                                          *
30
 ****************************************************************************/
31
 
32
/*  This unit contains initialization circuits that are system dependent.
33
    A major part of the functionality involves stack overflow checking.
34
    The GCC backend generates probe instructions to test for stack overflow.
35
    For details on the exact approach used to generate these probes, see the
36
    "Using and Porting GCC" manual, in particular the "Stack Checking" section
37
    and the subsection "Specifying How Stack Checking is Done".  The handlers
38
    installed by this file are used to catch the resulting signals that come
39
    from these probes failing (i.e. touching protected pages).  */
40
 
41
/* This file should be kept synchronized with 2sinit.ads, 2sinit.adb,
42
   s-init-ae653-cert.adb and s-init-xi-sparc.adb.  All these files implement
43
   the required functionality for different targets.  */
44
 
45
/* The following include is here to meet the published VxWorks requirement
46
   that the __vxworks header appear before any other include.  */
47
#ifdef __vxworks
48
#include "vxWorks.h"
49
#endif
50
 
51
#ifdef IN_RTS
52
#include "tconfig.h"
53
#include "tsystem.h"
54
#include <sys/stat.h>
55
 
56
/* We don't have libiberty, so use malloc.  */
57
#define xmalloc(S) malloc (S)
58
#else
59
#include "config.h"
60
#include "system.h"
61
#endif
62
 
63
#include "adaint.h"
64
#include "raise.h"
65
 
66
extern void __gnat_raise_program_error (const char *, int);
67
 
68
/* Addresses of exception data blocks for predefined exceptions.  Tasking_Error
69
   is not used in this unit, and the abort signal is only used on IRIX.  */
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
 
75
/* For the Cert run time we use the regular raise exception routine because
76
   Raise_From_Signal_Handler is not available.  */
77
#ifdef CERT
78
#define Raise_From_Signal_Handler \
79
                      __gnat_raise_exception
80
extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
81
#else
82
#define Raise_From_Signal_Handler \
83
                      ada__exceptions__raise_from_signal_handler
84
extern void Raise_From_Signal_Handler (struct Exception_Data *, const char *);
85
#endif
86
 
87
/* Global values computed by the binder.  */
88
int   __gl_main_priority                 = -1;
89
int   __gl_time_slice_val                = -1;
90
char  __gl_wc_encoding                   = 'n';
91
char  __gl_locking_policy                = ' ';
92
char  __gl_queuing_policy                = ' ';
93
char  __gl_task_dispatching_policy       = ' ';
94
char *__gl_priority_specific_dispatching = 0;
95
int   __gl_num_specific_dispatching      = 0;
96
char *__gl_interrupt_states              = 0;
97
int   __gl_num_interrupt_states          = 0;
98
int   __gl_unreserve_all_interrupts      = 0;
99
int   __gl_exception_tracebacks          = 0;
100
int   __gl_zero_cost_exceptions          = 0;
101
int   __gl_detect_blocking               = 0;
102
int   __gl_default_stack_size            = -1;
103
int   __gl_leap_seconds_support          = 0;
104
int   __gl_canonical_streams             = 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 then 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_get_specific_dispatching */
148
/***********************************/
149
 
150
char __gnat_get_specific_dispatching (int);
151
 
152
/* This routine is called from the runtime as needed to determine the
153
   priority specific dispatching policy, as set by a
154
   Priority_Specific_Dispatching pragma appearing anywhere in the current
155
   partition.  The input argument is the priority number, and the result
156
   is the upper case first character of the policy name, e.g. 'F' for
157
   FIFO_Within_Priorities. A space ' ' is returned if no
158
   Priority_Specific_Dispatching pragma is used in the partition.  */
159
 
160
char
161
__gnat_get_specific_dispatching (int priority)
162
{
163
  if (__gl_num_specific_dispatching == 0)
164
    return ' ';
165
  else if (priority >= __gl_num_specific_dispatching)
166
    return 'F';
167
  else
168
    return __gl_priority_specific_dispatching [priority];
169
}
170
 
171
#ifndef IN_RTS
172
 
173
/**********************/
174
/* __gnat_set_globals */
175
/**********************/
176
 
177
/* This routine is kept for bootstrapping purposes, since the binder generated
178
   file now sets the __gl_* variables directly.  */
179
 
180
void
181
__gnat_set_globals (void)
182
{
183
}
184
 
185
#endif
186
 
187
/***************/
188
/* AIX Section */
189
/***************/
190
 
191
#if defined (_AIX)
192
 
193
#include <signal.h>
194
#include <sys/time.h>
195
 
196
/* Some versions of AIX don't define SA_NODEFER.  */
197
 
198
#ifndef SA_NODEFER
199
#define SA_NODEFER 0
200
#endif /* SA_NODEFER */
201
 
202
/* Versions of AIX before 4.3 don't have nanosleep but provide
203
   nsleep instead.  */
204
 
205
#ifndef _AIXVERSION_430
206
 
207
extern int nanosleep (struct timestruc_t *, struct timestruc_t *);
208
 
209
int
210
nanosleep (struct timestruc_t *Rqtp, struct timestruc_t *Rmtp)
211
{
212
  return nsleep (Rqtp, Rmtp);
213
}
214
 
215
#endif /* _AIXVERSION_430 */
216
 
217
static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
218
 
219
static void
220
__gnat_error_handler (int sig,
221
                      siginfo_t * si ATTRIBUTE_UNUSED,
222
                      void * uc ATTRIBUTE_UNUSED)
223
{
224
  struct Exception_Data *exception;
225
  const char *msg;
226
 
227
  switch (sig)
228
    {
229
    case SIGSEGV:
230
      /* FIXME: we need to detect the case of a *real* SIGSEGV.  */
231
      exception = &storage_error;
232
      msg = "stack overflow or erroneous memory access";
233
      break;
234
 
235
    case SIGBUS:
236
      exception = &constraint_error;
237
      msg = "SIGBUS";
238
      break;
239
 
240
    case SIGFPE:
241
      exception = &constraint_error;
242
      msg = "SIGFPE";
243
      break;
244
 
245
    default:
246
      exception = &program_error;
247
      msg = "unhandled signal";
248
    }
249
 
250
  Raise_From_Signal_Handler (exception, msg);
251
}
252
 
253
void
254
__gnat_install_handler (void)
255
{
256
  struct sigaction act;
257
 
258
  /* Set up signal handler to map synchronous signals to appropriate
259
     exceptions.  Make sure that the handler isn't interrupted by another
260
     signal that might cause a scheduling event!  */
261
 
262
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
263
  act.sa_sigaction = __gnat_error_handler;
264
  sigemptyset (&act.sa_mask);
265
 
266
  /* Do not install handlers if interrupt state is "System".  */
267
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
268
    sigaction (SIGABRT, &act, NULL);
269
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
270
    sigaction (SIGFPE,  &act, NULL);
271
  if (__gnat_get_interrupt_state (SIGILL) != 's')
272
    sigaction (SIGILL,  &act, NULL);
273
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
274
    sigaction (SIGSEGV, &act, NULL);
275
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
276
    sigaction (SIGBUS,  &act, NULL);
277
 
278
  __gnat_handler_installed = 1;
279
}
280
 
281
/*****************/
282
/* Tru64 section */
283
/*****************/
284
 
285
#elif defined(__alpha__) && defined(__osf__)
286
 
287
#include <signal.h>
288
#include <sys/siginfo.h>
289
 
290
static void __gnat_error_handler (int, siginfo_t *, struct sigcontext *);
291
extern char *__gnat_get_code_loc (struct sigcontext *);
292
extern void __gnat_set_code_loc (struct sigcontext *, char *);
293
extern size_t __gnat_machine_state_length (void);
294
 
295
#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
296
 
297
void
298
__gnat_adjust_context_for_raise (int signo, void *ucontext)
299
{
300
  struct sigcontext *sigcontext = (struct sigcontext *) ucontext;
301
 
302
  /* The unwinder expects the signal context to contain the address of the
303
     faulting instruction.  For SIGFPE, this depends on the trap shadow
304
     situation (see man ieee).  We nonetheless always compensate for it,
305
     considering that PC designates the instruction following the one that
306
     trapped.  This is not necessarily true but corresponds to what we have
307
     always observed.  */
308
  if (signo == SIGFPE)
309
    sigcontext->sc_pc--;
310
}
311
 
312
static void
313
__gnat_error_handler (int sig, siginfo_t *sip, struct sigcontext *context)
314
{
315
  struct Exception_Data *exception;
316
  static int recurse = 0;
317
  const char *msg;
318
 
319
  /* Adjusting is required for every fault context, so adjust for this one
320
     now, before we possibly trigger a recursive fault below.  */
321
  __gnat_adjust_context_for_raise (sig, context);
322
 
323
  /* If this was an explicit signal from a "kill", just resignal it.  */
324
  if (SI_FROMUSER (sip))
325
    {
326
      signal (sig, SIG_DFL);
327
      kill (getpid(), sig);
328
    }
329
 
330
  /* Otherwise, treat it as something we handle.  */
331
  switch (sig)
332
    {
333
    case SIGSEGV:
334
      /* If the problem was permissions, this is a constraint error.
335
         Likewise if the failing address isn't maximally aligned or if
336
         we've recursed.
337
 
338
         ??? Using a static variable here isn't task-safe, but it's
339
         much too hard to do anything else and we're just determining
340
         which exception to raise.  */
341
      if (sip->si_code == SEGV_ACCERR
342
          || (((long) sip->si_addr) & 3) != 0
343
          || recurse)
344
        {
345
          exception = &constraint_error;
346
          msg = "SIGSEGV";
347
        }
348
      else
349
        {
350
          /* See if the page before the faulting page is accessible.  Do that
351
             by trying to access it.  We'd like to simply try to access
352
             4096 + the faulting address, but it's not guaranteed to be
353
             the actual address, just to be on the same page.  */
354
          recurse++;
355
          ((volatile char *)
356
           ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
357
          msg = "stack overflow (or erroneous memory access)";
358
          exception = &storage_error;
359
        }
360
      break;
361
 
362
    case SIGBUS:
363
      exception = &program_error;
364
      msg = "SIGBUS";
365
      break;
366
 
367
    case SIGFPE:
368
      exception = &constraint_error;
369
      msg = "SIGFPE";
370
      break;
371
 
372
    default:
373
      exception = &program_error;
374
      msg = "unhandled signal";
375
    }
376
 
377
  recurse = 0;
378
  Raise_From_Signal_Handler (exception, (const char *) msg);
379
}
380
 
381
void
382
__gnat_install_handler (void)
383
{
384
  struct sigaction act;
385
 
386
  /* Setup signal handler to map synchronous signals to appropriate
387
     exceptions. Make sure that the handler isn't interrupted by another
388
     signal that might cause a scheduling event!  */
389
 
390
  act.sa_handler = (void (*) (int)) __gnat_error_handler;
391
  act.sa_flags = SA_RESTART | SA_NODEFER | SA_SIGINFO;
392
  sigemptyset (&act.sa_mask);
393
 
394
  /* Do not install handlers if interrupt state is "System".  */
395
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
396
    sigaction (SIGABRT, &act, NULL);
397
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
398
    sigaction (SIGFPE,  &act, NULL);
399
  if (__gnat_get_interrupt_state (SIGILL) != 's')
400
    sigaction (SIGILL,  &act, NULL);
401
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
402
    sigaction (SIGSEGV, &act, NULL);
403
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
404
    sigaction (SIGBUS,  &act, NULL);
405
 
406
  __gnat_handler_installed = 1;
407
}
408
 
409
/* Routines called by s-mastop-tru64.adb.  */
410
 
411
#define SC_GP 29
412
 
413
char *
414
__gnat_get_code_loc (struct sigcontext *context)
415
{
416
  return (char *) context->sc_pc;
417
}
418
 
419
void
420
__gnat_set_code_loc (struct sigcontext *context, char *pc)
421
{
422
  context->sc_pc = (long) pc;
423
}
424
 
425
size_t
426
__gnat_machine_state_length (void)
427
{
428
  return sizeof (struct sigcontext);
429
}
430
 
431
/*****************/
432
/* HP-UX section */
433
/*****************/
434
 
435
#elif defined (__hpux__)
436
 
437
#include <signal.h>
438
#include <sys/ucontext.h>
439
 
440
static void
441
__gnat_error_handler (int sig, siginfo_t *siginfo, void *ucontext);
442
 
443
static void
444
__gnat_error_handler
445
  (int sig,
446
   siginfo_t *siginfo ATTRIBUTE_UNUSED,
447
   void *ucontext ATTRIBUTE_UNUSED)
448
{
449
  struct Exception_Data *exception;
450
  const char *msg;
451
 
452
  switch (sig)
453
    {
454
    case SIGSEGV:
455
      /* FIXME: we need to detect the case of a *real* SIGSEGV.  */
456
      exception = &storage_error;
457
      msg = "stack overflow or erroneous memory access";
458
      break;
459
 
460
    case SIGBUS:
461
      exception = &constraint_error;
462
      msg = "SIGBUS";
463
      break;
464
 
465
    case SIGFPE:
466
      exception = &constraint_error;
467
      msg = "SIGFPE";
468
      break;
469
 
470
    default:
471
      exception = &program_error;
472
      msg = "unhandled signal";
473
    }
474
 
475
  Raise_From_Signal_Handler (exception, msg);
476
}
477
 
478
/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
479
#if defined (__hppa__)
480
char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
481
#else
482
char __gnat_alternate_stack[128 * 1024]; /* MINSIGSTKSZ */
483
#endif
484
 
485
void
486
__gnat_install_handler (void)
487
{
488
  struct sigaction act;
489
 
490
  /* Set up signal handler to map synchronous signals to appropriate
491
     exceptions.  Make sure that the handler isn't interrupted by another
492
     signal that might cause a scheduling event!  Also setup an alternate
493
     stack region for the handler execution so that stack overflows can be
494
     handled properly, avoiding a SEGV generation from stack usage by the
495
     handler itself.  */
496
 
497
  stack_t stack;
498
  stack.ss_sp = __gnat_alternate_stack;
499
  stack.ss_size = sizeof (__gnat_alternate_stack);
500
  stack.ss_flags = 0;
501
  sigaltstack (&stack, NULL);
502
 
503
  act.sa_sigaction = __gnat_error_handler;
504
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
505
  sigemptyset (&act.sa_mask);
506
 
507
  /* Do not install handlers if interrupt state is "System".  */
508
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
509
    sigaction (SIGABRT, &act, NULL);
510
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
511
    sigaction (SIGFPE,  &act, NULL);
512
  if (__gnat_get_interrupt_state (SIGILL) != 's')
513
    sigaction (SIGILL,  &act, NULL);
514
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
515
    sigaction (SIGBUS,  &act, NULL);
516
  act.sa_flags |= SA_ONSTACK;
517
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
518
    sigaction (SIGSEGV, &act, NULL);
519
 
520
  __gnat_handler_installed = 1;
521
}
522
 
523
/*********************/
524
/* GNU/Linux Section */
525
/*********************/
526
 
527
#elif defined (linux)
528
 
529
#include <signal.h>
530
 
531
#define __USE_GNU 1 /* required to get REG_EIP/RIP from glibc's ucontext.h */
532
#include <sys/ucontext.h>
533
 
534
/* GNU/Linux, which uses glibc, does not define NULL in included
535
   header files.  */
536
 
537
#if !defined (NULL)
538
#define NULL ((void *) 0)
539
#endif
540
 
541
#if defined (MaRTE)
542
 
543
/* MaRTE OS provides its own version of sigaction, sigfillset, and
544
   sigemptyset (overriding these symbol names).  We want to make sure that
545
   the versions provided by the underlying C library are used here (these
546
   versions are renamed by MaRTE to linux_sigaction, fake_linux_sigfillset,
547
   and fake_linux_sigemptyset, respectively).  The MaRTE library will not
548
   always be present (it will not be linked if no tasking constructs are
549
   used), so we use the weak symbol mechanism to point always to the symbols
550
   defined within the C library.  */
551
 
552
#pragma weak linux_sigaction
553
int linux_sigaction (int signum, const struct sigaction *act,
554
                     struct sigaction *oldact) {
555
  return sigaction (signum, act, oldact);
556
}
557
#define sigaction(signum, act, oldact) linux_sigaction (signum, act, oldact)
558
 
559
#pragma weak fake_linux_sigfillset
560
void fake_linux_sigfillset (sigset_t *set) {
561
  sigfillset (set);
562
}
563
#define sigfillset(set) fake_linux_sigfillset (set)
564
 
565
#pragma weak fake_linux_sigemptyset
566
void fake_linux_sigemptyset (sigset_t *set) {
567
  sigemptyset (set);
568
}
569
#define sigemptyset(set) fake_linux_sigemptyset (set)
570
 
571
#endif
572
 
573
static void __gnat_error_handler (int, siginfo_t *siginfo, void *ucontext);
574
 
575
#if defined (i386) || defined (__x86_64__) || defined (__ia64__)
576
 
577
#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
578
 
579
void
580
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
581
{
582
  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
583
 
584
  /* On the i386 and x86-64 architectures, we specifically detect calls to
585
     the null address and entirely fold the not-yet-fully-established frame
586
     to prevent it from stopping the unwinding.
587
 
588
     On the i386 and x86-64 architectures, stack checking is performed by
589
     means of probes with moving stack pointer, that is to say the probed
590
     address is always the value of the stack pointer.  Upon hitting the
591
     guard page, the stack pointer therefore points to an inaccessible
592
     address and an alternate signal stack is needed to run the handler.
593
     But there is an additional twist: on these architectures, the EH
594
     return code writes the address of the handler at the target CFA's
595
     value on the stack before doing the jump.  As a consequence, if
596
     there is an active handler in the frame whose stack has overflowed,
597
     the stack pointer must nevertheless point to an accessible address
598
     by the time the EH return is executed.
599
 
600
     We therefore adjust the saved value of the stack pointer by the size
601
     of one page + a small dope of 4 words, in order to make sure that it
602
     points to an accessible address in case it's used as the target CFA.
603
     The stack checking code guarantees that this address is unused by the
604
     time this happens.  */
605
 
606
#if defined (i386)
607
  unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
608
  /* The call insn pushes the return address onto the stack.  Pop it.  */
609
  if (pc == NULL)
610
    {
611
      mcontext->gregs[REG_EIP] = *(unsigned long *)mcontext->gregs[REG_ESP];
612
      mcontext->gregs[REG_ESP] += 4;
613
    }
614
  /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode.  */
615
  else if (signo == SIGSEGV && *pc == 0x00240c83)
616
    mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
617
#elif defined (__x86_64__)
618
  unsigned long *pc = (unsigned long *)mcontext->gregs[REG_RIP];
619
  /* The call insn pushes the return address onto the stack.  Pop it.  */
620
  if (pc == NULL)
621
    {
622
      mcontext->gregs[REG_RIP] = *(unsigned long *)mcontext->gregs[REG_RSP];
623
      mcontext->gregs[REG_RSP] += 8;
624
    }
625
  /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode.  */
626
  else if (signo == SIGSEGV && (*pc & 0xffffffffff) == 0x00240c8348)
627
    mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
628
#elif defined (__ia64__)
629
  /* ??? The IA-64 unwinder doesn't compensate for signals.  */
630
  mcontext->sc_ip++;
631
#endif
632
}
633
 
634
#endif
635
 
636
static void
637
__gnat_error_handler (int sig,
638
                      siginfo_t *siginfo ATTRIBUTE_UNUSED,
639
                      void *ucontext)
640
{
641
  struct Exception_Data *exception;
642
  static int recurse = 0;
643
  const char *msg;
644
 
645
  /* Adjusting is required for every fault context, so adjust for this one
646
     now, before we possibly trigger a recursive fault below.  */
647
  __gnat_adjust_context_for_raise (sig, ucontext);
648
 
649
  switch (sig)
650
    {
651
    case SIGSEGV:
652
      /* If the problem was permissions, this is a constraint error.
653
       Likewise if the failing address isn't maximally aligned or if
654
       we've recursed.
655
 
656
       ??? Using a static variable here isn't task-safe, but it's
657
       much too hard to do anything else and we're just determining
658
       which exception to raise.  */
659
      if (recurse)
660
      {
661
        exception = &constraint_error;
662
        msg = "SIGSEGV";
663
      }
664
      else
665
      {
666
        /* Here we would like a discrimination test to see whether the
667
           page before the faulting address is accessible. Unfortunately
668
           Linux seems to have no way of giving us the faulting address.
669
 
670
           In versions of a-init.c before 1.95, we had a test of the page
671
           before the stack pointer using:
672
 
673
            recurse++;
674
             ((volatile char *)
675
              ((long) info->esp_at_signal & - getpagesize ()))[getpagesize ()];
676
 
677
           but that's wrong, since it tests the stack pointer location, and
678
           the current stack probe code does not move the stack pointer
679
           until all probes succeed.
680
 
681
           For now we simply do not attempt any discrimination at all. Note
682
           that this is quite acceptable, since a "real" SIGSEGV can only
683
           occur as the result of an erroneous program.  */
684
 
685
        msg = "stack overflow (or erroneous memory access)";
686
        exception = &storage_error;
687
      }
688
      break;
689
 
690
    case SIGBUS:
691
      exception = &constraint_error;
692
      msg = "SIGBUS";
693
      break;
694
 
695
    case SIGFPE:
696
      exception = &constraint_error;
697
      msg = "SIGFPE";
698
      break;
699
 
700
    default:
701
      exception = &program_error;
702
      msg = "unhandled signal";
703
    }
704
 
705
  recurse = 0;
706
  Raise_From_Signal_Handler (exception, msg);
707
}
708
 
709
#if defined (i386) || defined (__x86_64__)
710
/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
711
char __gnat_alternate_stack[16 * 1024]; /* 2 * SIGSTKSZ */
712
#endif
713
 
714
#ifdef __XENO__
715
#include <sys/mman.h>
716
#include <native/task.h>
717
 
718
RT_TASK main_task;
719
#endif
720
 
721
void
722
__gnat_install_handler (void)
723
{
724
  struct sigaction act;
725
 
726
#ifdef __XENO__
727
  int prio;
728
 
729
  if (__gl_main_priority == -1)
730
    prio = 49;
731
  else
732
    prio = __gl_main_priority;
733
 
734
  /* Avoid memory swapping for this program */
735
 
736
  mlockall (MCL_CURRENT|MCL_FUTURE);
737
 
738
  /* Turn the current Linux task into a native Xenomai task */
739
 
740
  rt_task_shadow(&main_task, "environment_task", prio, T_FPU);
741
#endif
742
 
743
  /* Set up signal handler to map synchronous signals to appropriate
744
     exceptions.  Make sure that the handler isn't interrupted by another
745
     signal that might cause a scheduling event!  Also setup an alternate
746
     stack region for the handler execution so that stack overflows can be
747
     handled properly, avoiding a SEGV generation from stack usage by the
748
     handler itself.  */
749
 
750
#if defined (i386) || defined (__x86_64__)
751
  stack_t stack;
752
  stack.ss_sp = __gnat_alternate_stack;
753
  stack.ss_size = sizeof (__gnat_alternate_stack);
754
  stack.ss_flags = 0;
755
  sigaltstack (&stack, NULL);
756
#endif
757
 
758
  act.sa_sigaction = __gnat_error_handler;
759
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
760
  sigemptyset (&act.sa_mask);
761
 
762
  /* Do not install handlers if interrupt state is "System".  */
763
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
764
    sigaction (SIGABRT, &act, NULL);
765
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
766
    sigaction (SIGFPE,  &act, NULL);
767
  if (__gnat_get_interrupt_state (SIGILL) != 's')
768
    sigaction (SIGILL,  &act, NULL);
769
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
770
    sigaction (SIGBUS,  &act, NULL);
771
#if defined (i386) || defined (__x86_64__)
772
  act.sa_flags |= SA_ONSTACK;
773
#endif
774
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
775
    sigaction (SIGSEGV, &act, NULL);
776
 
777
  __gnat_handler_installed = 1;
778
}
779
 
780
/****************/
781
/* IRIX Section */
782
/****************/
783
 
784
#elif defined (sgi)
785
 
786
#include <signal.h>
787
#include <siginfo.h>
788
 
789
#ifndef NULL
790
#define NULL 0
791
#endif
792
 
793
#define SIGADAABORT 48
794
#define SIGNAL_STACK_SIZE 4096
795
#define SIGNAL_STACK_ALIGNMENT 64
796
 
797
#define Check_Abort_Status     \
798
                      system__soft_links__check_abort_status
799
extern int (*Check_Abort_Status) (void);
800
 
801
extern struct Exception_Data _abort_signal;
802
 
803
static void __gnat_error_handler (int, int, sigcontext_t *);
804
 
805
/* We are not setting the SA_SIGINFO bit in the sigaction flags when
806
   connecting that handler, with the effects described in the sigaction
807
   man page:
808
 
809
          SA_SIGINFO [...]
810
          If cleared and the signal is caught, the first argument is
811
          also the signal number but the second argument is the signal
812
          code identifying the cause of the signal. The third argument
813
          points to a sigcontext_t structure containing the receiving
814
          process's context when the signal was delivered.  */
815
 
816
static void
817
__gnat_error_handler (int sig, int code, sigcontext_t *sc ATTRIBUTE_UNUSED)
818
{
819
  struct Exception_Data *exception;
820
  const char *msg;
821
 
822
  switch (sig)
823
    {
824
    case SIGSEGV:
825
      if (code == EFAULT)
826
        {
827
          exception = &program_error;
828
          msg = "SIGSEGV: (Invalid virtual address)";
829
        }
830
      else if (code == ENXIO)
831
        {
832
          exception = &program_error;
833
          msg = "SIGSEGV: (Read beyond mapped object)";
834
        }
835
      else if (code == ENOSPC)
836
        {
837
          exception = &program_error; /* ??? storage_error ??? */
838
          msg = "SIGSEGV: (Autogrow for file failed)";
839
        }
840
      else if (code == EACCES || code == EEXIST)
841
        {
842
          /* ??? We handle stack overflows here, some of which do trigger
843
                 SIGSEGV + EEXIST on Irix 6.5 although EEXIST is not part of
844
                 the documented valid codes for SEGV in the signal(5) man
845
                 page.  */
846
 
847
          /* ??? Re-add smarts to further verify that we launched
848
                 the stack into a guard page, not an attempt to
849
                 write to .text or something.  */
850
          exception = &storage_error;
851
          msg = "SIGSEGV: (stack overflow or erroneous memory access)";
852
        }
853
      else
854
        {
855
          /* Just in case the OS guys did it to us again.  Sometimes
856
             they fail to document all of the valid codes that are
857
             passed to signal handlers, just in case someone depends
858
             on knowing all the codes.  */
859
          exception = &program_error;
860
          msg = "SIGSEGV: (Undocumented reason)";
861
        }
862
      break;
863
 
864
    case SIGBUS:
865
      /* Map all bus errors to Program_Error.  */
866
      exception = &program_error;
867
      msg = "SIGBUS";
868
      break;
869
 
870
    case SIGFPE:
871
      /* Map all fpe errors to Constraint_Error.  */
872
      exception = &constraint_error;
873
      msg = "SIGFPE";
874
      break;
875
 
876
    case SIGADAABORT:
877
      if ((*Check_Abort_Status) ())
878
        {
879
          exception = &_abort_signal;
880
          msg = "";
881
        }
882
      else
883
        return;
884
 
885
      break;
886
 
887
    default:
888
      /* Everything else is a Program_Error.  */
889
      exception = &program_error;
890
      msg = "unhandled signal";
891
    }
892
 
893
  Raise_From_Signal_Handler (exception, msg);
894
}
895
 
896
void
897
__gnat_install_handler (void)
898
{
899
  struct sigaction act;
900
 
901
  /* Setup signal handler to map synchronous signals to appropriate
902
     exceptions.  Make sure that the handler isn't interrupted by another
903
     signal that might cause a scheduling event!  */
904
 
905
  act.sa_handler = __gnat_error_handler;
906
  act.sa_flags = SA_NODEFER + SA_RESTART;
907
  sigfillset (&act.sa_mask);
908
  sigemptyset (&act.sa_mask);
909
 
910
  /* Do not install handlers if interrupt state is "System".  */
911
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
912
    sigaction (SIGABRT, &act, NULL);
913
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
914
    sigaction (SIGFPE,  &act, NULL);
915
  if (__gnat_get_interrupt_state (SIGILL) != 's')
916
    sigaction (SIGILL,  &act, NULL);
917
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
918
    sigaction (SIGSEGV, &act, NULL);
919
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
920
    sigaction (SIGBUS,  &act, NULL);
921
  if (__gnat_get_interrupt_state (SIGADAABORT) != 's')
922
    sigaction (SIGADAABORT,  &act, NULL);
923
 
924
  __gnat_handler_installed = 1;
925
}
926
 
927
/*******************/
928
/* LynxOS Section */
929
/*******************/
930
 
931
#elif defined (__Lynx__)
932
 
933
#include <signal.h>
934
#include <unistd.h>
935
 
936
static void
937
__gnat_error_handler (int sig)
938
{
939
  struct Exception_Data *exception;
940
  const char *msg;
941
 
942
  switch(sig)
943
  {
944
    case SIGFPE:
945
      exception = &constraint_error;
946
      msg = "SIGFPE";
947
      break;
948
    case SIGILL:
949
      exception = &constraint_error;
950
      msg = "SIGILL";
951
      break;
952
    case SIGSEGV:
953
      exception = &storage_error;
954
      msg = "stack overflow or erroneous memory access";
955
      break;
956
    case SIGBUS:
957
      exception = &constraint_error;
958
      msg = "SIGBUS";
959
      break;
960
    default:
961
      exception = &program_error;
962
      msg = "unhandled signal";
963
    }
964
 
965
    Raise_From_Signal_Handler(exception, msg);
966
}
967
 
968
void
969
__gnat_install_handler(void)
970
{
971
  struct sigaction act;
972
 
973
  act.sa_handler = __gnat_error_handler;
974
  act.sa_flags = 0x0;
975
  sigemptyset (&act.sa_mask);
976
 
977
  /* Do not install handlers if interrupt state is "System".  */
978
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
979
    sigaction (SIGFPE,  &act, NULL);
980
  if (__gnat_get_interrupt_state (SIGILL) != 's')
981
    sigaction (SIGILL,  &act, NULL);
982
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
983
    sigaction (SIGSEGV, &act, NULL);
984
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
985
    sigaction (SIGBUS,  &act, NULL);
986
 
987
  __gnat_handler_installed = 1;
988
}
989
 
990
/*******************/
991
/* Solaris Section */
992
/*******************/
993
 
994
#elif defined (sun) && defined (__SVR4) && !defined (__vxworks)
995
 
996
#include <signal.h>
997
#include <siginfo.h>
998
#include <sys/ucontext.h>
999
#include <sys/regset.h>
1000
 
1001
/* The code below is common to SPARC and x86.  Beware of the delay slot
1002
   differences for signal context adjustments.  */
1003
 
1004
#if defined (__sparc)
1005
#define RETURN_ADDR_OFFSET 8
1006
#else
1007
#define RETURN_ADDR_OFFSET 0
1008
#endif
1009
 
1010
/* Likewise regarding how the "instruction pointer" register slot can
1011
   be identified in signal machine contexts.  We have either "REG_PC"
1012
   or "PC" at hand, depending on the target CPU and Solaris version.  */
1013
#if !defined (REG_PC)
1014
#define REG_PC PC
1015
#endif
1016
 
1017
static void __gnat_error_handler (int, siginfo_t *, void *);
1018
 
1019
#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1020
 
1021
void
1022
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1023
{
1024
  mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
1025
  unsigned long *pc = (unsigned long *)mcontext->gregs[REG_PC];
1026
 
1027
  /* We specifically detect calls to the null address and entirely fold
1028
     the not-yet-fully-established frame to prevent it from stopping the
1029
     unwinding.  */
1030
  if (pc == NULL)
1031
#if defined (__sparc)
1032
    /* The call insn moves the return address into %o7.  Move it back.  */
1033
    mcontext->gregs[REG_PC] = mcontext->gregs[REG_O7];
1034
#elif defined (i386)
1035
    {
1036
      /* The call insn pushes the return address onto the stack.  Pop it.  */
1037
      mcontext->gregs[REG_PC] = *(unsigned long *)mcontext->gregs[UESP];
1038
      mcontext->gregs[UESP] += 4;
1039
    }
1040
#elif defined (__x86_64__)
1041
    {
1042
      /* The call insn pushes the return address onto the stack.  Pop it.  */
1043
      mcontext->gregs[REG_PC] = *(unsigned long *)mcontext->gregs[REG_RSP];
1044
      mcontext->gregs[REG_RSP] += 8;
1045
    }
1046
#else
1047
#error architecture not supported on Solaris
1048
#endif
1049
}
1050
 
1051
static void
1052
__gnat_error_handler (int sig, siginfo_t *sip, void *ucontext)
1053
{
1054
  struct Exception_Data *exception;
1055
  static int recurse = 0;
1056
  const char *msg;
1057
 
1058
  /* Adjusting is required for every fault context, so adjust for this one
1059
     now, before we possibly trigger a recursive fault below.  */
1060
  __gnat_adjust_context_for_raise (sig, ucontext);
1061
 
1062
  switch (sig)
1063
    {
1064
    case SIGSEGV:
1065
      /* If the problem was permissions, this is a constraint error.
1066
         Likewise if the failing address isn't maximally aligned or if
1067
         we've recursed.
1068
 
1069
         ??? Using a static variable here isn't task-safe, but it's
1070
         much too hard to do anything else and we're just determining
1071
         which exception to raise.  */
1072
      if (sip->si_code == SEGV_ACCERR
1073
          || (long) sip->si_addr == 0
1074
          || (((long) sip->si_addr) & 3) != 0
1075
          || recurse)
1076
        {
1077
          exception = &constraint_error;
1078
          msg = "SIGSEGV";
1079
        }
1080
      else
1081
        {
1082
          /* See if the page before the faulting page is accessible.  Do that
1083
             by trying to access it.  We'd like to simply try to access
1084
             4096 + the faulting address, but it's not guaranteed to be
1085
             the actual address, just to be on the same page.  */
1086
          recurse++;
1087
          ((volatile char *)
1088
           ((long) sip->si_addr & - getpagesize ()))[getpagesize ()];
1089
          exception = &storage_error;
1090
          msg = "stack overflow (or erroneous memory access)";
1091
        }
1092
      break;
1093
 
1094
    case SIGBUS:
1095
      exception = &program_error;
1096
      msg = "SIGBUS";
1097
      break;
1098
 
1099
    case SIGFPE:
1100
      exception = &constraint_error;
1101
      msg = "SIGFPE";
1102
      break;
1103
 
1104
    default:
1105
      exception = &program_error;
1106
      msg = "unhandled signal";
1107
    }
1108
 
1109
  recurse = 0;
1110
  Raise_From_Signal_Handler (exception, msg);
1111
}
1112
 
1113
void
1114
__gnat_install_handler (void)
1115
{
1116
  struct sigaction act;
1117
 
1118
  /* Set up signal handler to map synchronous signals to appropriate
1119
     exceptions.  Make sure that the handler isn't interrupted by another
1120
     signal that might cause a scheduling event!  */
1121
 
1122
  act.sa_handler = __gnat_error_handler;
1123
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1124
  sigemptyset (&act.sa_mask);
1125
 
1126
  /* Do not install handlers if interrupt state is "System".  */
1127
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
1128
    sigaction (SIGABRT, &act, NULL);
1129
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
1130
    sigaction (SIGFPE,  &act, NULL);
1131
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
1132
    sigaction (SIGSEGV, &act, NULL);
1133
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
1134
    sigaction (SIGBUS,  &act, NULL);
1135
 
1136
  __gnat_handler_installed = 1;
1137
}
1138
 
1139
/***************/
1140
/* VMS Section */
1141
/***************/
1142
 
1143
#elif defined (VMS)
1144
 
1145
/* Routine called from binder to override default feature values. */
1146
void __gnat_set_features ();
1147
int __gnat_features_set = 0;
1148
 
1149
long __gnat_error_handler (int *, void *);
1150
 
1151
#ifdef __IA64
1152
#define lib_get_curr_invo_context LIB$I64_GET_CURR_INVO_CONTEXT
1153
#define lib_get_prev_invo_context LIB$I64_GET_PREV_INVO_CONTEXT
1154
#define lib_get_invo_handle LIB$I64_GET_INVO_HANDLE
1155
#else
1156
#define lib_get_curr_invo_context LIB$GET_CURR_INVO_CONTEXT
1157
#define lib_get_prev_invo_context LIB$GET_PREV_INVO_CONTEXT
1158
#define lib_get_invo_handle LIB$GET_INVO_HANDLE
1159
#endif
1160
 
1161
#if defined (IN_RTS) && !defined (__IA64)
1162
 
1163
/* The prehandler actually gets control first on a condition.  It swaps the
1164
   stack pointer and calls the handler (__gnat_error_handler).  */
1165
extern long __gnat_error_prehandler (void);
1166
 
1167
extern char *__gnat_error_prehandler_stack;   /* Alternate signal stack */
1168
#endif
1169
 
1170
/* Define macro symbols for the VMS conditions that become Ada exceptions.
1171
   Most of these are also defined in the header file ssdef.h which has not
1172
   yet been converted to be recognized by GNU C.  */
1173
 
1174
/* Defining these as macros, as opposed to external addresses, allows
1175
   them to be used in a case statement below.  */
1176
#define SS$_ACCVIO            12
1177
#define SS$_HPARITH         1284
1178
#define SS$_STKOVF          1364
1179
#define SS$_RESIGNAL        2328
1180
 
1181
/* These codes are in standard message libraries.  */
1182
extern int C$_SIGKILL;
1183
extern int CMA$_EXIT_THREAD;
1184
extern int SS$_DEBUG;
1185
extern int SS$_INTDIV;
1186
extern int LIB$_KEYNOTFOU;
1187
extern int LIB$_ACTIMAGE;
1188
extern int MTH$_FLOOVEMAT;       /* Some ACVC_21 CXA tests */
1189
 
1190
/* These codes are non standard, which is to say the author is
1191
   not sure if they are defined in the standard message libraries
1192
   so keep them as macros for now.  */
1193
#define RDB$_STREAM_EOF 20480426
1194
#define FDL$_UNPRIKW 11829410
1195
 
1196
struct cond_except {
1197
  const int *cond;
1198
  const struct Exception_Data *except;
1199
};
1200
 
1201
struct descriptor_s {unsigned short len, mbz; __char_ptr32 adr; };
1202
 
1203
/* Conditions that don't have an Ada exception counterpart must raise
1204
   Non_Ada_Error.  Since this is defined in s-auxdec, it should only be
1205
   referenced by user programs, not the compiler or tools.  Hence the
1206
   #ifdef IN_RTS.  */
1207
 
1208
#ifdef IN_RTS
1209
 
1210
#define Status_Error ada__io_exceptions__status_error
1211
extern struct Exception_Data Status_Error;
1212
 
1213
#define Mode_Error ada__io_exceptions__mode_error
1214
extern struct Exception_Data Mode_Error;
1215
 
1216
#define Name_Error ada__io_exceptions__name_error
1217
extern struct Exception_Data Name_Error;
1218
 
1219
#define Use_Error ada__io_exceptions__use_error
1220
extern struct Exception_Data Use_Error;
1221
 
1222
#define Device_Error ada__io_exceptions__device_error
1223
extern struct Exception_Data Device_Error;
1224
 
1225
#define End_Error ada__io_exceptions__end_error
1226
extern struct Exception_Data End_Error;
1227
 
1228
#define Data_Error ada__io_exceptions__data_error
1229
extern struct Exception_Data Data_Error;
1230
 
1231
#define Layout_Error ada__io_exceptions__layout_error
1232
extern struct Exception_Data Layout_Error;
1233
 
1234
#define Non_Ada_Error system__aux_dec__non_ada_error
1235
extern struct Exception_Data Non_Ada_Error;
1236
 
1237
#define Coded_Exception system__vms_exception_table__coded_exception
1238
extern struct Exception_Data *Coded_Exception (Exception_Code);
1239
 
1240
#define Base_Code_In system__vms_exception_table__base_code_in
1241
extern Exception_Code Base_Code_In (Exception_Code);
1242
 
1243
/* DEC Ada exceptions are not defined in a header file, so they
1244
   must be declared as external addresses.  */
1245
 
1246
extern int ADA$_PROGRAM_ERROR;
1247
extern int ADA$_LOCK_ERROR;
1248
extern int ADA$_EXISTENCE_ERROR;
1249
extern int ADA$_KEY_ERROR;
1250
extern int ADA$_KEYSIZERR;
1251
extern int ADA$_STAOVF;
1252
extern int ADA$_CONSTRAINT_ERRO;
1253
extern int ADA$_IOSYSFAILED;
1254
extern int ADA$_LAYOUT_ERROR;
1255
extern int ADA$_STORAGE_ERROR;
1256
extern int ADA$_DATA_ERROR;
1257
extern int ADA$_DEVICE_ERROR;
1258
extern int ADA$_END_ERROR;
1259
extern int ADA$_MODE_ERROR;
1260
extern int ADA$_NAME_ERROR;
1261
extern int ADA$_STATUS_ERROR;
1262
extern int ADA$_NOT_OPEN;
1263
extern int ADA$_ALREADY_OPEN;
1264
extern int ADA$_USE_ERROR;
1265
extern int ADA$_UNSUPPORTED;
1266
extern int ADA$_FAC_MODE_MISMAT;
1267
extern int ADA$_ORG_MISMATCH;
1268
extern int ADA$_RFM_MISMATCH;
1269
extern int ADA$_RAT_MISMATCH;
1270
extern int ADA$_MRS_MISMATCH;
1271
extern int ADA$_MRN_MISMATCH;
1272
extern int ADA$_KEY_MISMATCH;
1273
extern int ADA$_MAXLINEXC;
1274
extern int ADA$_LINEXCMRS;
1275
 
1276
/* DEC Ada specific conditions.  */
1277
static const struct cond_except dec_ada_cond_except_table [] = {
1278
  {&ADA$_PROGRAM_ERROR,   &program_error},
1279
  {&ADA$_USE_ERROR,       &Use_Error},
1280
  {&ADA$_KEYSIZERR,       &program_error},
1281
  {&ADA$_STAOVF,          &storage_error},
1282
  {&ADA$_CONSTRAINT_ERRO, &constraint_error},
1283
  {&ADA$_IOSYSFAILED,     &Device_Error},
1284
  {&ADA$_LAYOUT_ERROR,    &Layout_Error},
1285
  {&ADA$_STORAGE_ERROR,   &storage_error},
1286
  {&ADA$_DATA_ERROR,      &Data_Error},
1287
  {&ADA$_DEVICE_ERROR,    &Device_Error},
1288
  {&ADA$_END_ERROR,       &End_Error},
1289
  {&ADA$_MODE_ERROR,      &Mode_Error},
1290
  {&ADA$_NAME_ERROR,      &Name_Error},
1291
  {&ADA$_STATUS_ERROR,    &Status_Error},
1292
  {&ADA$_NOT_OPEN,        &Use_Error},
1293
  {&ADA$_ALREADY_OPEN,    &Use_Error},
1294
  {&ADA$_USE_ERROR,       &Use_Error},
1295
  {&ADA$_UNSUPPORTED,     &Use_Error},
1296
  {&ADA$_FAC_MODE_MISMAT, &Use_Error},
1297
  {&ADA$_ORG_MISMATCH,    &Use_Error},
1298
  {&ADA$_RFM_MISMATCH,    &Use_Error},
1299
  {&ADA$_RAT_MISMATCH,    &Use_Error},
1300
  {&ADA$_MRS_MISMATCH,    &Use_Error},
1301
  {&ADA$_MRN_MISMATCH,    &Use_Error},
1302
  {&ADA$_KEY_MISMATCH,    &Use_Error},
1303
  {&ADA$_MAXLINEXC,       &constraint_error},
1304
  {&ADA$_LINEXCMRS,       &constraint_error},
1305
  {0,                     0}
1306
};
1307
 
1308
#if 0
1309
   /* Already handled by a pragma Import_Exception
1310
      in Aux_IO_Exceptions */
1311
  {&ADA$_LOCK_ERROR,      &Lock_Error},
1312
  {&ADA$_EXISTENCE_ERROR, &Existence_Error},
1313
  {&ADA$_KEY_ERROR,       &Key_Error},
1314
#endif
1315
 
1316
#endif /* IN_RTS */
1317
 
1318
/* Non-DEC Ada specific conditions.  We could probably also put
1319
   SS$_HPARITH here and possibly SS$_ACCVIO, SS$_STKOVF.  */
1320
static const struct cond_except cond_except_table [] = {
1321
  {&MTH$_FLOOVEMAT, &constraint_error},
1322
  {&SS$_INTDIV,     &constraint_error},
1323
  {0,               0}
1324
};
1325
 
1326
/* To deal with VMS conditions and their mapping to Ada exceptions,
1327
   the __gnat_error_handler routine below is installed as an exception
1328
   vector having precedence over DEC frame handlers.  Some conditions
1329
   still need to be handled by such handlers, however, in which case
1330
   __gnat_error_handler needs to return SS$_RESIGNAL.  Consider for
1331
   instance the use of a third party library compiled with DECAda and
1332
   performing its own exception handling internally.
1333
 
1334
   To allow some user-level flexibility, which conditions should be
1335
   resignaled is controlled by a predicate function, provided with the
1336
   condition value and returning a boolean indication stating whether
1337
   this condition should be resignaled or not.
1338
 
1339
   That predicate function is called indirectly, via a function pointer,
1340
   by __gnat_error_handler, and changing that pointer is allowed to the
1341
   the user code by way of the __gnat_set_resignal_predicate interface.
1342
 
1343
   The user level function may then implement what it likes, including
1344
   for instance the maintenance of a dynamic data structure if the set
1345
   of to be resignalled conditions has to change over the program's
1346
   lifetime.
1347
 
1348
   ??? This is not a perfect solution to deal with the possible
1349
   interactions between the GNAT and the DECAda exception handling
1350
   models and better (more general) schemes are studied.  This is so
1351
   just provided as a convenient workaround in the meantime, and
1352
   should be use with caution since the implementation has been kept
1353
   very simple.  */
1354
 
1355
typedef int
1356
resignal_predicate (int code);
1357
 
1358
const int *cond_resignal_table [] = {
1359
  &C$_SIGKILL,
1360
  &CMA$_EXIT_THREAD,
1361
  &SS$_DEBUG,
1362
  &LIB$_KEYNOTFOU,
1363
  &LIB$_ACTIMAGE,
1364
  (int *) RDB$_STREAM_EOF,
1365
  (int *) FDL$_UNPRIKW,
1366
 
1367
};
1368
 
1369
const int facility_resignal_table [] = {
1370
  0x1380000, /* RDB */
1371
  0x2220000, /* SQL */
1372
 
1373
};
1374
 
1375
/* Default GNAT predicate for resignaling conditions.  */
1376
 
1377
static int
1378
__gnat_default_resignal_p (int code)
1379
{
1380
  int i, iexcept;
1381
 
1382
  for (i = 0; facility_resignal_table [i]; i++)
1383
    if ((code & 0xfff0000) == facility_resignal_table [i])
1384
      return 1;
1385
 
1386
  for (i = 0, iexcept = 0;
1387
       cond_resignal_table [i] &&
1388
       !(iexcept = LIB$MATCH_COND (&code, &cond_resignal_table [i]));
1389
       i++);
1390
 
1391
  return iexcept;
1392
}
1393
 
1394
/* Static pointer to predicate that the __gnat_error_handler exception
1395
   vector invokes to determine if it should resignal a condition.  */
1396
 
1397
static resignal_predicate * __gnat_resignal_p = __gnat_default_resignal_p;
1398
 
1399
/* User interface to change the predicate pointer to PREDICATE. Reset to
1400
   the default if PREDICATE is null.  */
1401
 
1402
void
1403
__gnat_set_resignal_predicate (resignal_predicate * predicate)
1404
{
1405
  if (predicate == 0)
1406
    __gnat_resignal_p = __gnat_default_resignal_p;
1407
  else
1408
    __gnat_resignal_p = predicate;
1409
}
1410
 
1411
/* Should match System.Parameters.Default_Exception_Msg_Max_Length.  */
1412
#define Default_Exception_Msg_Max_Length 512
1413
 
1414
/* Action routine for SYS$PUTMSG. There may be multiple
1415
   conditions, each with text to be appended to MESSAGE
1416
   and separated by line termination.  */
1417
 
1418
static int
1419
copy_msg (msgdesc, message)
1420
     struct descriptor_s *msgdesc;
1421
     char *message;
1422
{
1423
  int len = strlen (message);
1424
  int copy_len;
1425
 
1426
  /* Check for buffer overflow and skip.  */
1427
  if (len > 0 && len <= Default_Exception_Msg_Max_Length - 3)
1428
    {
1429
      strcat (message, "\r\n");
1430
      len += 2;
1431
    }
1432
 
1433
  /* Check for buffer overflow and truncate if necessary.  */
1434
  copy_len = (len + msgdesc->len <= Default_Exception_Msg_Max_Length - 1 ?
1435
              msgdesc->len :
1436
              Default_Exception_Msg_Max_Length - 1 - len);
1437
  strncpy (&message [len], msgdesc->adr, copy_len);
1438
  message [len + copy_len] = 0;
1439
 
1440
  return 0;
1441
}
1442
 
1443
long
1444
__gnat_handle_vms_condition (int *sigargs, void *mechargs)
1445
{
1446
  struct Exception_Data *exception = 0;
1447
  Exception_Code base_code;
1448
  struct descriptor_s gnat_facility = {4,0,"GNAT"};
1449
  char message [Default_Exception_Msg_Max_Length];
1450
 
1451
  const char *msg = "";
1452
 
1453
  /* Check for conditions to resignal which aren't effected by pragma
1454
     Import_Exception.  */
1455
  if (__gnat_resignal_p (sigargs [1]))
1456
    return SS$_RESIGNAL;
1457
 
1458
#ifdef IN_RTS
1459
  /* See if it's an imported exception.  Beware that registered exceptions
1460
     are bound to their base code, with the severity bits masked off.  */
1461
  base_code = Base_Code_In ((Exception_Code) sigargs [1]);
1462
  exception = Coded_Exception (base_code);
1463
 
1464
  if (exception)
1465
    {
1466
      message [0] = 0;
1467
 
1468
      /* Subtract PC & PSL fields which messes with PUTMSG.  */
1469
      sigargs [0] -= 2;
1470
      SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1471
      sigargs [0] += 2;
1472
      msg = message;
1473
 
1474
      exception->Name_Length = 19;
1475
      /* ??? The full name really should be get sys$getmsg returns.  */
1476
      exception->Full_Name = "IMPORTED_EXCEPTION";
1477
      exception->Import_Code = base_code;
1478
 
1479
#ifdef __IA64
1480
      /* Do not adjust the program counter as already points to the next
1481
         instruction (just after the call to LIB$STOP).  */
1482
      Raise_From_Signal_Handler (exception, msg);
1483
#endif
1484
    }
1485
#endif
1486
 
1487
  if (exception == 0)
1488
    switch (sigargs[1])
1489
      {
1490
      case SS$_ACCVIO:
1491
        if (sigargs[3] == 0)
1492
          {
1493
            exception = &constraint_error;
1494
            msg = "access zero";
1495
          }
1496
        else
1497
          {
1498
            exception = &storage_error;
1499
            msg = "stack overflow (or erroneous memory access)";
1500
          }
1501
        __gnat_adjust_context_for_raise (0, (void *)mechargs);
1502
        break;
1503
 
1504
      case SS$_STKOVF:
1505
        exception = &storage_error;
1506
        msg = "stack overflow";
1507
        __gnat_adjust_context_for_raise (0, (void *)mechargs);
1508
        break;
1509
 
1510
      case SS$_HPARITH:
1511
#ifndef IN_RTS
1512
        return SS$_RESIGNAL; /* toplev.c handles for compiler */
1513
#else
1514
        exception = &constraint_error;
1515
        msg = "arithmetic error";
1516
#ifndef __alpha__
1517
        /* No need to adjust pc on Alpha: the pc is already on the instruction
1518
           after the trapping one.  */
1519
        __gnat_adjust_context_for_raise (0, (void *)mechargs);
1520
#endif
1521
#endif
1522
        break;
1523
 
1524
      default:
1525
#ifdef IN_RTS
1526
        {
1527
          int i;
1528
 
1529
          /* Scan the DEC Ada exception condition table for a match and fetch
1530
             the associated GNAT exception pointer.  */
1531
          for (i = 0;
1532
               dec_ada_cond_except_table [i].cond &&
1533
               !LIB$MATCH_COND (&sigargs [1],
1534
                                &dec_ada_cond_except_table [i].cond);
1535
               i++);
1536
          exception = (struct Exception_Data *)
1537
            dec_ada_cond_except_table [i].except;
1538
 
1539
          if (!exception)
1540
            {
1541
              /* Scan the VMS standard condition table for a match and fetch
1542
                 the associated GNAT exception pointer.  */
1543
              for (i = 0;
1544
                   cond_except_table [i].cond &&
1545
                   !LIB$MATCH_COND (&sigargs [1], &cond_except_table [i].cond);
1546
                   i++);
1547
              exception = (struct Exception_Data *)
1548
                cond_except_table [i].except;
1549
 
1550
              if (!exception)
1551
                /* User programs expect Non_Ada_Error to be raised, reference
1552
                   DEC Ada test CXCONDHAN.  */
1553
                exception = &Non_Ada_Error;
1554
            }
1555
        }
1556
#else
1557
        exception = &program_error;
1558
#endif
1559
        message [0] = 0;
1560
        /* Subtract PC & PSL fields which messes with PUTMSG.  */
1561
        sigargs [0] -= 2;
1562
        SYS$PUTMSG (sigargs, copy_msg, &gnat_facility, message);
1563
        sigargs [0] += 2;
1564
        msg = message;
1565
        break;
1566
      }
1567
 
1568
  Raise_From_Signal_Handler (exception, msg);
1569
}
1570
 
1571
long
1572
__gnat_error_handler (int *sigargs, void *mechargs)
1573
{
1574
  return __gnat_handle_vms_condition (sigargs, mechargs);
1575
}
1576
 
1577
void
1578
__gnat_install_handler (void)
1579
{
1580
  long prvhnd ATTRIBUTE_UNUSED;
1581
 
1582
#if !defined (IN_RTS)
1583
  SYS$SETEXV (1, __gnat_error_handler, 3, &prvhnd);
1584
#endif
1585
 
1586
  /* On alpha-vms, we avoid the global vector annoyance thanks to frame based
1587
     handlers to turn conditions into exceptions since GCC 3.4.  The global
1588
     vector is still required for earlier GCC versions.  We're resorting to
1589
     the __gnat_error_prehandler assembly function in this case.  */
1590
 
1591
#if defined (IN_RTS) && defined (__alpha__)
1592
  if ((__GNUC__ * 10 + __GNUC_MINOR__) < 34)
1593
    {
1594
      char * c = (char *) xmalloc (2049);
1595
 
1596
      __gnat_error_prehandler_stack = &c[2048];
1597
      SYS$SETEXV (1, __gnat_error_prehandler, 3, &prvhnd);
1598
    }
1599
#endif
1600
 
1601
  __gnat_handler_installed = 1;
1602
}
1603
 
1604
/* __gnat_adjust_context_for_raise for Alpha - see comments along with the
1605
   default version later in this file.  */
1606
 
1607
#if defined (IN_RTS) && defined (__alpha__)
1608
 
1609
#include <vms/chfctxdef.h>
1610
#include <vms/chfdef.h>
1611
 
1612
#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1613
 
1614
void
1615
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1616
{
1617
  /* Add one to the address of the instruction signaling the condition,
1618
     located in the sigargs array.  */
1619
 
1620
  CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1621
  CHF$SIGNAL_ARRAY * sigargs
1622
    = (CHF$SIGNAL_ARRAY *) mechargs->chf$q_mch_sig_addr;
1623
 
1624
  int vcount = sigargs->chf$is_sig_args;
1625
  int * pc_slot = & (&sigargs->chf$l_sig_name)[vcount-2];
1626
 
1627
  (*pc_slot) ++;
1628
}
1629
 
1630
#endif
1631
 
1632
/* __gnat_adjust_context_for_raise for ia64.  */
1633
 
1634
#if defined (IN_RTS) && defined (__IA64)
1635
 
1636
#include <vms/chfctxdef.h>
1637
#include <vms/chfdef.h>
1638
 
1639
#define HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
1640
 
1641
typedef unsigned long long u64;
1642
 
1643
void
1644
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED, void *ucontext)
1645
{
1646
  /* Add one to the address of the instruction signaling the condition,
1647
     located in the 64bits sigargs array.  */
1648
 
1649
  CHF$MECH_ARRAY * mechargs = (CHF$MECH_ARRAY *) ucontext;
1650
 
1651
  CHF64$SIGNAL_ARRAY *chfsig64
1652
    = (CHF64$SIGNAL_ARRAY *) mechargs->chf$ph_mch_sig64_addr;
1653
 
1654
  u64 * post_sigarray
1655
    = (u64 *)chfsig64 + 1 + chfsig64->chf64$l_sig_args;
1656
 
1657
  u64 * ih_pc_loc = post_sigarray - 2;
1658
 
1659
  (*ih_pc_loc) ++;
1660
}
1661
 
1662
#endif
1663
 
1664
/* Feature logical name and global variable address pair */
1665
struct feature {char *name; int* gl_addr;};
1666
 
1667
/* Default values for GNAT features set by environment. */
1668
int __gl_no_malloc_64 = 0;
1669
 
1670
/* Array feature logical names and global variable addresses */
1671
static struct feature features[] = {
1672
  {"GNAT$NO_MALLOC_64", &__gl_no_malloc_64},
1673
  {0, 0}
1674
};
1675
 
1676
void __gnat_set_features ()
1677
{
1678
  struct descriptor_s name_desc, result_desc;
1679
  int i, status;
1680
  unsigned short rlen;
1681
 
1682
#define MAXEQUIV 10
1683
  char buff [MAXEQUIV];
1684
 
1685
  /* Loop through features array and test name for enable/disable */
1686
  for (i=0; features [i].name; i++)
1687
    {
1688
       name_desc.len = strlen (features [i].name);
1689
       name_desc.mbz = 0;
1690
       name_desc.adr = features [i].name;
1691
 
1692
       result_desc.len = MAXEQUIV - 1;
1693
       result_desc.mbz = 0;
1694
       result_desc.adr = buff;
1695
 
1696
       status = LIB$GET_LOGICAL (&name_desc, &result_desc, &rlen);
1697
 
1698
       if (((status & 1) == 1) && (rlen < MAXEQUIV))
1699
         buff [rlen] = 0;
1700
       else
1701
         strcpy (buff, "");
1702
 
1703
       if (strcmp (buff, "ENABLE") == 0)
1704
          *features [i].gl_addr = 1;
1705
       else if (strcmp (buff, "DISABLE") == 0)
1706
          *features [i].gl_addr = 0;
1707
    }
1708
 
1709
    __gnat_features_set = 1;
1710
}
1711
 
1712
/*******************/
1713
/* FreeBSD Section */
1714
/*******************/
1715
 
1716
#elif defined (__FreeBSD__)
1717
 
1718
#include <signal.h>
1719
#include <sys/ucontext.h>
1720
#include <unistd.h>
1721
 
1722
static void __gnat_error_handler (int, siginfo_t *, ucontext_t *);
1723
 
1724
static void
1725
__gnat_error_handler (int sig, siginfo_t *info __attribute__ ((unused)),
1726
                      ucontext_t *ucontext)
1727
{
1728
  struct Exception_Data *exception;
1729
  const char *msg;
1730
 
1731
  switch (sig)
1732
    {
1733
    case SIGFPE:
1734
      exception = &constraint_error;
1735
      msg = "SIGFPE";
1736
      break;
1737
 
1738
    case SIGILL:
1739
      exception = &constraint_error;
1740
      msg = "SIGILL";
1741
      break;
1742
 
1743
    case SIGSEGV:
1744
      exception = &storage_error;
1745
      msg = "stack overflow or erroneous memory access";
1746
      break;
1747
 
1748
    case SIGBUS:
1749
      exception = &constraint_error;
1750
      msg = "SIGBUS";
1751
      break;
1752
 
1753
    default:
1754
      exception = &program_error;
1755
      msg = "unhandled signal";
1756
    }
1757
 
1758
  Raise_From_Signal_Handler (exception, msg);
1759
}
1760
 
1761
void
1762
__gnat_install_handler ()
1763
{
1764
  struct sigaction act;
1765
 
1766
  /* Set up signal handler to map synchronous signals to appropriate
1767
     exceptions.  Make sure that the handler isn't interrupted by another
1768
     signal that might cause a scheduling event!  */
1769
 
1770
  act.sa_sigaction
1771
    = (void (*)(int, struct __siginfo *, void*)) __gnat_error_handler;
1772
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
1773
  (void) sigemptyset (&act.sa_mask);
1774
 
1775
  (void) sigaction (SIGILL,  &act, NULL);
1776
  (void) sigaction (SIGFPE,  &act, NULL);
1777
  (void) sigaction (SIGSEGV, &act, NULL);
1778
  (void) sigaction (SIGBUS,  &act, NULL);
1779
 
1780
  __gnat_handler_installed = 1;
1781
}
1782
 
1783
/*******************/
1784
/* VxWorks Section */
1785
/*******************/
1786
 
1787
#elif defined(__vxworks)
1788
 
1789
#include <signal.h>
1790
#include <taskLib.h>
1791
 
1792
#ifndef __RTP__
1793
#include <intLib.h>
1794
#include <iv.h>
1795
#endif
1796
 
1797
#ifdef VTHREADS
1798
#include "private/vThreadsP.h"
1799
#endif
1800
 
1801
void __gnat_error_handler (int, void *, struct sigcontext *);
1802
 
1803
#ifndef __RTP__
1804
 
1805
/* Directly vectored Interrupt routines are not supported when using RTPs.  */
1806
 
1807
extern int __gnat_inum_to_ivec (int);
1808
 
1809
/* This is needed by the GNAT run time to handle Vxworks interrupts.  */
1810
int
1811
__gnat_inum_to_ivec (int num)
1812
{
1813
  return INUM_TO_IVEC (num);
1814
}
1815
#endif
1816
 
1817
#if !defined(__alpha_vxworks) && (_WRS_VXWORKS_MAJOR != 6) && !defined(__RTP__)
1818
 
1819
/* getpid is used by s-parint.adb, but is not defined by VxWorks, except
1820
   on Alpha VxWorks and VxWorks 6.x (including RTPs).  */
1821
 
1822
extern long getpid (void);
1823
 
1824
long
1825
getpid (void)
1826
{
1827
  return taskIdSelf ();
1828
}
1829
#endif
1830
 
1831
/* VxWorks 653 vThreads expects the field excCnt to be zeroed when a signal is.
1832
   handled. The VxWorks version of longjmp does this; GCC's builtin_longjmp
1833
   doesn't.  */
1834
void
1835
__gnat_clear_exception_count (void)
1836
{
1837
#ifdef VTHREADS
1838
  WIND_TCB *currentTask = (WIND_TCB *) taskIdSelf();
1839
 
1840
  currentTask->vThreads.excCnt = 0;
1841
#endif
1842
}
1843
 
1844
/* Handle different SIGnal to exception mappings in different VxWorks
1845
   versions.   */
1846
static void
1847
__gnat_map_signal (int sig)
1848
{
1849
  struct Exception_Data *exception;
1850
  const char *msg;
1851
 
1852
  switch (sig)
1853
    {
1854
    case SIGFPE:
1855
      exception = &constraint_error;
1856
      msg = "SIGFPE";
1857
      break;
1858
#ifdef VTHREADS
1859
#ifdef __VXWORKSMILS__
1860
    case SIGILL:
1861
      exception = &storage_error;
1862
      msg = "SIGILL: possible stack overflow";
1863
      break;
1864
    case SIGSEGV:
1865
      exception = &storage_error;
1866
      msg = "SIGSEGV";
1867
      break;
1868
    case SIGBUS:
1869
      exception = &program_error;
1870
      msg = "SIGBUS";
1871
      break;
1872
#else
1873
    case SIGILL:
1874
      exception = &constraint_error;
1875
      msg = "Floating point exception or SIGILL";
1876
      break;
1877
    case SIGSEGV:
1878
      exception = &storage_error;
1879
      msg = "SIGSEGV";
1880
      break;
1881
    case SIGBUS:
1882
      exception = &storage_error;
1883
      msg = "SIGBUS: possible stack overflow";
1884
      break;
1885
#endif
1886
#elif (_WRS_VXWORKS_MAJOR == 6)
1887
    case SIGILL:
1888
      exception = &constraint_error;
1889
      msg = "SIGILL";
1890
      break;
1891
#ifdef __RTP__
1892
    /* In RTP mode a SIGSEGV is most likely due to a stack overflow,
1893
       since stack checking uses the probing mechanism.  */
1894
    case SIGSEGV:
1895
      exception = &storage_error;
1896
      msg = "SIGSEGV: possible stack overflow";
1897
      break;
1898
    case SIGBUS:
1899
      exception = &program_error;
1900
      msg = "SIGBUS";
1901
      break;
1902
#else
1903
      /* VxWorks 6 kernel mode with probing. SIGBUS for guard page hit */
1904
    case SIGSEGV:
1905
      exception = &storage_error;
1906
      msg = "SIGSEGV";
1907
      break;
1908
    case SIGBUS:
1909
      exception = &storage_error;
1910
      msg = "SIGBUS: possible stack overflow";
1911
      break;
1912
#endif
1913
#else
1914
    /* VxWorks 5: a SIGILL is most likely due to a stack overflow,
1915
       since stack checking uses the stack limit mechanism.  */
1916
    case SIGILL:
1917
      exception = &storage_error;
1918
      msg = "SIGILL: possible stack overflow";
1919
      break;
1920
    case SIGSEGV:
1921
      exception = &storage_error;
1922
      msg = "SIGSEGV";
1923
      break;
1924
    case SIGBUS:
1925
      exception = &program_error;
1926
      msg = "SIGBUS";
1927
      break;
1928
#endif
1929
    default:
1930
      exception = &program_error;
1931
      msg = "unhandled signal";
1932
    }
1933
 
1934
  __gnat_clear_exception_count ();
1935
  Raise_From_Signal_Handler (exception, msg);
1936
}
1937
 
1938
/* Tasking and Non-tasking signal handler.  Map SIGnal to Ada exception
1939
   propagation after the required low level adjustments.  */
1940
 
1941
void
1942
__gnat_error_handler (int sig, void * si ATTRIBUTE_UNUSED,
1943
                      struct sigcontext * sc)
1944
{
1945
  sigset_t mask;
1946
 
1947
  /* VxWorks will always mask out the signal during the signal handler and
1948
     will reenable it on a longjmp.  GNAT does not generate a longjmp to
1949
     return from a signal handler so the signal will still be masked unless
1950
     we unmask it.  */
1951
  sigprocmask (SIG_SETMASK, NULL, &mask);
1952
  sigdelset (&mask, sig);
1953
  sigprocmask (SIG_SETMASK, &mask, NULL);
1954
 
1955
  __gnat_map_signal (sig);
1956
}
1957
 
1958
void
1959
__gnat_install_handler (void)
1960
{
1961
  struct sigaction act;
1962
 
1963
  /* Setup signal handler to map synchronous signals to appropriate
1964
     exceptions.  Make sure that the handler isn't interrupted by another
1965
     signal that might cause a scheduling event!  */
1966
 
1967
  act.sa_handler = __gnat_error_handler;
1968
  act.sa_flags = SA_SIGINFO | SA_ONSTACK;
1969
  sigemptyset (&act.sa_mask);
1970
 
1971
  /* For VxWorks, install all signal handlers, since pragma Interrupt_State
1972
     applies to vectored hardware interrupts, not signals.  */
1973
  sigaction (SIGFPE,  &act, NULL);
1974
  sigaction (SIGILL,  &act, NULL);
1975
  sigaction (SIGSEGV, &act, NULL);
1976
  sigaction (SIGBUS,  &act, NULL);
1977
 
1978
  __gnat_handler_installed = 1;
1979
}
1980
 
1981
#define HAVE_GNAT_INIT_FLOAT
1982
 
1983
void
1984
__gnat_init_float (void)
1985
{
1986
  /* Disable overflow/underflow exceptions on the PPC processor, needed
1987
     to get correct Ada semantics.  Note that for AE653 vThreads, the HW
1988
     overflow settings are an OS configuration issue.  The instructions
1989
     below have no effect.  */
1990
#if defined (_ARCH_PPC) && !defined (_SOFT_FLOAT) && !defined (VTHREADS)
1991
#if defined (__SPE__)
1992
  {
1993
     const unsigned long spefscr_mask = 0xfffffff3;
1994
     unsigned long spefscr;
1995
     asm ("mfspr  %0, 512" : "=r" (spefscr));
1996
     spefscr = spefscr & spefscr_mask;
1997
     asm ("mtspr 512, %0\n\tisync" : : "r" (spefscr));
1998
  }
1999
#else
2000
  asm ("mtfsb0 25");
2001
  asm ("mtfsb0 26");
2002
#endif
2003
#endif
2004
 
2005
#if (defined (__i386__) || defined (i386)) && !defined (VTHREADS)
2006
  /* This is used to properly initialize the FPU on an x86 for each
2007
     process thread.  */
2008
  asm ("finit");
2009
#endif
2010
 
2011
  /* Similarly for SPARC64.  Achieved by masking bits in the Trap Enable Mask
2012
     field of the Floating-point Status Register (see the SPARC Architecture
2013
     Manual Version 9, p 48).  */
2014
#if defined (sparc64)
2015
 
2016
#define FSR_TEM_NVM (1 << 27)  /* Invalid operand  */
2017
#define FSR_TEM_OFM (1 << 26)  /* Overflow  */
2018
#define FSR_TEM_UFM (1 << 25)  /* Underflow  */
2019
#define FSR_TEM_DZM (1 << 24)  /* Division by Zero  */
2020
#define FSR_TEM_NXM (1 << 23)  /* Inexact result  */
2021
  {
2022
    unsigned int fsr;
2023
 
2024
    __asm__("st %%fsr, %0" : "=m" (fsr));
2025
    fsr &= ~(FSR_TEM_OFM | FSR_TEM_UFM);
2026
    __asm__("ld %0, %%fsr" : : "m" (fsr));
2027
  }
2028
#endif
2029
}
2030
 
2031
/* This subprogram is called by System.Task_Primitives.Operations.Enter_Task
2032
   (if not null) when a new task is created.  It is initialized by
2033
   System.Stack_Checking.Operations.Initialize_Stack_Limit.
2034
   The use of a hook avoids to drag stack checking subprograms if stack
2035
   checking is not used.  */
2036
void (*__gnat_set_stack_limit_hook)(void) = (void (*)(void))0;
2037
 
2038
/******************/
2039
/* NetBSD Section */
2040
/******************/
2041
 
2042
#elif defined(__NetBSD__)
2043
 
2044
#include <signal.h>
2045
#include <unistd.h>
2046
 
2047
static void
2048
__gnat_error_handler (int sig)
2049
{
2050
  struct Exception_Data *exception;
2051
  const char *msg;
2052
 
2053
  switch(sig)
2054
  {
2055
    case SIGFPE:
2056
      exception = &constraint_error;
2057
      msg = "SIGFPE";
2058
      break;
2059
    case SIGILL:
2060
      exception = &constraint_error;
2061
      msg = "SIGILL";
2062
      break;
2063
    case SIGSEGV:
2064
      exception = &storage_error;
2065
      msg = "stack overflow or erroneous memory access";
2066
      break;
2067
    case SIGBUS:
2068
      exception = &constraint_error;
2069
      msg = "SIGBUS";
2070
      break;
2071
    default:
2072
      exception = &program_error;
2073
      msg = "unhandled signal";
2074
    }
2075
 
2076
    Raise_From_Signal_Handler(exception, msg);
2077
}
2078
 
2079
void
2080
__gnat_install_handler(void)
2081
{
2082
  struct sigaction act;
2083
 
2084
  act.sa_handler = __gnat_error_handler;
2085
  act.sa_flags = SA_NODEFER | SA_RESTART;
2086
  sigemptyset (&act.sa_mask);
2087
 
2088
  /* Do not install handlers if interrupt state is "System".  */
2089
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
2090
    sigaction (SIGFPE,  &act, NULL);
2091
  if (__gnat_get_interrupt_state (SIGILL) != 's')
2092
    sigaction (SIGILL,  &act, NULL);
2093
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2094
    sigaction (SIGSEGV, &act, NULL);
2095
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
2096
    sigaction (SIGBUS,  &act, NULL);
2097
 
2098
  __gnat_handler_installed = 1;
2099
}
2100
 
2101
/*******************/
2102
/* OpenBSD Section */
2103
/*******************/
2104
 
2105
#elif defined(__OpenBSD__)
2106
 
2107
#include <signal.h>
2108
#include <unistd.h>
2109
 
2110
static void
2111
__gnat_error_handler (int sig)
2112
{
2113
  struct Exception_Data *exception;
2114
  const char *msg;
2115
 
2116
  switch(sig)
2117
  {
2118
    case SIGFPE:
2119
      exception = &constraint_error;
2120
      msg = "SIGFPE";
2121
      break;
2122
    case SIGILL:
2123
      exception = &constraint_error;
2124
      msg = "SIGILL";
2125
      break;
2126
    case SIGSEGV:
2127
      exception = &storage_error;
2128
      msg = "stack overflow or erroneous memory access";
2129
      break;
2130
    case SIGBUS:
2131
      exception = &constraint_error;
2132
      msg = "SIGBUS";
2133
      break;
2134
    default:
2135
      exception = &program_error;
2136
      msg = "unhandled signal";
2137
    }
2138
 
2139
    Raise_From_Signal_Handler(exception, msg);
2140
}
2141
 
2142
void
2143
__gnat_install_handler(void)
2144
{
2145
  struct sigaction act;
2146
 
2147
  act.sa_handler = __gnat_error_handler;
2148
  act.sa_flags = SA_NODEFER | SA_RESTART;
2149
  sigemptyset (&act.sa_mask);
2150
 
2151
  /* Do not install handlers if interrupt state is "System" */
2152
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
2153
    sigaction (SIGFPE,  &act, NULL);
2154
  if (__gnat_get_interrupt_state (SIGILL) != 's')
2155
    sigaction (SIGILL,  &act, NULL);
2156
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2157
    sigaction (SIGSEGV, &act, NULL);
2158
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
2159
    sigaction (SIGBUS,  &act, NULL);
2160
 
2161
  __gnat_handler_installed = 1;
2162
}
2163
 
2164
/******************/
2165
/* Darwin Section */
2166
/******************/
2167
 
2168
#elif defined(__APPLE__)
2169
 
2170
#include <signal.h>
2171
#include <sys/syscall.h>
2172
#include <mach/mach_vm.h>
2173
#include <mach/mach_init.h>
2174
#include <mach/vm_statistics.h>
2175
 
2176
/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size.  */
2177
char __gnat_alternate_stack[32 * 1024]; /* 1 * MINSIGSTKSZ */
2178
 
2179
static void __gnat_error_handler (int sig, siginfo_t * si, void * uc);
2180
 
2181
/* Defined in xnu unix_signal.c.
2182
   Tell the kernel to re-use alt stack when delivering a signal.  */
2183
#define UC_RESET_ALT_STACK      0x80000000
2184
 
2185
/* Return true if ADDR is within a stack guard area.  */
2186
static int
2187
__gnat_is_stack_guard (mach_vm_address_t addr)
2188
{
2189
  kern_return_t kret;
2190
  vm_region_submap_info_data_64_t info;
2191
  mach_vm_address_t start;
2192
  mach_vm_size_t size;
2193
  natural_t depth;
2194
  mach_msg_type_number_t count;
2195
 
2196
  count = VM_REGION_SUBMAP_INFO_COUNT_64;
2197
  start = addr;
2198
  size = -1;
2199
  depth = 9999;
2200
  kret = mach_vm_region_recurse (mach_task_self (), &start, &size, &depth,
2201
                                 (vm_region_recurse_info_t) &info, &count);
2202
  if (kret == KERN_SUCCESS
2203
      && addr >= start && addr < (start + size)
2204
      && info.protection == VM_PROT_NONE
2205
      && info.user_tag == VM_MEMORY_STACK)
2206
    return 1;
2207
  return 0;
2208
}
2209
 
2210
static void
2211
__gnat_error_handler (int sig, siginfo_t * si, void * uc ATTRIBUTE_UNUSED)
2212
{
2213
  struct Exception_Data *exception;
2214
  const char *msg;
2215
 
2216
  switch (sig)
2217
    {
2218
    case SIGSEGV:
2219
    case SIGBUS:
2220
      if (__gnat_is_stack_guard ((unsigned long)si->si_addr))
2221
        {
2222
          exception = &storage_error;
2223
          msg = "stack overflow";
2224
        }
2225
      else
2226
        {
2227
          exception = &constraint_error;
2228
          msg = "erroneous memory access";
2229
        }
2230
      /* Reset the use of alt stack, so that the alt stack will be used
2231
         for the next signal delivery.
2232
         The stack can't be used in case of stack checking.  */
2233
      syscall (SYS_sigreturn, NULL, UC_RESET_ALT_STACK);
2234
      break;
2235
 
2236
    case SIGFPE:
2237
      exception = &constraint_error;
2238
      msg = "SIGFPE";
2239
      break;
2240
 
2241
    default:
2242
      exception = &program_error;
2243
      msg = "unhandled signal";
2244
    }
2245
 
2246
  Raise_From_Signal_Handler (exception, msg);
2247
}
2248
 
2249
void
2250
__gnat_install_handler (void)
2251
{
2252
  struct sigaction act;
2253
 
2254
  /* Set up signal handler to map synchronous signals to appropriate
2255
     exceptions.  Make sure that the handler isn't interrupted by another
2256
     signal that might cause a scheduling event!  Also setup an alternate
2257
     stack region for the handler execution so that stack overflows can be
2258
     handled properly, avoiding a SEGV generation from stack usage by the
2259
     handler itself (and it is required by Darwin).  */
2260
 
2261
  stack_t stack;
2262
  stack.ss_sp = __gnat_alternate_stack;
2263
  stack.ss_size = sizeof (__gnat_alternate_stack);
2264
  stack.ss_flags = 0;
2265
  sigaltstack (&stack, NULL);
2266
 
2267
  act.sa_flags = SA_NODEFER | SA_RESTART | SA_SIGINFO;
2268
  act.sa_sigaction = __gnat_error_handler;
2269
  sigemptyset (&act.sa_mask);
2270
 
2271
  /* Do not install handlers if interrupt state is "System".  */
2272
  if (__gnat_get_interrupt_state (SIGABRT) != 's')
2273
    sigaction (SIGABRT, &act, NULL);
2274
  if (__gnat_get_interrupt_state (SIGFPE) != 's')
2275
    sigaction (SIGFPE,  &act, NULL);
2276
  if (__gnat_get_interrupt_state (SIGILL) != 's')
2277
    sigaction (SIGILL,  &act, NULL);
2278
 
2279
  act.sa_flags |= SA_ONSTACK;
2280
  if (__gnat_get_interrupt_state (SIGSEGV) != 's')
2281
    sigaction (SIGSEGV, &act, NULL);
2282
  if (__gnat_get_interrupt_state (SIGBUS) != 's')
2283
    sigaction (SIGBUS,  &act, NULL);
2284
 
2285
  __gnat_handler_installed = 1;
2286
}
2287
 
2288
#else
2289
 
2290
/* For all other versions of GNAT, the handler does nothing.  */
2291
 
2292
/*******************/
2293
/* Default Section */
2294
/*******************/
2295
 
2296
void
2297
__gnat_install_handler (void)
2298
{
2299
  __gnat_handler_installed = 1;
2300
}
2301
 
2302
#endif
2303
 
2304
/*********************/
2305
/* __gnat_init_float */
2306
/*********************/
2307
 
2308
/* This routine is called as each process thread is created, for possible
2309
   initialization of the FP processor.  This version is used under INTERIX,
2310
   WIN32 and could be used under OS/2.  */
2311
 
2312
#if defined (_WIN32) || defined (__INTERIX) || defined (__EMX__) \
2313
  || defined (__Lynx__) || defined(__NetBSD__) || defined(__FreeBSD__) \
2314
  || defined (__OpenBSD__)
2315
 
2316
#define HAVE_GNAT_INIT_FLOAT
2317
 
2318
void
2319
__gnat_init_float (void)
2320
{
2321
#if defined (__i386__) || defined (i386) || defined (__x86_64)
2322
 
2323
  /* This is used to properly initialize the FPU on an x86 for each
2324
     process thread.  */
2325
 
2326
  asm ("finit");
2327
 
2328
#endif  /* Defined __i386__ */
2329
}
2330
#endif
2331
 
2332
#ifndef HAVE_GNAT_INIT_FLOAT
2333
 
2334
/* All targets without a specific __gnat_init_float will use an empty one.  */
2335
void
2336
__gnat_init_float (void)
2337
{
2338
}
2339
#endif
2340
 
2341
/***********************************/
2342
/* __gnat_adjust_context_for_raise */
2343
/***********************************/
2344
 
2345
#ifndef HAVE_GNAT_ADJUST_CONTEXT_FOR_RAISE
2346
 
2347
/* All targets without a specific version will use an empty one.  */
2348
 
2349
/* Given UCONTEXT a pointer to a context structure received by a signal
2350
   handler for SIGNO, perform the necessary adjustments to let the handler
2351
   raise an exception.  Calls to this routine are not conditioned by the
2352
   propagation scheme in use.  */
2353
 
2354
void
2355
__gnat_adjust_context_for_raise (int signo ATTRIBUTE_UNUSED,
2356
                                 void *ucontext ATTRIBUTE_UNUSED)
2357
{
2358
  /* We used to compensate here for the raised from call vs raised from signal
2359
     exception discrepancy with the GCC ZCX scheme, but this now can be dealt
2360
     with generically in the unwinder (see GCC PR other/26208).  This however
2361
     requires the use of the _Unwind_GetIPInfo routine in raise-gcc.c, which
2362
     is predicated on the definition of HAVE_GETIPINFO at compile time.  Only
2363
     the VMS ports still do the compensation described in the few lines below.
2364
 
2365
     *** Call vs signal exception discrepancy with GCC ZCX scheme ***
2366
 
2367
     The GCC unwinder expects to be dealing with call return addresses, since
2368
     this is the "nominal" case of what we retrieve while unwinding a regular
2369
     call chain.
2370
 
2371
     To evaluate if a handler applies at some point identified by a return
2372
     address, the propagation engine needs to determine what region the
2373
     corresponding call instruction pertains to.  Because the return address
2374
     may not be attached to the same region as the call, the unwinder always
2375
     subtracts "some" amount from a return address to search the region
2376
     tables, amount chosen to ensure that the resulting address is inside the
2377
     call instruction.
2378
 
2379
     When we raise an exception from a signal handler, e.g. to transform a
2380
     SIGSEGV into Storage_Error, things need to appear as if the signal
2381
     handler had been "called" by the instruction which triggered the signal,
2382
     so that exception handlers that apply there are considered.  What the
2383
     unwinder will retrieve as the return address from the signal handler is
2384
     what it will find as the faulting instruction address in the signal
2385
     context pushed by the kernel.  Leaving this address untouched looses, if
2386
     the triggering instruction happens to be the very first of a region, as
2387
     the later adjustments performed by the unwinder would yield an address
2388
     outside that region.  We need to compensate for the unwinder adjustments
2389
     at some point, and this is what this routine is expected to do.
2390
 
2391
     signo is passed because on some targets for some signals the PC in
2392
     context points to the instruction after the faulting one, in which case
2393
     the unwinder adjustment is still desired.  */
2394
}
2395
 
2396
#endif

powered by: WebSVN 2.1.0

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