]>
Commit | Line | Data |
---|---|---|
28f540f4 | 1 | /* Translate Mach exception codes into signal numbers. i386 version. |
2b778ceb | 2 | Copyright (C) 1991-2021 Free Software Foundation, Inc. |
478b92f0 | 3 | This file is part of the GNU C Library. |
28f540f4 | 4 | |
478b92f0 | 5 | The GNU C Library is free software; you can redistribute it and/or |
41bdb6e2 AJ |
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. | |
28f540f4 | 9 | |
478b92f0 UD |
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 | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
28f540f4 | 14 | |
41bdb6e2 | 15 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 | 16 | License along with the GNU C Library; if not, see |
5a82c748 | 17 | <https://www.gnu.org/licenses/>. */ |
28f540f4 RM |
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 | ||
d865ff74 JK |
26 | static void |
27 | exception2signal (struct hurd_signal_detail *detail, int *signo, int posix) | |
28f540f4 | 28 | { |
0e3426bb | 29 | detail->error = 0; |
28f540f4 | 30 | |
0e3426bb | 31 | switch (detail->exc) |
28f540f4 RM |
32 | { |
33 | default: | |
34 | *signo = SIGIOT; | |
0e3426bb | 35 | detail->code = detail->exc; |
28f540f4 | 36 | break; |
0e3426bb | 37 | |
28f540f4 | 38 | case EXC_BAD_ACCESS: |
d865ff74 JK |
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 | } | |
0e3426bb | 58 | detail->error = detail->exc_code; |
28f540f4 RM |
59 | break; |
60 | ||
61 | case EXC_BAD_INSTRUCTION: | |
62 | *signo = SIGILL; | |
d865ff74 JK |
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 | } | |
28f540f4 | 77 | break; |
0e3426bb | 78 | |
28f540f4 | 79 | case EXC_ARITHMETIC: |
d865ff74 | 80 | *signo = SIGFPE; |
0e3426bb | 81 | switch (detail->exc_code) |
28f540f4 RM |
82 | { |
83 | case EXC_I386_DIV: /* integer divide by zero */ | |
d865ff74 | 84 | detail->code = posix ? FPE_INTDIV : FPE_INTDIV_FAULT; |
28f540f4 | 85 | break; |
0e3426bb | 86 | |
28f540f4 | 87 | case EXC_I386_INTO: /* integer overflow */ |
d865ff74 | 88 | detail->code = posix ? FPE_INTOVF : FPE_INTOVF_TRAP; |
28f540f4 RM |
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: | |
0e3426bb | 95 | detail->code = 0; |
28f540f4 RM |
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. */ | |
0e3426bb | 101 | if (detail->exc_subcode & FPS_IE) |
28f540f4 | 102 | { |
d865ff74 JK |
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*/; | |
28f540f4 | 106 | } |
0e3426bb | 107 | else if (detail->exc_subcode & FPS_DE) |
28f540f4 | 108 | { |
d865ff74 | 109 | detail->code = posix ? FPE_FLTUND : FPE_FLTDNR_FAULT; |
28f540f4 | 110 | } |
0e3426bb | 111 | else if (detail->exc_subcode & FPS_ZE) |
28f540f4 | 112 | { |
d865ff74 | 113 | detail->code = posix ? FPE_FLTDIV : FPE_FLTDIV_FAULT; |
28f540f4 | 114 | } |
0e3426bb | 115 | else if (detail->exc_subcode & FPS_OE) |
28f540f4 | 116 | { |
d865ff74 | 117 | detail->code = posix ? FPE_FLTOVF : FPE_FLTOVF_FAULT; |
28f540f4 | 118 | } |
0e3426bb | 119 | else if (detail->exc_subcode & FPS_UE) |
28f540f4 | 120 | { |
d865ff74 | 121 | detail->code = posix ? FPE_FLTUND : FPE_FLTUND_FAULT; |
28f540f4 | 122 | } |
0e3426bb | 123 | else if (detail->exc_subcode & FPS_PE) |
28f540f4 | 124 | { |
d865ff74 | 125 | detail->code = posix ? FPE_FLTRES : FPE_FLTINX_FAULT; |
28f540f4 RM |
126 | } |
127 | else | |
128 | { | |
0e3426bb | 129 | detail->code = 0; |
28f540f4 RM |
130 | } |
131 | break; | |
132 | ||
0e3426bb | 133 | /* These two can only be arithmetic exceptions if we |
d865ff74 | 134 | are in V86 mode. (See Mach 3.0 i386/trap.c.) */ |
28f540f4 | 135 | case EXC_I386_EMERR: |
d865ff74 | 136 | detail->code = posix ? 0 : FPE_EMERR_FAULT; |
28f540f4 RM |
137 | break; |
138 | case EXC_I386_BOUND: | |
d865ff74 | 139 | detail->code = posix ? FPE_FLTSUB : FPE_EMBND_FAULT; |
28f540f4 RM |
140 | break; |
141 | } | |
142 | break; | |
143 | ||
0e3426bb | 144 | case EXC_EMULATION: |
28f540f4 RM |
145 | /* 3.0 doesn't give this one, why, I don't know. */ |
146 | *signo = SIGEMT; | |
0e3426bb | 147 | detail->code = 0; |
28f540f4 RM |
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. */ | |
0e3426bb | 153 | if (detail->exc_code == EXC_I386_BOUND) |
28f540f4 RM |
154 | { |
155 | *signo = SIGFPE; | |
d865ff74 | 156 | detail->code = posix ? FPE_FLTSUB : FPE_SUBRNG_FAULT; |
28f540f4 RM |
157 | } |
158 | else | |
159 | { | |
160 | *signo = SIGEMT; | |
0e3426bb | 161 | detail->code = 0; |
28f540f4 RM |
162 | } |
163 | break; | |
0e3426bb | 164 | |
28f540f4 RM |
165 | case EXC_BREAKPOINT: |
166 | *signo = SIGTRAP; | |
d865ff74 JK |
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 | } | |
28f540f4 RM |
181 | break; |
182 | } | |
183 | } | |
ff297b70 | 184 | libc_hidden_def (_hurd_exception2signal) |
d865ff74 JK |
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 | } |