|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Mach Operating System
24: * Copyright (c) 1987 Carnegie-Mellon University
25: * All rights reserved. The CMU software License Agreement specifies
26: * the terms and conditions for use and redistribution.
27: */
28:
29: /*
30: *********************************************************************
31: * HISTORY
32: **********************************************************************
33: */
34:
35: #include <sys/param.h>
36:
37: #include <mach/boolean.h>
38: #include <mach/exception.h>
39: #include <mach/kern_return.h>
40: #include <mach/message.h>
41: #include <mach/port.h>
42: #include <mach/mig_errors.h>
43: #include <kern/task.h>
44: #include <kern/thread.h>
45: #include <kern/thread_act.h>
46: #include <kern/kalloc.h>
47:
48: #include <sys/proc.h>
49: #include <sys/user.h>
50: #include <sys/ux_exception.h>
51:
52: /*
53: * Unix exception handler.
54: */
55:
56: static void ux_exception();
57:
58: decl_simple_lock_data(static, ux_handler_init_lock)
59: mach_port_name_t ux_exception_port;
60: static task_t ux_handler_self;
61:
62: static
63: void
64: ux_handler(void)
65: {
66: task_t self = current_task();
67: mach_port_name_t exc_port_name;
68: mach_port_name_t exc_set_name;
69:
70: (void) thread_set_funneled(TRUE);
71:
72: /* self->kernel_vm_space = TRUE; */
73: ux_handler_self = self;
74:
75:
76: /*
77: * Allocate a port set that we will receive on.
78: */
79: if (mach_port_allocate(get_task_ipcspace(ux_handler_self), MACH_PORT_RIGHT_PORT_SET, &exc_set_name) != MACH_MSG_SUCCESS)
80: panic("ux_handler: port_set_allocate failed");
81:
82: /*
83: * Allocate an exception port and use object_copyin to
84: * translate it to the global name. Put it into the set.
85: */
86: if (mach_port_allocate(get_task_ipcspace(ux_handler_self), MACH_PORT_RIGHT_RECEIVE, &exc_port_name) != MACH_MSG_SUCCESS)
87: panic("ux_handler: port_allocate failed");
88: if (mach_port_move_member(get_task_ipcspace(ux_handler_self),
89: exc_port_name, exc_set_name) != MACH_MSG_SUCCESS)
90: panic("ux_handler: port_set_add failed");
91:
92: if (ipc_object_copyin(get_task_ipcspace(self), exc_port_name,
93: MACH_MSG_TYPE_MAKE_SEND,
94: (void *) &ux_exception_port) != MACH_MSG_SUCCESS)
95: panic("ux_handler: object_copyin(ux_exception_port) failed");
96:
97: thread_wakeup(&ux_exception_port);
98:
99: /* Message handling loop. */
100:
101: for (;;) {
102: struct rep_msg {
103: mach_msg_header_t Head;
104: NDR_record_t NDR;
105: kern_return_t RetCode;
106: } rep_msg;
107: struct exc_msg {
108: mach_msg_header_t Head;
109: /* start of the kernel processed data */
110: mach_msg_body_t msgh_body;
111: mach_msg_port_descriptor_t thread;
112: mach_msg_port_descriptor_t task;
113: /* end of the kernel processed data */
114: NDR_record_t NDR;
115: exception_type_t exception;
116: mach_msg_type_number_t codeCnt;
117: exception_data_t code;
118: /* some times RCV_TO_LARGE probs */
119: char pad[512];
120: } exc_msg;
121: mach_port_name_t reply_port;
122: kern_return_t result;
123:
124: exc_msg.Head.msgh_local_port = (mach_port_t)exc_set_name;
125: exc_msg.Head.msgh_size = sizeof (exc_msg);
126: #if 0
127: result = mach_msg_receive(&exc_msg.Head);
128: #else
129: result = mach_msg_receive(&exc_msg.Head, MACH_RCV_MSG,
130: sizeof (exc_msg), exc_set_name,
131: MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL,
132: 0);
133: #endif
134: if (result == MACH_MSG_SUCCESS) {
135: reply_port = (mach_port_name_t)exc_msg.Head.msgh_remote_port;
136:
137: if (exc_server(&exc_msg.Head, &rep_msg.Head))
138: (void) mach_msg_send(&rep_msg.Head, MACH_SEND_MSG,
139: sizeof (rep_msg),MACH_MSG_TIMEOUT_NONE,MACH_PORT_NULL);
140:
141: if (reply_port != MACH_PORT_NULL)
142: (void) mach_port_deallocate(get_task_ipcspace(ux_handler_self), reply_port);
143: }
144: else if (result == MACH_RCV_TOO_LARGE)
145: /* ignore oversized messages */;
146: else
147: panic("exception_handler");
148: }
149: }
150:
151: void
152: ux_handler_init(void)
153: {
154: task_t handler_task;
155:
156: simple_lock_init(&ux_handler_init_lock);
157: ux_exception_port = MACH_PORT_NULL;
158: if (kernel_task_create(kernel_task,
159: 0, 0, &handler_task) != MACH_MSG_SUCCESS) {
160: panic("Failed to created ux handler task\n");
161: }
162: (void) kernel_thread(handler_task, ux_handler);
163: simple_lock(&ux_handler_init_lock);
164: if (ux_exception_port == MACH_PORT_NULL) {
165: simple_unlock(&ux_handler_init_lock);
166: assert_wait(&ux_exception_port, THREAD_UNINT);
167: thread_block((void (*)(void)) 0);
168: }
169: else
170: simple_unlock(&ux_handler_init_lock);
171: }
172:
173: kern_return_t
174: catch_exception_raise(
175: mach_port_name_t exception_port,
176: mach_port_name_t thread_name,
177: mach_port_name_t task_name,
178: int exception,
179: exception_data_t code,
180: mach_msg_type_number_t codecnt
181: )
182: {
183: task_t self = current_task();
184: thread_act_t th_act;
185: ipc_port_t thread_port;
186: ipc_port_t task_port;
187: kern_return_t result = MACH_MSG_SUCCESS;
188: int signal = 0;
189: u_long ucode = 0;
190: struct uthread *ut;
191:
192: /*
193: * Convert local thread name to global port.
194: */
195:
196: if (ipc_object_copyin(get_task_ipcspace(self), thread_name,
197: MACH_MSG_TYPE_PORT_SEND,
198: (void *) &thread_port) == MACH_MSG_SUCCESS) {
199:
200: th_act = (thread_act_t)convert_port_to_act(thread_port);
201: ipc_port_release(thread_port);
202:
203: /*
204: * Catch bogus ports
205: */
206: if (th_act != THREAD_NULL) {
207:
208: /*
209: * Convert exception to unix signal and code.
210: */
211: ut = get_bsdthread_info(th_act);
212: ux_exception(exception, code[0], code[1],
213: &signal, &ucode);
214:
215: /*
216: * Send signal.
217: */
218: if (signal != 0)
219: threadsignal(th_act, signal, ucode);
220:
221: act_deallocate(th_act);
222: }
223: else
224: result = KERN_INVALID_ARGUMENT;
225: }
226: else
227: result = KERN_INVALID_ARGUMENT;
228:
229: /*
230: * Delete our send rights to the task and thread ports.
231: */
232: (void)mach_port_deallocate(get_task_ipcspace(ux_handler_self), task_name);
233: (void)mach_port_deallocate(get_task_ipcspace(ux_handler_self),thread_name);
234:
235: return (result);
236: }
237: kern_return_t
238: catch_exception_raise_state(mach_port_name_t exception_port, int exception, exception_data_t code, mach_msg_type_number_t codeCnt, int flavor, thread_state_t old_state, int old_stateCnt, thread_state_t new_state, int new_stateCnt)
239: {
240: return(KERN_INVALID_ARGUMENT);
241: }
242: kern_return_t
243: catch_exception_raise_state_identity(mach_port_name_t exception_port, mach_port_t thread, mach_port_t task, int exception, exception_data_t code, mach_msg_type_number_t codeCnt, int flavor, thread_state_t old_state, int old_stateCnt, thread_state_t new_state, int new_stateCnt)
244: {
245: return(KERN_INVALID_ARGUMENT);
246: }
247:
248: boolean_t machine_exception();
249:
250: /*
251: * ux_exception translates a mach exception, code and subcode to
252: * a signal and u.u_code. Calls machine_exception (machine dependent)
253: * to attempt translation first.
254: */
255:
256: static
257: void ux_exception(
258: int exception,
259: int code,
260: int subcode,
261: int *ux_signal,
262: int *ux_code
263: )
264: {
265: /*
266: * Try machine-dependent translation first.
267: */
268: if (machine_exception(exception, code, subcode, ux_signal, ux_code))
269: return;
270:
271: switch(exception) {
272:
273: case EXC_BAD_ACCESS:
274: if (code == KERN_INVALID_ADDRESS)
275: *ux_signal = SIGSEGV;
276: else
277: *ux_signal = SIGBUS;
278: break;
279:
280: case EXC_BAD_INSTRUCTION:
281: *ux_signal = SIGILL;
282: break;
283:
284: case EXC_ARITHMETIC:
285: *ux_signal = SIGFPE;
286: break;
287:
288: case EXC_EMULATION:
289: *ux_signal = SIGEMT;
290: break;
291:
292: case EXC_SOFTWARE:
293: switch (code) {
294:
295: case EXC_UNIX_BAD_SYSCALL:
296: *ux_signal = SIGSYS;
297: break;
298: case EXC_UNIX_BAD_PIPE:
299: *ux_signal = SIGPIPE;
300: break;
301: case EXC_UNIX_ABORT:
302: *ux_signal = SIGABRT;
303: break;
304: }
305: break;
306:
307: case EXC_BREAKPOINT:
308: *ux_signal = SIGTRAP;
309: break;
310: }
311: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.