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