|
|
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.