|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1987 Carnegie-Mellon University
28: * All rights reserved. The CMU software License Agreement specifies
29: * the terms and conditions for use and redistribution.
30: */
31:
32: /*
33: *********************************************************************
34: *
35: * 1-Oct-87 David Black (dlb) at Carnegie-Mellon University
36: * Created
37: *
38: **********************************************************************
39: */
40:
41: #import <sys/param.h>
42:
43: #import <mach/boolean.h>
44: #import <mach/exception.h>
45: #import <mach/kern_return.h>
46: #import <mach/message.h>
47: #import <mach/port.h>
48: #import <kern/task.h>
49: #import <kern/thread.h>
50: #import <sys/proc.h>
51: #import <sys/ux_exception.h>
52: #import <mach/mig_errors.h>
53: #import <kern/kalloc.h>
54:
55: #import <mach/mach_user_internal.h>
56:
57: #import <kern/sched_prim.h>
58:
59: /*
60: * Unix exception handler.
61: */
62:
63: static void ux_exception();
64:
65: decl_simple_lock_data(static, ux_handler_init_lock)
66: port_t ux_exception_port;
67: static port_t ux_handler_self;
68:
69: static
70: void
71: ux_handler(void)
72: {
73: task_t self = current_task();
74: port_name_t exc_port_name;
75: port_set_name_t exc_set_name;
76:
77:
78: self->kernel_vm_space = TRUE;
79: ux_handler_self = task_self();
80:
81: simple_lock(&ux_handler_init_lock);
82:
83: /*
84: * Allocate a port set that we will receive on.
85: */
86: if (port_set_allocate(ux_handler_self, &exc_set_name) != KERN_SUCCESS)
87: panic("ux_handler: port_set_allocate failed");
88:
89: /*
90: * Allocate an exception port and use object_copyin to
91: * translate it to the global name. Put it into the set.
92: */
93: if (port_allocate(ux_handler_self, &exc_port_name) != KERN_SUCCESS)
94: panic("ux_handler: port_allocate failed");
95: if (port_set_add(ux_handler_self,
96: exc_set_name, exc_port_name) != KERN_SUCCESS)
97: panic("ux_handler: port_set_add failed");
98: if (!object_copyin(self, exc_port_name,
99: MSG_TYPE_PORT, FALSE,
100: (void *) &ux_exception_port))
101: panic("ux_handler: object_copyin(ux_exception_port) failed");
102:
103: /*
104: * Release kernel to continue.
105: */
106: thread_wakeup(&ux_exception_port);
107: simple_unlock(&ux_handler_init_lock);
108:
109: /* Message handling loop. */
110:
111: for (;;) {
112: struct rep_msg {
113: msg_header_t h;
114: int d[4];
115: } rep_msg;
116: struct exc_msg {
117: msg_header_t h;
118: int d[16]; /* max is actually 10 */
119: } exc_msg;
120: port_t reply_port;
121: msg_return_t result;
122:
123: exc_msg.h.msg_local_port = exc_set_name;
124: exc_msg.h.msg_size = sizeof (exc_msg);
125:
126: result = msg_receive(&exc_msg.h, MSG_OPTION_NONE, 0);
127:
128: if (result == RCV_SUCCESS) {
129: reply_port = exc_msg.h.msg_remote_port;
130:
131: if (exc_server(&exc_msg.h, &rep_msg.h))
132: (void) msg_send(&rep_msg.h, MSG_OPTION_NONE, 0);
133:
134: if (reply_port != PORT_NULL)
135: (void) port_deallocate(ux_handler_self, reply_port);
136: }
137: else if (result == RCV_TOO_LARGE)
138: /* ignore oversized messages */;
139: else
140: panic("exception_handler");
141: }
142: }
143:
144: void
145: ux_handler_init(void)
146: {
147: task_t handler_task;
148:
149: simple_lock_init(&ux_handler_init_lock);
150: ux_exception_port = PORT_NULL;
151: handler_task = kernel_task_create(kernel_task, 0);
152: (void) kernel_thread(handler_task, ux_handler, (void *)0);
153: simple_lock(&ux_handler_init_lock);
154: if (ux_exception_port == PORT_NULL)
155: thread_sleep(&ux_exception_port,
156: simple_lock_addr(ux_handler_init_lock), FALSE);
157: else
158: simple_unlock(&ux_handler_init_lock);
159: }
160:
161: kern_return_t
162: catch_exception_raise(
163: port_t exception_port,
164: port_t thread_name,
165: port_t task_name,
166: int exception,
167: int code,
168: int subcode
169: )
170: {
171: task_t self = current_task();
172: thread_t thread;
173: port_t thread_port;
174: kern_return_t result = KERN_SUCCESS;
175: int signal = 0;
176: u_long ucode = 0;
177:
178: /*
179: * Convert local thread name to global port.
180: */
181:
182: if (object_copyin(self, thread_name,
183: MSG_TYPE_PORT, FALSE,
184: (void *) &thread_port)) {
185:
186: thread = convert_port_to_thread(thread_port);
187: port_release(thread_port);
188:
189: /*
190: * Catch bogus ports
191: */
192: if (thread != THREAD_NULL) {
193:
194: /*
195: * Convert exception to unix signal and code.
196: */
197: ux_exception(exception, code, subcode, &signal, &ucode);
198:
199: /*
200: * Send signal.
201: */
202: if (signal != 0)
203: threadsignal(thread, signal, ucode);
204:
205: thread_deallocate(thread);
206: }
207: else
208: result = KERN_INVALID_ARGUMENT;
209: }
210: else
211: result = KERN_INVALID_ARGUMENT;
212:
213: /*
214: * Delete our send rights to the task and thread ports.
215: */
216: (void) port_deallocate(ux_handler_self, task_name);
217: (void) port_deallocate(ux_handler_self, thread_name);
218:
219: return (result);
220: }
221:
222:
223: boolean_t machine_exception();
224:
225: /*
226: * ux_exception translates a mach exception, code and subcode to
227: * a signal and u.u_code. Calls machine_exception (machine dependent)
228: * to attempt translation first.
229: */
230:
231: static
232: void ux_exception(
233: int exception,
234: int code,
235: int subcode,
236: int *ux_signal,
237: int *ux_code
238: )
239: {
240: /*
241: * Try machine-dependent translation first.
242: */
243: if (machine_exception(exception, code, subcode, ux_signal, ux_code))
244: return;
245:
246: switch(exception) {
247:
248: case EXC_BAD_ACCESS:
249: if (code == KERN_INVALID_ADDRESS)
250: *ux_signal = SIGSEGV;
251: else
252: *ux_signal = SIGBUS;
253: break;
254:
255: case EXC_BAD_INSTRUCTION:
256: *ux_signal = SIGILL;
257: break;
258:
259: case EXC_ARITHMETIC:
260: *ux_signal = SIGFPE;
261: break;
262:
263: case EXC_EMULATION:
264: *ux_signal = SIGEMT;
265: break;
266:
267: case EXC_SOFTWARE:
268: switch (code) {
269:
270: case EXC_UNIX_BAD_SYSCALL:
271: *ux_signal = SIGSYS;
272: break;
273: case EXC_UNIX_BAD_PIPE:
274: *ux_signal = SIGPIPE;
275: break;
276: case EXC_UNIX_ABORT:
277: *ux_signal = SIGABRT;
278: break;
279: }
280: break;
281:
282: case EXC_BREAKPOINT:
283: *ux_signal = SIGTRAP;
284: break;
285: }
286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.