1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <hurd.h>
22: #include <hurd/signal.h>
23: #include "hurdfault.h"
24: #include <errno.h>
25: #include <string.h>
26: #include <setjmp.h>
27: #include <stdio.h>
28: #include <thread_state.h>
29: #include "faultexc_server.h"
30: #include <assert.h>
31:
32: jmp_buf _hurdsig_fault_env;
33: struct hurd_signal_preemptor _hurdsig_fault_preemptor = {0};
34:
35:
36: weak_alias (_hurdsig_fault_preemptor, _hurdsig_fault_preempter)
37:
38: static mach_port_t forward_sigexc;
39:
40: kern_return_t
41: _hurdsig_fault_catch_exception_raise (mach_port_t port,
42: thread_t thread,
43: task_t task,
44: #ifdef EXC_MASK_ALL
45: exception_type_t exception,
46: exception_data_t code,
47: mach_msg_type_number_t codeCnt
48: #else
49: integer_t exception,
50: integer_t code, integer_t subcode
51: #endif
52: )
53: {
54: int signo;
55: struct hurd_signal_detail d;
56:
57: if (port != forward_sigexc ||
58: thread != _hurd_msgport_thread || task != __mach_task_self ())
59: return EPERM;
60:
61: d.exc = exception;
62: #ifdef EXC_MASK_ALL
63: assert (codeCnt >= 2);
64: d.exc_code = code[0];
65: d.exc_subcode = code[1];
66: #else
67: d.exc_code = code;
68: d.exc_subcode = subcode;
69: #endif
70:
71:
72:
73: _hurd_exception2signal (&d, &signo);
74:
75: return HURD_PREEMPT_SIGNAL_P (&_hurdsig_fault_preemptor, signo, d.code)
76: ? 0 : EGREGIOUS;
77: }
78:
79: #ifdef EXC_MASK_ALL
80:
81:
82:
83:
84: kern_return_t
85: _hurdsig_fault_catch_exception_raise_state
86: (mach_port_t port,
87: exception_type_t exception,
88: exception_data_t code,
89: mach_msg_type_number_t codeCnt,
90: int *flavor,
91: thread_state_t old_state,
92: mach_msg_type_number_t old_stateCnt,
93: thread_state_t new_state,
94: mach_msg_type_number_t *new_stateCnt)
95: {
96: abort ();
97: return KERN_FAILURE;
98: }
99:
100: kern_return_t
101: _hurdsig_fault_catch_exception_raise_state_identity
102: (mach_port_t exception_port,
103: thread_t thread,
104: task_t task,
105: exception_type_t exception,
106: exception_data_t code,
107: mach_msg_type_number_t codeCnt,
108: int *flavor,
109: thread_state_t old_state,
110: mach_msg_type_number_t old_stateCnt,
111: thread_state_t new_state,
112: mach_msg_type_number_t *new_stateCnt)
113: {
114: abort ();
115: return KERN_FAILURE;
116: }
117: #endif
118:
119:
120: #ifdef NDR_CHAR_ASCII
121: # define mig_reply_header_t mig_reply_error_t
122: #endif
123:
124: static void
125: faulted (void)
126: {
127: struct
128: {
129: mach_msg_header_t head;
130: char buf[64];
131: } request;
132: mig_reply_header_t reply;
133: extern int _hurdsig_fault_exc_server (mach_msg_header_t *,
134: mach_msg_header_t *);
135:
136:
137:
138: if (__mach_msg (&request.head, MACH_RCV_MSG, 0,
139: sizeof request, forward_sigexc,
140: MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)
141: != MACH_MSG_SUCCESS)
142: __libc_fatal ("msg receive failed on signal thread exc\n");
143:
144:
145:
146: _hurdsig_fault_exc_server (&request.head, &reply.Head);
147: if (reply.Head.msgh_remote_port != MACH_PORT_NULL)
148: __mach_msg (&reply.Head, MACH_SEND_MSG, reply.Head.msgh_size,
149: 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
150: if (reply.RetCode == MIG_BAD_ID)
151: __mach_msg_destroy (&request.head);
152:
153: if (reply.RetCode)
154: __libc_fatal ("BUG: unexpected fault in signal thread\n");
155:
156: _hurdsig_fault_preemptor.signals = 0;
157: longjmp (_hurdsig_fault_env, 1);
158: }
159:
160: static char faultstack[1024];
161:
162:
163:
164:
165:
166:
167: void
168: _hurdsig_fault_init (void)
169: {
170: error_t err;
171: struct machine_thread_state state;
172: mach_port_t sigexc;
173:
174:
175:
176: err = __mach_port_allocate (__mach_task_self (),
177: MACH_PORT_RIGHT_RECEIVE, &sigexc);
178: assert_perror (err);
179: err = __mach_port_allocate (__mach_task_self (),
180: MACH_PORT_RIGHT_RECEIVE, &forward_sigexc);
181: assert_perror (err);
182:
183:
184:
185: err = __mach_port_insert_right (__mach_task_self (), sigexc,
186: sigexc, MACH_MSG_TYPE_MAKE_SEND);
187: assert_perror (err);
188:
189:
190:
191:
192: #ifdef MACH_PORT_RECEIVE_STATUS_COUNT
193: {
194: const mach_port_limits_t lim = { mpl_qlimit: 1 };
195: assert (MACH_PORT_RECEIVE_STATUS_COUNT == sizeof lim / sizeof (natural_t));
196: err = __mach_port_set_attributes (__mach_task_self (), forward_sigexc,
197: MACH_PORT_RECEIVE_STATUS,
198: (mach_port_info_t) &lim,
199: MACH_PORT_RECEIVE_STATUS_COUNT);
200: }
201: #else
202: err = __mach_port_set_qlimit (__mach_task_self (), forward_sigexc, 1);
203: #endif
204: assert_perror (err);
205:
206:
207:
208: memset (&state, 0, sizeof state);
209: MACHINE_THREAD_STATE_SET_PC (&state, faulted);
210: MACHINE_THREAD_STATE_SET_SP (&state, faultstack, sizeof faultstack);
211:
212: err = __USEPORT
213: (PROC,
214: __proc_handle_exceptions (port,
215: sigexc,
216: forward_sigexc, MACH_MSG_TYPE_MAKE_SEND,
217: MACHINE_THREAD_STATE_FLAVOR,
218: (natural_t *) &state,
219: MACHINE_THREAD_STATE_COUNT));
220: assert_perror (err);
221:
222:
223: #ifdef THREAD_EXCEPTION_PORT
224: err = __thread_set_special_port (_hurd_msgport_thread,
225: THREAD_EXCEPTION_PORT, sigexc);
226: #elif defined (EXC_MASK_ALL)
227: __thread_set_exception_ports (_hurd_msgport_thread,
228: EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
229: | EXC_MASK_MACH_SYSCALL
230: | EXC_MASK_RPC_ALERT),
231: sigexc,
232: EXCEPTION_STATE_IDENTITY,
233: MACHINE_THREAD_STATE);
234: #else
235: # error thread_set_exception_ports?
236: #endif
237: __mach_port_deallocate (__mach_task_self (), sigexc);
238: assert_perror (err);
239: }