1 /* Translate Mach exception codes into signal numbers. i386 version.
2 Copyright (C) 1991-2022 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
exception2signal(struct hurd_signal_detail * detail,int * signo,int posix)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 }
libc_hidden_def(_hurd_exception2signal)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
_hurd_exception2signal_legacy(struct hurd_signal_detail * detail,int * signo)193 _hurd_exception2signal_legacy (struct hurd_signal_detail *detail, int *signo)
194 {
195 exception2signal (detail, signo, 0);
196 }
197