(root)/
glibc-2.38/
sysdeps/
mach/
hurd/
x86/
exc2signal.c
       1  /* Translate Mach exception codes into signal numbers.  i386 version.
       2     Copyright (C) 1991-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <hurd.h>
      20  #include <hurd/signal.h>
      21  #include <mach/exception.h>
      22  
      23  /* Translate the Mach exception codes, as received in an `exception_raise' RPC,
      24     into a signal number and signal subcode.  */
      25  
      26  static void
      27  exception2signal (struct hurd_signal_detail *detail, int *signo, int posix)
      28  {
      29    detail->error = 0;
      30  
      31    switch (detail->exc)
      32      {
      33      default:
      34        *signo = SIGIOT;
      35        detail->code = detail->exc;
      36        break;
      37  
      38      case EXC_BAD_ACCESS:
      39        switch (detail->exc_code)
      40          {
      41  	case KERN_INVALID_ADDRESS:
      42  	case KERN_MEMORY_FAILURE:
      43  	  *signo = SIGSEGV;
      44  	  detail->code = posix ? SEGV_MAPERR : detail->exc_subcode;
      45  	  break;
      46  
      47  	case KERN_PROTECTION_FAILURE:
      48  	case KERN_WRITE_PROTECTION_FAILURE:
      49  	  *signo = SIGSEGV;
      50  	  detail->code = posix ? SEGV_ACCERR : detail->exc_subcode;
      51  	  break;
      52  
      53  	default:
      54  	  *signo = SIGBUS;
      55  	  detail->code = posix ? BUS_ADRERR : detail->exc_subcode;
      56  	  break;
      57  	}
      58        detail->error = detail->exc_code;
      59        break;
      60  
      61      case EXC_BAD_INSTRUCTION:
      62        *signo = SIGILL;
      63        switch (detail->exc_code)
      64          {
      65  	case EXC_I386_INVOP:
      66  	  detail->code = posix ? ILL_ILLOPC : ILL_INVOPR_FAULT;
      67  	  break;
      68  
      69  	case EXC_I386_STKFLT:
      70  	  detail->code = posix ? ILL_BADSTK : ILL_STACK_FAULT;
      71  	  break;
      72  
      73  	default:
      74  	  detail->code = 0;
      75  	  break;
      76  	}
      77        break;
      78  
      79      case EXC_ARITHMETIC:
      80        *signo = SIGFPE;
      81        switch (detail->exc_code)
      82  	{
      83  	case EXC_I386_DIV:	/* integer divide by zero */
      84  	  detail->code = posix ? FPE_INTDIV : FPE_INTDIV_FAULT;
      85  	  break;
      86  
      87  	case EXC_I386_INTO:	/* integer overflow */
      88  	  detail->code = posix ? FPE_INTOVF : FPE_INTOVF_TRAP;
      89  	  break;
      90  
      91  	  /* These aren't anywhere documented or used in Mach 3.0.  */
      92  	case EXC_I386_NOEXT:
      93  	case EXC_I386_EXTOVR:
      94  	default:
      95  	  detail->code = 0;
      96  	  break;
      97  
      98  	case EXC_I386_EXTERR:
      99  	  /* Subcode is the fp_status word saved by the hardware.
     100  	     Give an error code corresponding to the first bit set.  */
     101  	  if (detail->exc_subcode & FPS_IE)
     102  	    {
     103  	      /* NB: We used to send SIGILL here but we can't distinguish
     104  		 POSIX vs. legacy with respect to what signal we send.  */
     105  	      detail->code = posix ? FPE_FLTINV : 0 /*ILL_FPEOPR_FAULT*/;
     106  	    }
     107  	  else if (detail->exc_subcode & FPS_DE)
     108  	    {
     109  	      detail->code = posix ? FPE_FLTUND : FPE_FLTDNR_FAULT;
     110  	    }
     111  	  else if (detail->exc_subcode & FPS_ZE)
     112  	    {
     113  	      detail->code = posix ? FPE_FLTDIV : FPE_FLTDIV_FAULT;
     114  	    }
     115  	  else if (detail->exc_subcode & FPS_OE)
     116  	    {
     117  	      detail->code = posix ? FPE_FLTOVF : FPE_FLTOVF_FAULT;
     118  	    }
     119  	  else if (detail->exc_subcode & FPS_UE)
     120  	    {
     121  	      detail->code = posix ? FPE_FLTUND : FPE_FLTUND_FAULT;
     122  	    }
     123  	  else if (detail->exc_subcode & FPS_PE)
     124  	    {
     125  	      detail->code = posix ? FPE_FLTRES : FPE_FLTINX_FAULT;
     126  	    }
     127  	  else
     128  	    {
     129  	      detail->code = 0;
     130  	    }
     131  	  break;
     132  
     133  	  /* These two can only be arithmetic exceptions if we
     134  	     are in V86 mode.  (See Mach 3.0 i386/trap.c.)  */
     135  	case EXC_I386_EMERR:
     136  	  detail->code = posix ? 0 : FPE_EMERR_FAULT;
     137  	  break;
     138  	case EXC_I386_BOUND:
     139  	  detail->code = posix ? FPE_FLTSUB : FPE_EMBND_FAULT;
     140  	  break;
     141  	}
     142        break;
     143  
     144      case EXC_EMULATION:
     145        /* 3.0 doesn't give this one, why, I don't know.  */
     146        *signo = SIGEMT;
     147        detail->code = 0;
     148        break;
     149  
     150      case EXC_SOFTWARE:
     151        /* The only time we get this in Mach 3.0
     152  	 is for an out of bounds trap.  */
     153        if (detail->exc_code == EXC_I386_BOUND)
     154  	{
     155  	  *signo = SIGFPE;
     156  	  detail->code = posix ? FPE_FLTSUB : FPE_SUBRNG_FAULT;
     157  	}
     158        else
     159  	{
     160  	  *signo = SIGEMT;
     161  	  detail->code = 0;
     162  	}
     163        break;
     164  
     165      case EXC_BREAKPOINT:
     166        *signo = SIGTRAP;
     167        switch (detail->exc_code)
     168          {
     169  	case EXC_I386_SGL:
     170  	  detail->code = posix ? TRAP_BRKPT : DBG_SINGLE_TRAP;
     171  	  break;
     172  
     173  	case EXC_I386_BPT:
     174  	  detail->code = posix ? TRAP_BRKPT : DBG_BRKPNT_FAULT;
     175  	  break;
     176  
     177  	default:
     178  	  detail->code = 0;
     179  	  break;
     180  	}
     181        break;
     182      }
     183  }
     184  libc_hidden_def (_hurd_exception2signal)
     185  
     186  void
     187  _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
     188  {
     189    exception2signal (detail, signo, 1);
     190  }
     191  
     192  void
     193  _hurd_exception2signal_legacy (struct hurd_signal_detail *detail, int *signo)
     194  {
     195    exception2signal (detail, signo, 0);
     196  }