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