Annotation of coherent/b/kernel/coh.386/sig.c, revision 1.1

1.1     ! root        1: /* (lgl-
        !             2:  *     The information contained herein is a trade secret of Mark Williams
        !             3:  *     Company, and  is confidential information.  It is provided  under a
        !             4:  *     license agreement,  and may be  copied or disclosed  only under the
        !             5:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
        !             6:  *     material without the express written authorization of Mark Williams
        !             7:  *     Company or persuant to the license agreement is unlawful.
        !             8:  *
        !             9:  *     COHERENT Version 5.0
        !            10:  *     Copyright (c) 1982, 1993.
        !            11:  *     An unpublished work by Mark Williams Company, Chicago.
        !            12:  *     All rights reserved.
        !            13:  -lgl) */
        !            14: /*
        !            15:  * File:       coh.386/sig.c
        !            16:  *
        !            17:  * Purpose:    signal handling
        !            18:  *
        !            19:  * Revised: Tue May  4 11:59:15 1993 CDT
        !            20:  */
        !            21: 
        !            22: /*
        !            23:  * ----------------------------------------------------------------------
        !            24:  * Includes.
        !            25:  */
        !            26: #include <sys/coherent.h>
        !            27: #include <errno.h>
        !            28: #include <sys/ino.h>
        !            29: #include <sys/inode.h>
        !            30: #include <sys/io.h>
        !            31: #include <sys/proc.h>
        !            32: #include <sys/ptrace.h>
        !            33: #include <sys/sched.h>
        !            34: #include <sys/seg.h>
        !            35: #include <signal.h>
        !            36: #include <sys/core.h>
        !            37: 
        !            38: /*
        !            39:  * ----------------------------------------------------------------------
        !            40:  * Definitions.
        !            41:  *     Constants.
        !            42:  *     Macros with argument lists.
        !            43:  *     Typedefs.
        !            44:  *     Enums.
        !            45:  */
        !            46: typedef void (*VFPTR)();       /* pointer to void function */
        !            47: 
        !            48: /*
        !            49:  * ----------------------------------------------------------------------
        !            50:  * Functions.
        !            51:  *     Import Functions.
        !            52:  *     Export Functions.
        !            53:  *     Local Functions.
        !            54:  */
        !            55: int    actvsig();
        !            56: int    nondsig();
        !            57: int    ptret();
        !            58: int    ptset();
        !            59: void   sendsig();
        !            60: void   sigDefault();
        !            61: void   sigHold();
        !            62: void   sigIgnore();
        !            63: void   sigPause();
        !            64: void   sigRelease();
        !            65: int    sigSet();
        !            66: int    sigdump();
        !            67: int    usigsys();
        !            68: 
        !            69: static struct _fpstate * empack();
        !            70: 
        !            71: /*
        !            72:  * ----------------------------------------------------------------------
        !            73:  * Global Data.
        !            74:  *     Import Variables.
        !            75:  *     Export Variables.
        !            76:  *     Local Variables.
        !            77:  */
        !            78: /*
        !            79:  * Patchable variables.
        !            80:  *
        !            81:  * Patch DUMP_TEXT nonzero to make text segment show up in core files.
        !            82:  * Patch DUMP_LIM set the upper limit in bytes of how much of a
        !            83:  * segment is written to a core file.
        !            84:  *
        !            85:  * Patch CATCH_SEGV nonzero if you are trying to run software that was
        !            86:  * written in blatant defiance of the SVID 2 caution that handling SIGSEGV
        !            87:  * is nonportable and should not be assumed valid on all systems.
        !            88:  */
        !            89: int    DUMP_TEXT = 0;
        !            90: int    DUMP_LIM=512*1024;
        !            91: int    CATCH_SEGV = 0;
        !            92: 
        !            93: /*
        !            94:  * ----------------------------------------------------------------------
        !            95:  * Code.
        !            96:  */
        !            97: 
        !            98: /*
        !            99:  * Given 1-based signal number, ask whether a signal handler was
        !           100:  * attached to the current process using sigset().  This allows
        !           101:  * the kernel to process sigset() differently from signal(), as
        !           102:  * required.
        !           103:  *
        !           104:  * return 1 if sigset(), 0 if not.
        !           105:  */
        !           106: int
        !           107: sigSet(signal)
        !           108: int signal;
        !           109: {
        !           110:        return (SELF->p_dsig & SIG_BIT(signal)) ? 1 : 0;
        !           111: }
        !           112: 
        !           113: /*
        !           114:  * Given 1-based signal number, ignore that signal in the current process.
        !           115:  */
        !           116: void
        !           117: sigIgnore(signal)
        !           118: int signal;
        !           119: {
        !           120:        int sigbit = SIG_BIT(signal);
        !           121: 
        !           122:        SELF->p_dfsig &= ~sigbit;       /* No longer defaulted.  */
        !           123:        SELF->p_isig |= sigbit;         /* Mark signal as ignored.  */
        !           124:        u.u_sfunc[signal - 1] = SIG_IGN;
        !           125: }
        !           126: 
        !           127: /*
        !           128:  * Given 1-based signal number, restore default handling for the current
        !           129:  * process.
        !           130:  *
        !           131:  * There is some duplication of work done in sigAttach(), but sigDefault()
        !           132:  * is also called from msig.c
        !           133:  */
        !           134: void
        !           135: sigDefault(signal)
        !           136: int signal;
        !           137: {
        !           138:        int sigbit = SIG_BIT(signal);
        !           139: 
        !           140:        SELF->p_dfsig |= sigbit;
        !           141:        SELF->p_isig &= ~sigbit;
        !           142:        u.u_sfunc[signal - 1] = SIG_DFL;
        !           143: }
        !           144: 
        !           145: /*
        !           146:  * Given 1-based signal number, hold that signal for the current process.
        !           147:  */
        !           148: void
        !           149: sigHold(signal)
        !           150: int signal;
        !           151: {
        !           152:        SELF->p_hsig |= SIG_BIT(signal);
        !           153: }
        !           154: 
        !           155: /*
        !           156:  * Given 1-based signal number, pause for that signal for the current process.
        !           157:  */
        !           158: void
        !           159: sigPause(signal)
        !           160: int signal;
        !           161: {
        !           162:        SELF->p_hsig &= ~SIG_BIT(signal);
        !           163: 
        !           164:        /*
        !           165:         * Like upause(), do a sleep on an event which never gets a wakeup.
        !           166:         * The sleep returns immediately if a signal was already holding.
        !           167:         */
        !           168:        x_sleep((char *)&u, prilo, slpriSigCatch, "sigpause");
        !           169:        actvsig();
        !           170: }
        !           171: 
        !           172: /*
        !           173:  * Given 1-based signal number, release that signal for the current process.
        !           174:  */
        !           175: void
        !           176: sigRelease(signal)
        !           177: int signal;
        !           178: {
        !           179:        SELF->p_hsig &= ~SIG_BIT(signal);
        !           180:        if (nondsig()) {
        !           181:                actvsig();
        !           182:        }
        !           183: }
        !           184: 
        !           185: /*
        !           186:  * Given 1-based signal number, a pointer to a signal-handling function,
        !           187:  * and a flag, attach the signal handler to the current process.
        !           188:  *
        !           189:  * Function pointer "func" may take on special values SIG_DFL, SIG_IGN,
        !           190:  * and, if "how" is SIGSET, SIG_HOLD.
        !           191:  *
        !           192:  * The flag "how" is 0 if attachment is via signal(), SIGSET if attachment
        !           193:  * is via sigset().
        !           194:  *
        !           195:  * Return the previously attached signal handler, or SIG_HOLD if signals
        !           196:  * were previously held.
        !           197:  */
        !           198: VFPTR
        !           199: sigAttach(signal, func, how)
        !           200: int signal;
        !           201: VFPTR func;
        !           202: int how;
        !           203: {
        !           204:        VFPTR retval;
        !           205:        int sigbit = SIG_BIT(signal);
        !           206: 
        !           207:        /*
        !           208:         * Set up the return value, which says what was previously
        !           209:         * done with the given signal.
        !           210:         */
        !           211:        if (SELF->p_isig & sigbit)
        !           212:                retval = (VFPTR)SIG_IGN;
        !           213:        else if (SELF->p_hsig & sigbit)
        !           214:                retval = (VFPTR)SIG_HOLD;
        !           215:        else
        !           216:                retval = u.u_sfunc[signal - 1];
        !           217: 
        !           218:        u.u_sigreturn = (VFPTR)(u.u_regl[EDX]);
        !           219:        u.u_sfunc[signal - 1] = func;
        !           220: 
        !           221:        /*
        !           222:         * Remove previous default, ignore, or hold status.
        !           223:         */
        !           224:        SELF->p_dfsig &= ~sigbit;
        !           225:        SELF->p_isig &= ~sigbit;
        !           226:        SELF->p_hsig &= ~sigbit;
        !           227: 
        !           228:        /*
        !           229:         * Any pending signal is lost.
        !           230:         */
        !           231:        SELF->p_ssig &= ~sigbit;
        !           232: 
        !           233:        /*
        !           234:         * Special cases for handler.
        !           235:         */
        !           236:        switch ((int)func) {
        !           237:        case (int)SIG_DFL:
        !           238:                sigDefault(signal);
        !           239:                break;
        !           240:        case (int)SIG_IGN:
        !           241:                sigIgnore(signal);
        !           242:                break;
        !           243:        case (int)SIG_HOLD:
        !           244:                sigHold(signal);
        !           245:                break;
        !           246:        }
        !           247: 
        !           248:        /*
        !           249:         * Remember whether handler was attached with sigset() vs signal().
        !           250:         */
        !           251:        if (how == SIGSET)
        !           252:                SELF->p_dsig |= sigbit;
        !           253:        else
        !           254:                SELF->p_dsig &= ~sigbit;
        !           255: 
        !           256:        return retval;
        !           257: }
        !           258: 
        !           259: /*
        !           260:  * Set up the action to be taken on a signal.
        !           261:  */
        !           262: int
        !           263: usigsys(signal, func)
        !           264: int    signal;
        !           265: VFPTR func;
        !           266: {
        !           267:        int     sigtype;
        !           268:        int     retval = 0;
        !           269: 
        !           270:        sigtype = signal & ~0xFF;
        !           271:        signal &= 0xFF;
        !           272: 
        !           273:        T_HAL(8, if (signal == SIGINT)
        !           274:          printf("[%d]sigint(%x, %x) ", SELF->p_pid, sigtype, func));
        !           275: 
        !           276:        /* Range check on 1-based signal number. */
        !           277:        if (signal <= 0 || signal > NSIG) {
        !           278:                u.u_error = EINVAL;
        !           279:                return;
        !           280:        }
        !           281: 
        !           282:        /*
        !           283:         * Don't allow setting/holding/releasing some signals.
        !           284:         *
        !           285:         * NOTICE:  Ignoring SIGSEGV causes runaway user faults.
        !           286:         * SVID Issue 2 says *don't* do signal(SIGSEGV,...)!!!
        !           287:         */
        !           288:        if (signal == SIGKILL) {
        !           289:                u.u_error = EINVAL;
        !           290:                return;
        !           291:        }
        !           292: 
        !           293:        if (signal == SIGSEGV && CATCH_SEGV == 0) {
        !           294:                u.u_error = EINVAL;
        !           295:                return;
        !           296:        }
        !           297:         
        !           298:        switch (sigtype) {
        !           299:        case SIGHOLD:
        !           300:                sigHold(signal);
        !           301:                break;
        !           302:        case SIGRELSE:
        !           303:                sigRelease(signal);
        !           304:                break;
        !           305:        case SIGIGNORE:
        !           306:                sigIgnore(signal);
        !           307:                break;
        !           308:        case 0:                         /* old system entry */
        !           309:                retval = (int)sigAttach(signal, func, 0);
        !           310:                break;
        !           311:        case SIGSET:                    /* new system entry */
        !           312:                retval = (int)sigAttach(signal, func, SIGSET);
        !           313:                break;
        !           314:        case SIGPAUSE:
        !           315:                sigPause(signal);
        !           316:                break;
        !           317:        default:
        !           318:                u.u_error = SIGSYS;
        !           319:                break;
        !           320:        }
        !           321:        return retval;
        !           322: }
        !           323: 
        !           324: /*
        !           325:  * Send a signal to the process `pp'.
        !           326:  * Return 1 if signal was sent.
        !           327:  * Return 0 if signal was ignored.
        !           328:  * The return value is of use to the trap handler.
        !           329:  */
        !           330: void
        !           331: sendsig(sig, pp)
        !           332: register unsigned sig;
        !           333: register PROC *pp;
        !           334: {
        !           335:        register sig_t f;
        !           336:        register int s;
        !           337: 
        !           338:        T_HAL(8, if (sig == SIGINT) printf("[%d]gets int ", pp->p_pid));
        !           339: 
        !           340:        /*
        !           341:         * Convert the signal to a bit position.
        !           342:         */
        !           343:        f = SIG_BIT(sig);
        !           344: 
        !           345:        /*
        !           346:         * If the signal is ignored, and is not SIGCLD, do nothing.
        !           347:         */
        !           348:        if ((pp->p_isig & f) && sig != SIGCLD) {
        !           349:                goto sendSigDone;
        !           350:        }
        !           351: 
        !           352:        /*
        !           353:         * No further processing for delayed or held signals.
        !           354:         */
        !           355:        if ((pp->p_ssig & f) && (pp->p_hsig|pp->p_dsig) & f)
        !           356:                goto sendSigDone;
        !           357:        
        !           358:        /*
        !           359:         * Actually send the signal by flagging the needed bit.
        !           360:         */
        !           361:        pp->p_ssig |= f;
        !           362: 
        !           363:        /*
        !           364:         * If the process is sleeping, wake it up so that
        !           365:         * it can process this signal.
        !           366:         */
        !           367:        if (pp->p_state == PSSLSIG) {
        !           368:                s = sphi();
        !           369:                pp->p_lback->p_lforw = pp->p_lforw;
        !           370:                pp->p_lforw->p_lback = pp->p_lback;
        !           371: #ifndef _I386
        !           372:                addu(pp->p_cval, (utimer-pp->p_lctim)*CVCLOCK);
        !           373: #endif
        !           374:                setrun(pp);
        !           375:                spl(s);
        !           376:        }
        !           377: sendSigDone:
        !           378:        return;
        !           379: }
        !           380: 
        !           381: /*
        !           382:  * Return signal number if we have a non ignored or delayed signal, else zero.
        !           383:  */
        !           384: int
        !           385: nondsig()
        !           386: {
        !           387:        register PROC *pp;
        !           388:        register sig_t mask;
        !           389:        register int signo;
        !           390: 
        !           391:        pp = SELF;
        !           392:        signo = 0;
        !           393: 
        !           394:        /*
        !           395:         * Turn off all ignored signals except SIGCLD.
        !           396:         */
        !           397:        pp->p_ssig &= ~(pp->p_isig & ~SIG_BIT(SIGCLD));
        !           398: 
        !           399:        /*
        !           400:         * If any signals have arrived, but which are not held,
        !           401:         * figure out what they are.
        !           402:         */
        !           403:        if (pp->p_ssig&~pp->p_hsig) {
        !           404:                /*
        !           405:                 * There is at least one signal.  Extract its number
        !           406:                 * from the signal bits.
        !           407:                 */
        !           408:                mask = (sig_t) 1;
        !           409:                signo += 1;
        !           410:                while (((pp->p_ssig&~pp->p_hsig) & mask) == 0) {
        !           411:                        mask <<= 1;
        !           412:                        signo += 1;
        !           413:                }
        !           414:        }
        !           415:        return signo;
        !           416: }
        !           417: 
        !           418: /*
        !           419:  * If we have a signal that isn't ignored, activate it.
        !           420:  */
        !           421: int
        !           422: actvsig()
        !           423: {
        !           424:        register int signum;
        !           425:        register PROC *pp;
        !           426:        register int (*func)();
        !           427:        int ptval;
        !           428: 
        !           429:        /*
        !           430:         * Fetch an unprocessed signal.
        !           431:         * Return if there are none.
        !           432:         * The while() structure is only for traced processes.
        !           433:         */
        !           434:        while (signum = nondsig()) {
        !           435: 
        !           436:                pp = SELF;
        !           437: 
        !           438:                /*
        !           439:                 * Reset the signal to indicate that it has been processed.
        !           440:                 * Bit table p_ssig uses 0-based signals, while signal.h
        !           441:                 * lists 1-based signals.
        !           442:                 */
        !           443:                pp->p_ssig &= ~SIG_BIT(signum);
        !           444: 
        !           445:                /*
        !           446:                 * Fetch the user function that goes with this signal.
        !           447:                 * Function table u_sfunc uses 0-based signals, while signal.h
        !           448:                 * lists 1-based signals.
        !           449:                 */
        !           450:                func = u.u_sfunc[signum-1];
        !           451: 
        !           452:                /*
        !           453:                 * SIGCLD causes no work here if defaulted or ignored.
        !           454:                 */
        !           455:                if (signum == SIGCLD && (func == SIG_DFL || func == SIG_IGN))
        !           456:                        return;
        !           457: 
        !           458:                /*
        !           459:                 * Store the (1-based) signal number in the u area.
        !           460:                 * This is how a core dump records the death signal.
        !           461:                 */
        !           462:                u.u_signo = signum;
        !           463: 
        !           464:                /*
        !           465:                 * If the signal is not defaulted, go run the requested
        !           466:                 * function.
        !           467:                 */
        !           468:                if (func != SIG_DFL) {
        !           469:                        if (XMODE_286)
        !           470:                                oldsigstart(signum, func);
        !           471:                        else {
        !           472:                                msigstart(signum, func);
        !           473:                        }
        !           474:                        return;
        !           475:                }
        !           476: 
        !           477:                /*
        !           478:                 * ASSERTION:  the signal being processed is SIG_DFL'd.
        !           479:                 */
        !           480: 
        !           481:                /*
        !           482:                 * msysgen() is a nop for COHERENT 4.0.  The comment in the
        !           483:                 * assembly code is "Nothing useful to save".
        !           484:                 */
        !           485:                msysgen(u.u_sysgen);
        !           486: 
        !           487:                /*
        !           488:                 * When a traced process is signaled, it may need to exchange
        !           489:                 * data with its parent (via ptret).
        !           490:                 */
        !           491:                if (pp->p_flags&PFTRAC) {
        !           492:                        pp->p_flags |= PFWAIT;
        !           493:                        ptval = ptret();
        !           494:                        T_HAL(0x10000, printf("ptret()=%x ", ptval));
        !           495:                        pp->p_flags &= ~(PFWAIT|PFSTOP);
        !           496:                        if (ptval == 0)
        !           497:                                /* see if another signal came in */
        !           498:                                continue;
        !           499:                        else
        !           500:                                signum = ptval;
        !           501:                }
        !           502: 
        !           503:                /*
        !           504:                 * Some signals cause a core file to be written.
        !           505:                 */
        !           506:                switch(signum) {
        !           507:                case SIGQUIT:
        !           508:                case SIGILL:
        !           509:                case SIGTRAP:
        !           510:                case SIGABRT:
        !           511:                case SIGFPE:
        !           512:                case SIGSEGV:
        !           513:                case SIGSYS:
        !           514:                        if (sigdump())
        !           515:                                signum |= 0x80;
        !           516:                        break;
        !           517:                }
        !           518:                pexit(signum);
        !           519:        }
        !           520: }
        !           521: 
        !           522: /*
        !           523:  * Create a dump of ourselves onto the file `core'.
        !           524:  */
        !           525: int
        !           526: sigdump()
        !           527: {
        !           528:        register INODE *ip;
        !           529:        register SR *srp;
        !           530:        register SEG * sp;
        !           531:        register int n;
        !           532:        register paddr_t ssize;
        !           533:        extern  int     DUMP_LIM;
        !           534:        struct ch_info chInfo;
        !           535: 
        !           536:        if (SELF->p_flags&PFNDMP)
        !           537:                return (0);
        !           538:        u.u_io.io_seg  = IOSYS;
        !           539:        u.u_io.io_flag = 0;
        !           540:        /* Make the core with the real owners */
        !           541:        schizo();
        !           542:        if (ftoi("core", 'c')) {
        !           543:                schizo();
        !           544:                return (0);
        !           545:        }
        !           546:        if ((ip=u.u_cdiri) == NULL) {
        !           547:                if ((ip=imake(IFREG|0644, 0)) == NULL) {
        !           548:                        schizo();
        !           549:                        return (0);
        !           550:                }
        !           551:        } else {
        !           552:                if ((ip->i_mode&IFMT)!=IFREG
        !           553:                 || iaccess(ip, IPW)==0
        !           554:                 || getment(ip->i_dev, 1)==NULL) {
        !           555:                        idetach(ip);
        !           556:                        schizo();
        !           557:                        return (0);
        !           558:                }
        !           559:                iclear(ip);
        !           560:        }
        !           561:        schizo();
        !           562:        u.u_error = 0;
        !           563:        u.u_io.io_seek = 0;
        !           564: 
        !           565:        /* Write core file header */
        !           566:        chInfo.ch_magic = CORE_MAGIC;
        !           567:        chInfo.ch_info_len = sizeof(chInfo);
        !           568:        chInfo.ch_uproc_offset = U_OFFSET;
        !           569: 
        !           570:        u.u_io.io_seg = IOSYS;
        !           571:        u.u_io.io.vbase = &chInfo;
        !           572:        u.u_io.io_ioc = sizeof(chInfo);
        !           573:        u.u_io.io_flag = 0;
        !           574: 
        !           575:        sp->s_lrefc++;
        !           576:        iwrite(ip, &u.u_io);
        !           577:        sp->s_lrefc--;
        !           578: 
        !           579:        /*
        !           580:         * Added to aid in kernel debugging - if DUMP_TEXT is nonzero,
        !           581:         * dump the text segment (to see if it was corrupted) and set
        !           582:         * the dump flag so that postmortem utilities will know that
        !           583:         * text is present in the core file.
        !           584:         */
        !           585:        if (DUMP_TEXT)
        !           586:                u.u_segl[SISTEXT].sr_flag |= SRFDUMP;
        !           587: 
        !           588:        for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) {
        !           589: 
        !           590:                if ((srp->sr_flag & SRFDUMP)==0)
        !           591:                        continue;
        !           592: 
        !           593:                /* Don't try to dump empty segments. */
        !           594:                if ((sp = srp->sr_segp)==NULL) {
        !           595:                        srp->sr_flag &= ~SRFDUMP;
        !           596:                        continue;
        !           597:                }
        !           598: 
        !           599:                /* Don't dump segments too big to dump. */
        !           600:                if (sp->s_size > DUMP_LIM)
        !           601:                        srp->sr_flag &= ~SRFDUMP;
        !           602:        }
        !           603: 
        !           604:        for (srp=u.u_segl; u.u_error==0 && srp<&u.u_segl[NUSEG]; srp++) {
        !           605: 
        !           606:                /* Only dump segments flagged for dumping. */
        !           607:                if ((srp->sr_flag & SRFDUMP)==0)
        !           608:                        continue;
        !           609: 
        !           610:                ssize = sp->s_size;
        !           611:                u.u_io.io_seg = IOPHY;
        !           612:                u.u_io.io.pbase = MAPIO(sp->s_vmem, 0);
        !           613:                u.u_io.io_flag = 0;
        !           614:                sp->s_lrefc++;
        !           615:                while (u.u_error == 0 && ssize != 0) {
        !           616:                        n = ssize > SCHUNK ? SCHUNK : ssize;
        !           617:                        u.u_io.io_ioc = n;
        !           618:                        iwrite(ip, &u.u_io);
        !           619:                        u.u_io.io.pbase += n;
        !           620:                        ssize -= (paddr_t)n;
        !           621:                }
        !           622:                sp->s_lrefc--;
        !           623:        }
        !           624:        idetach(ip);
        !           625:        return (u.u_error==0);
        !           626: }
        !           627: 
        !           628: /*
        !           629:  * Send a ptrace command to the child.
        !           630:  *
        !           631:  * "pid" is child pid.
        !           632:  */
        !           633: int
        !           634: ptset(req, pid, addr, data)
        !           635: unsigned req;
        !           636: int *addr;
        !           637: {
        !           638:        register PROC *pp;
        !           639: 
        !           640:        lock(pnxgate);
        !           641:        for (pp=procq.p_nforw; pp!=&procq; pp=pp->p_nforw)
        !           642:                if (pp->p_pid == pid)
        !           643:                        break;
        !           644:        unlock(pnxgate);
        !           645:        if (pp==&procq || (pp->p_flags&PFSTOP)==0 || pp->p_ppid!=SELF->p_pid){
        !           646:                u.u_error = ESRCH;
        !           647:                return;
        !           648:        }
        !           649:        lock(pts.pt_gate);
        !           650:        pts.pt_req = req;
        !           651:        pts.pt_pid = pid;
        !           652:        pts.pt_addr = addr;
        !           653:        pts.pt_data = data;
        !           654:        pts.pt_errs = 0;
        !           655:        pts.pt_rval = 0;
        !           656:        pts.pt_busy = 1;
        !           657:        wakeup((char *)&pts.pt_req);
        !           658:        while (pts.pt_busy) {
        !           659:                x_sleep((char *)&pts.pt_busy, primed, slpriSigCatch, "ptrace");
        !           660:                /* Send a ptrace command to the child.  */
        !           661:        }
        !           662:        u.u_error = pts.pt_errs;
        !           663:        unlock(pts.pt_gate);
        !           664:        return (pts.pt_rval);
        !           665: }
        !           666: 
        !           667: /*
        !           668:  * This routine is called when a child that is being traced receives a signal
        !           669:  * that is not caught or ignored.  It follows up on any requests by the parent
        !           670:  * and returns when done.
        !           671:  *
        !           672:  * After ptrace handling done in this routine, a real or simulated signal
        !           673:  * may need to be sent to the traced process.
        !           674:  * Return a signal number to be sent to the child process, or 0 if none.
        !           675:  */
        !           676: int
        !           677: ptret()
        !           678: {
        !           679:        extern void (*ndpKfrstor)();
        !           680:        register PROC *pp;
        !           681:        register PROC *pp1;
        !           682:        register int sign;
        !           683:        unsigned off;
        !           684:        int doEmUnpack = 0;
        !           685: 
        !           686:        struct _fpstate * fstp = empack();
        !           687: 
        !           688:        pp = SELF;
        !           689: next:
        !           690:        u.u_error = 0;
        !           691:        if (pp->p_ppid == 1)
        !           692:                return (SIGKILL);
        !           693:        sign = -1;
        !           694: 
        !           695:        /* wake up parent if it is sleeping */
        !           696:        lock(pnxgate);
        !           697:        pp1 = &procq;
        !           698:        for (;;) {
        !           699:                if ((pp1=pp1->p_nforw) == &procq) {
        !           700:                        sign = SIGKILL;
        !           701:                        break;
        !           702:                }
        !           703:                if (pp1->p_pid != pp->p_ppid)
        !           704:                        continue;
        !           705:                if (ASLEEP(pp1))
        !           706:                        wakeup((char *)pp1);
        !           707:                break;
        !           708:        }
        !           709:        unlock(pnxgate);
        !           710: 
        !           711:        while (sign < 0) {
        !           712:                /* If no pending ptrace transaction for this process, sleep. */
        !           713:                if (pts.pt_busy==0 || pp->p_pid!=pts.pt_pid) {
        !           714:                        /* If a signal bit is set now, just exit - let
        !           715:                         * actvsig() handle it next time through.
        !           716:                         * Doing sleep and goto next will stick us in a loop */
        !           717:                        if (nondsig())
        !           718:                                return 0;
        !           719:                        x_sleep((char *)&pts.pt_req,
        !           720:                          primed, slpriSigCatch, "ptret");
        !           721:                        goto next;
        !           722:                }
        !           723:                switch (pts.pt_req) {
        !           724:                case PTRACE_RD_TXT:
        !           725:                        if (XMODE_286) {
        !           726:                                pts.pt_rval = getuwd(NBPS+pts.pt_addr);
        !           727:                                break;
        !           728:                        }
        !           729:                        /* Fall through for 386 mode processes. */
        !           730:                case PTRACE_RD_DAT:
        !           731:                        pts.pt_rval = getuwd(pts.pt_addr);
        !           732:                        break;
        !           733:                case PTRACE_RD_USR:
        !           734:                        /* See ptrace.h for valid offsets. */
        !           735:                        off = (unsigned)pts.pt_addr;
        !           736:                        if (off & 3)
        !           737:                                u.u_error = EINVAL;
        !           738:                        else if (off < PTRACE_FP_CW) {
        !           739:                                /* Reading CPU general register state */
        !           740:                                if (off == PTRACE_SIG)
        !           741:                                        pts.pt_rval = u.u_signo;
        !           742:                                else
        !           743:                                        pts.pt_rval = u.u_regl[off>>2];
        !           744:                        } else if (off < PTRACE_DR0) {
        !           745:                                /*
        !           746:                                 * Reading NDP state.
        !           747:                                 * If NDP state not already saved, save it.
        !           748:                                 * Fetch desired info.
        !           749:                                 * Restore NDP state in case we will resume.
        !           750:                                 */
        !           751:                                if (rdNdpUser()) {
        !           752:                                        /* if using coprocessor */
        !           753:                                        if (!rdNdpSaved()) {
        !           754:                                                ndpSave(&u.u_ndpCon);
        !           755:                                                wrNdpSaved(1);
        !           756:                                        }
        !           757: pts.pt_rval = ((int *)&u.u_ndpCon)[(off - PTRACE_FP_CW)>>2];
        !           758:                                        ndpRestore(&u.u_ndpCon);
        !           759:                                        wrNdpSaved(0);
        !           760:                                } else if (fstp) {
        !           761: pts.pt_rval = getuwd(((int *)fstp) + ((off - PTRACE_FP_CW)>>2));
        !           762:                                        /* if emulating */
        !           763:                                } else /* no ndp state to display */
        !           764:                                        pts.pt_rval = 0;
        !           765:                        } else
        !           766:                                u.u_error = EINVAL;
        !           767:                        break;
        !           768:                case PTRACE_WR_TXT:
        !           769:                        if (XMODE_286) {
        !           770:                                putuwd(NBPS+pts.pt_addr, pts.pt_data);
        !           771:                                break;
        !           772:                        }
        !           773:                        /* Fall through for 386 mode processes. */
        !           774:                case PTRACE_WR_DAT:
        !           775:                        putuwd(pts.pt_addr, pts.pt_data);
        !           776:                        break;
        !           777:                case PTRACE_WR_USR:
        !           778:                        /* See ptrace.h for valid offsets. */
        !           779:                        off = (unsigned)pts.pt_addr;
        !           780: 
        !           781:                        if (off & 3)
        !           782:                                u.u_error = EINVAL;
        !           783:                        else if (off < PTRACE_FP_CW) {
        !           784:                                /* Writing CPU general register state */
        !           785:                                if (off == PTRACE_SIG)
        !           786:                                        u.u_error = EINVAL;
        !           787:                                else
        !           788:                                        u.u_regl[off>>2] = pts.pt_data;
        !           789:                        } else if (off < PTRACE_DR0) {
        !           790:                                if (rdNdpUser()) {
        !           791:                                        /*
        !           792:                                         * Writing NDP state.
        !           793:                                         * If NDP state not already saved, save it.
        !           794:                                         * Store desired info.
        !           795:                                         * Restore NDP state in case we will resume.
        !           796:                                         */
        !           797:                                        if (!rdNdpSaved()) {
        !           798:                                                ndpSave(&u.u_ndpCon);
        !           799:                                                wrNdpSaved(1);
        !           800:                                        }
        !           801: ((int *)&u.u_ndpCon)[(off - PTRACE_FP_CW)>>2] = pts.pt_data;
        !           802:                                        ndpRestore(&u.u_ndpCon);
        !           803:                                        wrNdpSaved(0);
        !           804:                                } else if (fstp && ndpKfrstor) {
        !           805: putuwd(((int *)fstp) + ((off - PTRACE_FP_CW)>>2), pts.pt_data);
        !           806:                                        doEmUnpack = 1;
        !           807:                                }
        !           808:                        } else
        !           809:                                u.u_error = EINVAL;
        !           810:                        break;
        !           811:                case PTRACE_RESUME:
        !           812:                        u.u_regl[EFL] &= ~MFTTB;
        !           813:                        goto sig;
        !           814:                case PTRACE_TERM:
        !           815:                        sign = SIGKILL;
        !           816:                        break;
        !           817:                case PTRACE_SSTEP:
        !           818:                        u.u_regl[EFL] |= MFTTB;
        !           819:                sig:
        !           820:                        if (pts.pt_data<0 || pts.pt_data>NSIG) {
        !           821:                                u.u_error = EINVAL;
        !           822:                                break;
        !           823:                        }
        !           824:                        sign = pts.pt_data;
        !           825:                        if (pts.pt_addr != SIG_IGN) {
        !           826:                                u.u_regl[EIP] = (int)pts.pt_addr;
        !           827:                        }
        !           828:                        break;
        !           829:                default:
        !           830:                        u.u_error = EINVAL;
        !           831:                }
        !           832:                if ((pts.pt_errs=u.u_error) == EFAULT)
        !           833:                        pts.pt_errs = EINVAL;
        !           834:                pts.pt_busy = 0;
        !           835:                wakeup((char *)&pts.pt_busy);
        !           836:        }
        !           837:        if (doEmUnpack)
        !           838:                (*ndpKfrstor)(fstp, &u.u_ndpCon);
        !           839:        return (sign);
        !           840: }
        !           841: 
        !           842: /*
        !           843:  * If using floating point emulator, make room on user stack and save
        !           844:  * floating point context there.  Code elsewhere takes care of floating
        !           845:  * point context if there is a coprocessor.
        !           846:  *
        !           847:  * Return the virtual address in user space of the context area, or
        !           848:  * return NULL if not using FP emulation.
        !           849:  */
        !           850: static struct _fpstate *
        !           851: empack()
        !           852: {
        !           853:        int uesp;
        !           854:        int sphi, splo;
        !           855:        SEG * segp;
        !           856:        cseg_t * pp;
        !           857:        struct _fpstate * ret = NULL;
        !           858:        extern void (*ndpKfsave)();
        !           859:        unsigned long sw_old;
        !           860: 
        !           861:        /* If not emulating, do nothing */
        !           862:        if (rdNdpUser() || !rdEmTrapped() || !ndpKfsave)
        !           863:                return NULL;
        !           864: 
        !           865:        /*
        !           866:         * Will copy at least u_sigreturn, _fpstackframe, and ndpFlags.
        !           867:         * If using ndp, need room for an _fpstate.
        !           868:         * If emulating, need room for an _fpemstate.
        !           869:         */
        !           870:        uesp = u.u_regl[UESP] - sizeof(struct _fpstate);
        !           871: 
        !           872:        /* Add to user stack if necessary. */
        !           873:        segp = u.u_segl[SISTACK].sr_segp;
        !           874:        sphi = (XMODE_286) ? ISP_286 : ISP_386;
        !           875:        splo = sphi - segp->s_size;
        !           876: 
        !           877:        if (splo > uesp) {
        !           878:                pp = c_extend(segp->s_vmem, btoc(segp->s_size));
        !           879:                if (pp==0) {
        !           880:                        printf("Empack failed.  cmd=%s  c_extend(%x,%x)=0 ",
        !           881:                          u.u_comm, segp->s_vmem, btoc(segp->s_size));
        !           882:                        return NULL;
        !           883:                }
        !           884: 
        !           885:                segp->s_vmem = pp;
        !           886:                segp->s_size += NBPC;
        !           887:                if (sproto(0)==0) {
        !           888:                        printf("Empack failed.  cmd=%s  sproto(0)=0 ",
        !           889:                          u.u_comm);
        !           890:                        return NULL;
        !           891:                }
        !           892: 
        !           893:                segload();
        !           894:        }
        !           895: 
        !           896:        ret = (struct _fpstate *)uesp;
        !           897:        (*ndpKfsave)(&u.u_ndpCon, uesp);
        !           898:        sw_old = getuwd(&ret->sw);
        !           899:        putuwd(&ret->status, sw_old);
        !           900:        putuwd(&ret->sw, sw_old & 0x7f00);
        !           901: 
        !           902:        return ret;
        !           903: }

unix.superglobalmegacorp.com

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