Annotation of XNU/bsd/uxkern/ux_exception.c, revision 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.