1  /* SysExceptions.c connect signal handlers to exceptions.
       2  
       3  Copyright (C) 2010-2023 Free Software Foundation, Inc.
       4  Contributed by Gaius Mulley <gaius@glam.ac.uk>.
       5  
       6  This file is part of GNU Modula-2.
       7  
       8  GNU Modula-2 is free software; you can redistribute it and/or modify
       9  it under the terms of the GNU General Public License as published by
      10  the Free Software Foundation; either version 3, or (at your option)
      11  any later version.
      12  
      13  GNU Modula-2 is distributed in the hope that it will be useful, but
      14  WITHOUT ANY WARRANTY; without even the implied warranty of
      15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16  General Public License for more details.
      17  
      18  Under Section 7 of GPL version 3, you are granted additional
      19  permissions described in the GCC Runtime Library Exception, version
      20  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  #include "config.h"
      28  #include "system.h"
      29  #include "ansidecl.h"
      30  #include "gm2-libs-host.h"
      31  
      32  #if defined(HAVE_SIGNAL_H)
      33  #include <signal.h>
      34  #endif
      35  
      36  #ifdef __cplusplus
      37  extern "C" {
      38  #endif
      39  
      40  #if 0
      41  /* Signals.  */
      42  #define SIGHUP 1       /* Hangup (POSIX).  */
      43  #define SIGINT 2       /* Interrupt (ANSI).  */
      44  #define SIGQUIT 3      /* Quit (POSIX).  */
      45  #define SIGILL 4       /* Illegal instruction (ANSI).  */
      46  #define SIGTRAP 5      /* Trace trap (POSIX).  */
      47  #define SIGABRT 6      /* Abort (ANSI).  */
      48  #define SIGIOT 6       /* IOT trap (4.2 BSD).  */
      49  #define SIGBUS 7       /* BUS error (4.2 BSD).  */
      50  #define SIGFPE 8       /* Floating-point exception (ANSI).  */
      51  #define SIGKILL 9      /* Kill, unblockable (POSIX).  */
      52  #define SIGUSR1 10     /* User-defined signal 1 (POSIX).  */
      53  #define SIGSEGV 11     /* Segmentation violation (ANSI).  */
      54  #define SIGUSR2 12     /* User-defined signal 2 (POSIX).  */
      55  #define SIGPIPE 13     /* Broken pipe (POSIX).  */
      56  #define SIGALRM 14     /* Alarm clock (POSIX).  */
      57  #define SIGTERM 15     /* Termination (ANSI).  */
      58  #define SIGSTKFLT 16   /* Stack fault.  */
      59  #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V).  */
      60  #define SIGCHLD 17     /* Child status has changed (POSIX).  */
      61  #define SIGCONT 18     /* Continue (POSIX).  */
      62  #define SIGSTOP 19     /* Stop, unblockable (POSIX).  */
      63  #define SIGTSTP 20     /* Keyboard stop (POSIX).  */
      64  #define SIGTTIN 21     /* Background read from tty (POSIX).  */
      65  #define SIGTTOU 22     /* Background write to tty (POSIX).  */
      66  #define SIGURG 23      /* Urgent condition on socket (4.2 BSD).  */
      67  #define SIGXCPU 24     /* CPU limit exceeded (4.2 BSD).  */
      68  #define SIGXFSZ 25     /* File size limit exceeded (4.2 BSD).  */
      69  #define SIGVTALRM 26   /* Virtual alarm clock (4.2 BSD).  */
      70  #define SIGPROF 27     /* Profiling alarm clock (4.2 BSD).  */
      71  #define SIGWINCH 28    /* Window size change (4.3 BSD, Sun).  */
      72  #define SIGPOLL SIGIO  /* Pollable event occurred (System V).  */
      73  #define SIGIO 29       /* I/O now possible (4.2 BSD).  */
      74  #define SIGPWR 30      /* Power failure restart (System V).  */
      75  #define SIGSYS 31      /* Bad system call.  */
      76  #define SIGUNUSED 31
      77  
      78  
      79      (indexException,     rangeException,         caseSelectException,  invalidLocation,
      80       functionException,  wholeValueException,    wholeDivException,    realValueException,
      81       realDivException,   complexValueException,  complexDivException,  protException,
      82       sysException,       coException,            exException
      83      );
      84  
      85  #endif
      86  
      87  /* note wholeDivException and realDivException are caught by SIGFPE
      88     and depatched to the appropriate Modula-2 runtime routine upon
      89     testing FPE_INTDIV or FPE_FLTDIV.  realValueException is also
      90     caught by SIGFPE and dispatched by testing FFE_FLTOVF or
      91     FPE_FLTUND or FPE_FLTRES or FPE_FLTINV.  indexException is
      92     caught by SIGFPE and dispatched by FPE_FLTSUB.  */
      93  
      94  #if defined(HAVE_SIGNAL_H)
      95  static struct sigaction sigbus;
      96  static struct sigaction sigfpe_;
      97  static struct sigaction sigsegv;
      98  
      99  static void (*indexProc) (void *);
     100  static void (*rangeProc) (void *);
     101  static void (*assignmentrangeProc) (void *);
     102  static void (*caseProc) (void *);
     103  static void (*invalidlocProc) (void *);
     104  static void (*functionProc) (void *);
     105  static void (*wholevalueProc) (void *);
     106  static void (*wholedivProc) (void *);
     107  static void (*realvalueProc) (void *);
     108  static void (*realdivProc) (void *);
     109  static void (*complexvalueProc) (void *);
     110  static void (*complexdivProc) (void *);
     111  static void (*protectionProc) (void *);
     112  static void (*systemProc) (void *);
     113  static void (*coroutineProc) (void *);
     114  static void (*exceptionProc) (void *);
     115  
     116  static void
     117  sigbusDespatcher (int signum, siginfo_t *info, void *ucontext)
     118  {
     119    switch (signum)
     120      {
     121  
     122      case SIGSEGV:
     123      case SIGBUS:
     124        if (info)
     125          (*invalidlocProc) (info->si_addr);
     126        break;
     127      default:
     128        perror ("not expecting to arrive here with this signal");
     129      }
     130  }
     131  
     132  static void
     133  sigfpeDespatcher (int signum, siginfo_t *info, void *ucontext)
     134  {
     135    switch (signum)
     136      {
     137  
     138      case SIGFPE:
     139        if (info)
     140          {
     141            if (info->si_code | FPE_INTDIV)
     142              (*wholedivProc) (info->si_addr); /* integer divide by zero.  */
     143            if (info->si_code | FPE_INTOVF)
     144              (*wholevalueProc) (info->si_addr); /* integer overflow.  */
     145            if (info->si_code | FPE_FLTDIV)
     146              (*realdivProc) (
     147                  info->si_addr); /* floating-point divide by zero.  */
     148            if (info->si_code | FPE_FLTOVF)
     149              (*realvalueProc) (info->si_addr); /* floating-point overflow.  */
     150            if (info->si_code | FPE_FLTUND)
     151              (*realvalueProc) (info->si_addr); /* floating-point underflow.  */
     152            if (info->si_code | FPE_FLTRES)
     153              (*realvalueProc) (
     154                  info->si_addr); /* floating-point inexact result.  */
     155            if (info->si_code | FPE_FLTINV)
     156              (*realvalueProc) (
     157                  info->si_addr); /* floating-point invalid result.  */
     158            if (info->si_code | FPE_FLTSUB)
     159              (*indexProc) (info->si_addr); /* subscript out of range.  */
     160          }
     161        break;
     162      default:
     163        perror ("not expecting to arrive here with this signal");
     164      }
     165  }
     166  
     167  void
     168  SysExceptions_InitExceptionHandlers (
     169      void (*indexf) (void *), void (*range) (void *), void (*casef) (void *),
     170      void (*invalidloc) (void *), void (*function) (void *),
     171      void (*wholevalue) (void *), void (*wholediv) (void *),
     172      void (*realvalue) (void *), void (*realdiv) (void *),
     173      void (*complexvalue) (void *), void (*complexdiv) (void *),
     174      void (*protection) (void *), void (*systemf) (void *),
     175      void (*coroutine) (void *), void (*exception) (void *))
     176  {
     177    struct sigaction old;
     178  
     179    indexProc = indexf;
     180    rangeProc = range;
     181    caseProc = casef;
     182    invalidlocProc = invalidloc;
     183    functionProc = function;
     184    wholevalueProc = wholevalue;
     185    wholedivProc = wholediv;
     186    realvalueProc = realvalue;
     187    realdivProc = realdiv;
     188    complexvalueProc = complexvalue;
     189    complexdivProc = complexdiv;
     190    protectionProc = protection;
     191    systemProc = systemf;
     192    coroutineProc = coroutine;
     193    exceptionProc = exception;
     194  
     195    sigbus.sa_sigaction = sigbusDespatcher;
     196    sigbus.sa_flags = (SA_SIGINFO);
     197    sigemptyset (&sigbus.sa_mask);
     198  
     199    if (sigaction (SIGBUS, &sigbus, &old) != 0)
     200      perror ("unable to install the sigbus signal handler");
     201  
     202    sigsegv.sa_sigaction = sigbusDespatcher;
     203    sigsegv.sa_flags = (SA_SIGINFO);
     204    sigemptyset (&sigsegv.sa_mask);
     205  
     206    if (sigaction (SIGSEGV, &sigsegv, &old) != 0)
     207      perror ("unable to install the sigsegv signal handler");
     208  
     209    sigfpe_.sa_sigaction = sigfpeDespatcher;
     210    sigfpe_.sa_flags = (SA_SIGINFO);
     211    sigemptyset (&sigfpe_.sa_mask);
     212  
     213    if (sigaction (SIGFPE, &sigfpe_, &old) != 0)
     214      perror ("unable to install the sigfpe signal handler");
     215  }
     216  
     217  #else
     218  void
     219  SysExceptions_InitExceptionHandlers (void *indexf, void *range, void *casef,
     220                                       void *invalidloc, void *function,
     221                                       void *wholevalue, void *wholediv,
     222                                       void *realvalue, void *realdiv,
     223                                       void *complexvalue, void *complexdiv,
     224                                       void *protection, void *systemf,
     225                                       void *coroutine, void *exception)
     226  {
     227  }
     228  #endif
     229  
     230  /* GNU Modula-2 linking fodder.  */
     231  
     232  void
     233  _M2_SysExceptions_init (int argc, char *argv[], char *envp[])
     234  {
     235  }
     236  
     237  void
     238  _M2_SysExceptions_finish (void)
     239  {
     240  }
     241  #ifdef __cplusplus
     242  }
     243  #endif