Annotation of XNU/bsd/uxkern/ux_exception.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.