]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/mach/hurd/i386/exc2signal.c
initial import
[thirdparty/glibc.git] / sysdeps / mach / hurd / i386 / exc2signal.c
1 /* Translate Mach exception codes into signal numbers. i386 version.
2 Copyright (C) 1991, 1992, 1994 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 Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
19
20 #include <hurd.h>
21 #include <hurd/signal.h>
22 #include <mach/exception.h>
23
24 /* Translate the Mach exception codes, as received in an `exception_raise' RPC,
25 into a signal number and signal subcode. */
26
27 void
28 _hurd_exception2signal (int exception, int code, int subcode,
29 int *signo, long int *sigcode, int *error)
30 {
31 *error = 0;
32
33 switch (exception)
34 {
35 default:
36 *signo = SIGIOT;
37 *sigcode = exception;
38 break;
39
40 case EXC_BAD_ACCESS:
41 if (code == KERN_PROTECTION_FAILURE)
42 *signo = SIGSEGV;
43 else
44 *signo = SIGBUS;
45 *sigcode = subcode;
46 *error = code;
47 break;
48
49 case EXC_BAD_INSTRUCTION:
50 *signo = SIGILL;
51 if (code == EXC_I386_INVOP)
52 *sigcode = ILL_INVOPR_FAULT;
53 else if (code == EXC_I386_STKFLT)
54 *sigcode = ILL_STACK_FAULT;
55 else
56 *sigcode = 0;
57 break;
58
59 case EXC_ARITHMETIC:
60 switch (code)
61 {
62 case EXC_I386_DIV: /* integer divide by zero */
63 *signo = SIGFPE;
64 *sigcode = FPE_INTDIV_FAULT;
65 break;
66
67 case EXC_I386_INTO: /* integer overflow */
68 *signo = SIGFPE;
69 *sigcode = FPE_INTOVF_TRAP;
70 break;
71
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 *sigcode = 0;
78 break;
79
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 (subcode & FPS_IE)
84 {
85 *signo = SIGILL;
86 *sigcode = ILL_FPEOPR_FAULT;
87 }
88 else if (subcode & FPS_DE)
89 {
90 *signo = SIGFPE;
91 *sigcode = FPE_FLTDNR_FAULT;
92 }
93 else if (subcode & FPS_ZE)
94 {
95 *signo = SIGFPE;
96 *sigcode = FPE_FLTDIV_FAULT;
97 }
98 else if (subcode & FPS_OE)
99 {
100 *signo = SIGFPE;
101 *sigcode = FPE_FLTOVF_FAULT;
102 }
103 else if (subcode & FPS_UE)
104 {
105 *signo = SIGFPE;
106 *sigcode = FPE_FLTUND_FAULT;
107 }
108 else if (subcode & FPS_PE)
109 {
110 *signo = SIGFPE;
111 *sigcode = FPE_FLTINX_FAULT;
112 }
113 else
114 {
115 *signo = SIGFPE;
116 *sigcode = 0;
117 }
118 break;
119
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 *sigcode = FPE_EMERR_FAULT;
126 break;
127 case EXC_I386_BOUND:
128 *signo = SIGFPE;
129 *sigcode = FPE_EMBND_FAULT;
130 break;
131 }
132 break;
133
134 case EXC_EMULATION:
135 /* 3.0 doesn't give this one, why, I don't know. */
136 *signo = SIGEMT;
137 *sigcode = 0;
138 break;
139
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 (code == EXC_I386_BOUND)
144 {
145 *signo = SIGFPE;
146 *sigcode = FPE_SUBRNG_FAULT;
147 }
148 else
149 {
150 *signo = SIGEMT;
151 *sigcode = 0;
152 }
153 break;
154
155 case EXC_BREAKPOINT:
156 *signo = SIGTRAP;
157 if (code == EXC_I386_SGL)
158 *sigcode = DBG_SINGLE_TRAP;
159 else if (code == EXC_I386_BPT)
160 *sigcode = DBG_BRKPNT_FAULT;
161 else
162 *sigcode = 0;
163 break;
164 }
165 }