Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / mach / hurd / i386 / exc2signal.c
blobb67acff08de75c47ca8e471b4d9ea0d897f29a9c
1 /* Translate Mach exception codes into signal numbers. i386 version.
2 Copyright (C) 1991-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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 <http://www.gnu.org/licenses/>. */
19 #include <hurd.h>
20 #include <hurd/signal.h>
21 #include <mach/exception.h>
23 /* Translate the Mach exception codes, as received in an `exception_raise' RPC,
24 into a signal number and signal subcode. */
26 void
27 _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
29 detail->error = 0;
31 switch (detail->exc)
33 default:
34 *signo = SIGIOT;
35 detail->code = detail->exc;
36 break;
38 case EXC_BAD_ACCESS:
39 if (detail->exc_code == KERN_INVALID_ADDRESS
40 || detail->exc_code == KERN_PROTECTION_FAILURE
41 || detail->exc_code == KERN_WRITE_PROTECTION_FAILURE)
42 *signo = SIGSEGV;
43 else
44 *signo = SIGBUS;
45 detail->code = detail->exc_subcode;
46 detail->error = detail->exc_code;
47 break;
49 case EXC_BAD_INSTRUCTION:
50 *signo = SIGILL;
51 if (detail->exc_code == EXC_I386_INVOP)
52 detail->code = ILL_INVOPR_FAULT;
53 else if (detail->exc_code == EXC_I386_STKFLT)
54 detail->code = ILL_STACK_FAULT;
55 else
56 detail->code = 0;
57 break;
59 case EXC_ARITHMETIC:
60 switch (detail->exc_code)
62 case EXC_I386_DIV: /* integer divide by zero */
63 *signo = SIGFPE;
64 detail->code = FPE_INTDIV_FAULT;
65 break;
67 case EXC_I386_INTO: /* integer overflow */
68 *signo = SIGFPE;
69 detail->code = FPE_INTOVF_TRAP;
70 break;
72 /* These aren't anywhere documented or used in Mach 3.0. */
73 case EXC_I386_NOEXT:
74 case EXC_I386_EXTOVR:
75 default:
76 *signo = SIGFPE;
77 detail->code = 0;
78 break;
80 case EXC_I386_EXTERR:
81 /* Subcode is the fp_status word saved by the hardware.
82 Give an error code corresponding to the first bit set. */
83 if (detail->exc_subcode & FPS_IE)
85 *signo = SIGILL;
86 detail->code = ILL_FPEOPR_FAULT;
88 else if (detail->exc_subcode & FPS_DE)
90 *signo = SIGFPE;
91 detail->code = FPE_FLTDNR_FAULT;
93 else if (detail->exc_subcode & FPS_ZE)
95 *signo = SIGFPE;
96 detail->code = FPE_FLTDIV_FAULT;
98 else if (detail->exc_subcode & FPS_OE)
100 *signo = SIGFPE;
101 detail->code = FPE_FLTOVF_FAULT;
103 else if (detail->exc_subcode & FPS_UE)
105 *signo = SIGFPE;
106 detail->code = FPE_FLTUND_FAULT;
108 else if (detail->exc_subcode & FPS_PE)
110 *signo = SIGFPE;
111 detail->code = FPE_FLTINX_FAULT;
113 else
115 *signo = SIGFPE;
116 detail->code = 0;
118 break;
120 /* These two can only be arithmetic exceptions if we
121 are in V86 mode, which sounds like emulation to me.
122 (See Mach 3.0 i386/trap.c.) */
123 case EXC_I386_EMERR:
124 *signo = SIGFPE;
125 detail->code = FPE_EMERR_FAULT;
126 break;
127 case EXC_I386_BOUND:
128 *signo = SIGFPE;
129 detail->code = FPE_EMBND_FAULT;
130 break;
132 break;
134 case EXC_EMULATION:
135 /* 3.0 doesn't give this one, why, I don't know. */
136 *signo = SIGEMT;
137 detail->code = 0;
138 break;
140 case EXC_SOFTWARE:
141 /* The only time we get this in Mach 3.0
142 is for an out of bounds trap. */
143 if (detail->exc_code == EXC_I386_BOUND)
145 *signo = SIGFPE;
146 detail->code = FPE_SUBRNG_FAULT;
148 else
150 *signo = SIGEMT;
151 detail->code = 0;
153 break;
155 case EXC_BREAKPOINT:
156 *signo = SIGTRAP;
157 if (detail->exc_code == EXC_I386_SGL)
158 detail->code = DBG_SINGLE_TRAP;
159 else if (detail->exc_code == EXC_I386_BPT)
160 detail->code = DBG_BRKPNT_FAULT;
161 else
162 detail->code = 0;
163 break;