Annotation of cci/usr/src/bin/cdb/single.c, revision 1.1

1.1     ! root        1: static char sccsid[] = "@(#)single.c   2.8";
        !             2: 
        !             3: #include "cdb.h"
        !             4: 
        !             5: 
        !             6: extern char    vsbArgsChild[]; /* defined in pt.c */
        !             7: 
        !             8: export int     vcBadMax; /* most instructions we single step without symbols */
        !             9: 
        !            10: typedef struct {       /* the assertion descriptor */
        !            11:        char    *sbCheck;       /* points to command list for this check */
        !            12:        ASE     as;             /* state of THIS assertion check */
        !            13: } 
        !            14: ADR, *pADR;
        !            15: #define cbADR sizeof(ADR)
        !            16: 
        !            17: pADR   vrgAd;  /* the list of assertions */
        !            18: ADRT   vpcLast;
        !            19: export int     viadMac, viadMax;
        !            20: export FLAGT   vfRunAssert; /* see IbpFNewChild */
        !            21: export ASE     vas;    /* state of the assertions as a whole */
        !            22: 
        !            23: 
        !            24: 
        !            25: /* A D R   F   S T A C K   F I X */
        !            26: 
        !            27: export ADRT AdrFStackFix(adr)
        !            28: ADRT   adr;
        !            29: {
        !            30:        /* given an address immediately after a procedure call, step over any
        !            31:             * stack fix-up instructions
        !            32:             */
        !            33: #ifdef ONYX
        !            34:        int             inst;
        !            35: #define INCR15_INST    0xa900
        !            36:        inst = GetWord(adr, spaceText);
        !            37:        if ((inst & 0xff00) == INCR15_INST)
        !            38:                adr += 2;
        !            39: #endif
        !            40: #ifdef TAHOE
        !            41:        /* TAHOE has no stack fix stuff, it's all done by the callee */
        !            42: #endif
        !            43: #ifdef VAX
        !            44:        /* vax has no stack fix stuff, it's all done by the callee */
        !            45: #endif
        !            46: #ifdef M68000
        !            47:        short   inst;
        !            48: 
        !            49: #define TST_INST       0x4a5f
        !            50: #define TSTL_INST      0x4a9f
        !            51: #define CMPML_INST     0xbf8f
        !            52: #define ADDW_INST      0xdefc
        !            53: #define ADDQ_INST      0x500f
        !            54: #define ADDN_INST      0x504f
        !            55: 
        !            56:        GetBlock(adr, spaceText, &inst, 2);
        !            57:        if ( (inst == TST_INST)
        !            58:            OR (inst == TSTL_INST)
        !            59:            OR (inst == CMPML_INST)
        !            60:            OR ((inst & 0xf13f)  == ADDQ_INST))
        !            61:                adr += 2;
        !            62:        else if ((inst & 0xf1ff) == ADDN_INST)
        !            63:                adr += 4;
        !            64: #endif
        !            65:        return(adr);
        !            66: } /* AdrFStackFix */
        !            67: 
        !            68: 
        !            69: /* A D R   F   P R E A M B L E */
        !            70: 
        !            71: local ADRT AdrFPreamble(adr)
        !            72: ADRT   adr;
        !            73: {
        !            74:        /* given the first address in a procedure, return the address of the
        !            75:             * first `real' instruction - ie. after the csav0 or the brb whatever
        !            76:            */
        !            77: #ifdef ONYX
        !            78:        int             inst;
        !            79: 
        !            80: #define LDK_INST       0xbd00
        !            81: #define LD_INST        0x2100
        !            82:        inst = GetWord(adr, spaceText) & 0xff00; /* high byte of 1st instruction */
        !            83:        /* we want to skip over stack set up stuff */
        !            84:        adr += (inst == LDK_INST) ? 6 : (inst == LD_INST) ? 8 : 4;
        !            85: #endif
        !            86: #ifdef TAHOE
        !            87:        int             inst, specifier;
        !            88: 
        !            89: #define        BRB_INST        0x11    /* Guess they are the only ones after mask */
        !            90: #define        BRW_INST        0x13
        !            91: #define JMP_INST       0x71
        !            92: #define SUBL3_INST     0x3c
        !            93:        inst = GetByte(adr, spaceText) & 0xff; /* instruction */
        !            94:        specifier = GetByte((char *)adr + 1, spaceText) & 0xff; /* operand spec */
        !            95:        /* we want to skip over stack set up stuff */
        !            96:        switch (inst) {
        !            97:        case BRB_INST:
        !            98:                adr += 2; 
        !            99:                break;
        !           100:        case BRW_INST:
        !           101:                adr += 3; 
        !           102:                break;
        !           103:        case JMP_INST:
        !           104:                adr += 6; 
        !           105:                break;
        !           106:        case SUBL3_INST:
        !           107:                if (specifier <= 63) adr += 4 ;
        !           108:                else switch (specifier) {
        !           109:                case 0x88: 
        !           110:                        adr += 5; 
        !           111:                        break;
        !           112:                case 0x89: 
        !           113:                        adr += 6; 
        !           114:                        break;
        !           115:                case 0x8f: 
        !           116:                        adr += 8; 
        !           117:                        break;
        !           118:                }
        !           119:                break;
        !           120:        default:
        !           121:                printf("CDB problem - unexpected instruction (0x%0x) at procedure begining\n", inst);
        !           122:        }
        !           123: #endif
        !           124: 
        !           125: #ifdef VAX
        !           126:        int             inst;
        !           127: 
        !           128: #define        BRB_INST        0x11
        !           129: #define        BRW_INST        0x31
        !           130: #define JMP_INST       0x17
        !           131: #define SUBL2_INST     0xc2
        !           132:        inst = GetByte(adr, spaceText) & 0xff; /* instruction */
        !           133:        /* we want to skip over stack set up stuff */
        !           134:        if (inst == BRB_INST)
        !           135:                adr += 2;
        !           136:        else if (inst == BRW_INST)
        !           137:                adr += 3;
        !           138:        else if (inst == SUBL2_INST)
        !           139:                adr += 7;
        !           140:        else 
        !           141:            adr += 4;
        !           142: #endif
        !           143: #ifdef M68000
        !           144:        int             ipd, iln, ifd, slop;
        !           145: 
        !           146:        ipd = IpdFAdr(adr);
        !           147:        if (ipd != ipdNil) {
        !           148:                IfdLnFAdr(adr, vrgPd[ipd].isym+1, &ifd, &iln, &slop);
        !           149: #ifdef SUN
        !           150:                iln++;  /* first line number is connected with preamble */
        !           151: #endif
        !           152:                adr = AdrFIfdLn(ifd, iln);
        !           153:        } /* if */
        !           154: #endif
        !           155:        return(adr);
        !           156: } /* AdrFPreamble */
        !           157: 
        !           158: 
        !           159: /* F   A T   C A L L */
        !           160: 
        !           161: local FLAGT FAtCall(adr)
        !           162: ADRT   adr;
        !           163: {
        !           164:        short   inst;
        !           165:        /* return true or false based on whether the instruction at adr
        !           166:             * is a procedure call of any kind.
        !           167:             */
        !           168:        inst = 0;
        !           169: #ifdef ONYX
        !           170: #define CALL_INST      0x5f00
        !           171: #define cbInsMax       2
        !           172:        GetBlock(adr, spaceText, (ADRT)&inst, cbInsMax);
        !           173:        return(inst == CALL_INST);
        !           174: #endif
        !           175: 
        !           176: #ifdef TAHOE
        !           177: #define        CALLS_INST      0xbf    
        !           178: #define        CALLG_INST      0xfe
        !           179:        GetBlock(adr, spaceText, ((char *)&inst)+1, 1);
        !           180:        return((inst == CALLS_INST) OR (inst == CALLG_INST));
        !           181: #endif
        !           182: 
        !           183: #ifdef VAX
        !           184: #define        CALLS_INST      0xfb    /* arguments are on the stack */
        !           185: #define        CALLG_INST      0xfa    /* arguments are elsewhere */
        !           186:        GetBlock(adr, spaceText, &inst, 1);
        !           187:        return((inst == CALLS_INST) OR (inst == CALLG_INST));
        !           188: #endif
        !           189: 
        !           190: #ifdef M68000
        !           191: #define JSR_INST       0x4e80
        !           192: #define BSR_INST       0x6100
        !           193: #define cbInsMax       2
        !           194: 
        !           195:        GetBlock(adr, spaceText, (ADRT)&inst, cbInsMax);
        !           196:        return(((inst & 0xff00) == BSR_INST) OR ((inst & 0xffc0) == JSR_INST));
        !           197: #endif
        !           198: } /* FAtCall */
        !           199: 
        !           200: 
        !           201: /* R E T   F   S P */
        !           202: 
        !           203: local ADRT RetFSp(sp)
        !           204: ADRT   sp;
        !           205: {
        !           206:        /* given the stack pointer immediately after a procedure call,
        !           207:             * return the return address
        !           208:             */
        !           209: #ifdef TAHOE
        !           210:        /* We know that the argument here is realy 'fp', not 'sp'. */
        !           211:        return(GetWord(sp-8, spaceData)); /* get return */
        !           212: #endif
        !           213: #ifdef VAX
        !           214:        return(GetWord(sp+16, spaceData)); /* get return */
        !           215: #endif
        !           216: #ifdef ONYX
        !           217:        return(GetWord(sp, spaceData)); /* get return */
        !           218: #endif
        !           219: #ifdef M68000
        !           220:        return(GetWord(sp, spaceData)); /* get return */
        !           221: #endif
        !           222: } /* RetFSp */
        !           223: 
        !           224: 
        !           225: /* R E T   F   F P */
        !           226: 
        !           227: local ADRT RetFFp(fp)
        !           228: ADRT   fp;
        !           229: {
        !           230:        ADRT    ap, pc;
        !           231:        /* given a frame pointer, return the return address */
        !           232:        NextFrame(&fp, &ap, &pc);
        !           233:        return(pc); /* get return */
        !           234: } /* RetFFp */
        !           235: 
        !           236: 
        !           237: /* I B P   F   S I N G L E */
        !           238: 
        !           239: export int IbpFSingle(fBigStep, fQuiet)
        !           240: FLAGT  fBigStep, fQuiet;
        !           241: {
        !           242:        int             cBad, ibp, ifd, ln, slop;
        !           243:        ADRT    adr;
        !           244: 
        !           245:        if (vpid == pidNil) {
        !           246:                /* we have no process, create one! */
        !           247:                IbpFNewChild(vsbArgsChild);
        !           248:                PrintPos(vpc, (fQuiet) ? fmtNil : fmtProc+fmtLn+fmtPrint);
        !           249:                return(vibp);
        !           250:        } /* if */
        !           251: 
        !           252:        /* the idea here is to loop until we get someplace interesting. This
        !           253:             * usually means at an address that translates EXACTLY (slop == 0) to
        !           254:             * a known line number.
        !           255:             */
        !           256:        cBad = 0;       /* to count instructions in the twilight zone */
        !           257:        slop = -1; /* just to get us into loop first time */
        !           258:        while (slop != 0) {
        !           259:                ibp = ibpNil;
        !           260:                if (FAtCall(vpc)) { /* at proc call */
        !           261:                        /* follow the call - this way we don't have to deal with N ways
        !           262:                                     * to compute callee's address.
        !           263:                                     */
        !           264:                        ibp = IbpFRun(ptSingle);
        !           265:                        if (ibp != ibpNil)
        !           266:                                return(ibp);    /* a REAL breakpoint */
        !           267:                        if (!fBigStep) {
        !           268:                                if (IpdFAdr(vpc) != ipdNil) {
        !           269:                                        adr = AdrFPreamble(vpc); /* allows for intro code */
        !           270:                                        ibp = IbpFAdr(adr, 0, sbNil); /* temp BP after intro */
        !           271:                                        ibp = IbpFRun(ptResume);
        !           272:                                        break; /* go to the stuff at end of this procedure */
        !           273:                                } /* if */
        !           274:                                /* if we get here, then the proc call goes to the
        !           275:                                                 * twilight zone - fall into fBigStep code
        !           276:                                                 */
        !           277:                        } /* if */
        !           278: #ifdef TAHOE
        !           279:                        adr = AdrFStackFix(RetFSp(vfp));
        !           280: #else
        !           281:                        adr = AdrFStackFix(RetFSp(vsp));
        !           282: #endif
        !           283:                        ibp = IbpFAdr(adr, 0, sbNil); /* temp BP at return */
        !           284:                        ibp = IbpFRun(ptResume);
        !           285:                } 
        !           286:                else {  /* NOT at a procedure call */
        !           287:                        if ((ibp = IbpFRun(ptSingle)) != ibpNil)
        !           288:                                return(ibp); /* a REAL breakpoint, so it MUST be kosher! */
        !           289:                        if (IpdFAdr(vpc) != ipdNil) {
        !           290:                                cBad = 0;
        !           291:                        } 
        !           292:                        else {
        !           293:                                /* we are in a file without good symbols */
        !           294:                                /* KLUDGE! There is a problem here.
        !           295:                                                 * Some trips to boony land are short, like the switch code
        !           296:                                                 * for Onyx, some are MUCH longer, like the printf code.
        !           297:                                                 * What we do is go along with the joke for up to
        !           298:                                                 * vcBadMax `bad' instructions.  If we don't see daylight, we
        !           299:                                                 * set an up level break from the (hopefully good) return
        !           300:                                                 * address.  There are NO GUARANTEES that this is correct,
        !           301:                                                 * but it seems to work MOST of the time.
        !           302:                                                 */
        !           303:                                if (++cBad >= vcBadMax) {
        !           304:                                        /* set uplevel break and wait for it to come home */
        !           305:                                        adr = RetFFp(vfp); /* get return */
        !           306:                                        ibp = IbpFAdr(adr, 0, sbNil);
        !           307:                                        ibp = IbpFRun(ptResume);
        !           308:                                } /* if */
        !           309:                                slop = -1;
        !           310:                        } /* if */
        !           311:                } /* if */
        !           312:                if ( (ibp != ibpNil) OR (vpid == pidNil) )
        !           313:                        return(ibp);
        !           314:                if (cBad == 0)
        !           315:                        IfdLnFAdr(vpc, isym0, &ifd, &ln, &slop);
        !           316:        } /* while */
        !           317: 
        !           318:        if ((vpid != pidNil) AND (ibp == ibpNil))
        !           319:                PrintPos(vpc, (fQuiet) ? fmtNil : fmtProc+fmtLn+fmtPrint);
        !           320:        return(ibp);
        !           321: } /* IbpFSingle */
        !           322: 
        !           323: 
        !           324: /* these routines maintain the list of assertions.
        !           325:  * since the presence of even ONE assertion forces the
        !           326:  * child process to singlestep, they should only be used
        !           327:  * when your back is against the wall e.g. someone is stepping
        !           328:  * on a global and you don't know who!
        !           329:  */
        !           330: 
        !           331: 
        !           332: /* I N I T   A S S E R T */
        !           333: 
        !           334: export void InitAssert()
        !           335: {
        !           336:        viadMac = 0;
        !           337:        vrgAd = (pADR) malloc(viadMax * cbADR);
        !           338:        vcbTot += viadMax * cbADR;
        !           339:        vas = asActive;
        !           340: } /* InitAssert */
        !           341: 
        !           342: 
        !           343: /* L I S T   A S S E R T */
        !           344: 
        !           345: export void ListAssert()
        !           346: {
        !           347:        int             i;
        !           348: 
        !           349:        if (viadMac == 0)
        !           350:                UError("No assertions");
        !           351:        printf("Assertions in general are %s\n\n",
        !           352:        (vas == asActive) ? "ACTIVE" : "SUSPENDED");
        !           353:        for (i=0; i < viadMac; i++) {
        !           354:                printf("%2d: %s %s\n", i,
        !           355:                (vrgAd[i].as==asActive) ? "Active" : "Suspended", vrgAd[i].sbCheck);
        !           356:        } /* for */
        !           357: } /* ListAssert */
        !           358: 
        !           359: 
        !           360: /* A D D   A S S E R T */
        !           361: 
        !           362: export void AddAssert(sbCheck)
        !           363: char   *sbCheck;
        !           364: {
        !           365:        int             cb, iad;
        !           366: 
        !           367:        if (viadMac >= viadMax)
        !           368:                UError("Too many assertions");
        !           369:        iad = viadMac++;
        !           370:        cb = strlen(sbCheck);
        !           371:        vrgAd[iad].sbCheck = malloc(cb+1); /* room for null */
        !           372:        vcbTot += cb + 1;
        !           373:        strcpy(vrgAd[iad].sbCheck, sbCheck);
        !           374:        vrgAd[iad].sbCheck[cb] = chNull;
        !           375:        vrgAd[iad].as = asActive;
        !           376:        printf("Assertion %d: Active \"%s\"\n", iad, vrgAd[iad].sbCheck);
        !           377:        vas = asActive;
        !           378:        printf("Assertions are ACTIVE");
        !           379: } /* AddAssert */
        !           380: 
        !           381: 
        !           382: /* M O D   A S S E R T */
        !           383: 
        !           384: export void ModAssert(iad, as)
        !           385: int    iad;
        !           386: ASE    as;
        !           387: {
        !           388:        if (iad < 0 OR iad >= viadMac)
        !           389:                UError("Bad assertion number: %d", iad);
        !           390:        vrgAd[iad].as = as;
        !           391:        if (as == asNil) {
        !           392:                free(vrgAd[iad].sbCheck);
        !           393:                vrgAd[iad] = vrgAd[viadMac-1];  /* fold it back on itself */
        !           394:                viadMac--;
        !           395:        }
        !           396:        if (vas == asSuspended)
        !           397:                return;
        !           398:        for (iad = 0; iad < viadMac; iad++)
        !           399:                if (vrgAd[iad].as == asActive)
        !           400:                        return;
        !           401:        printf("Assertions are ACTIVE");
        !           402:        vas = asSuspended;
        !           403: } /* ModAssert */
        !           404: 
        !           405: 
        !           406: /* F   D O   A S S E R T */
        !           407: 
        !           408: export void FDoAssert(pt)
        !           409: int    pt;
        !           410: {
        !           411:        int             iad;
        !           412:        long    cnt;
        !           413: 
        !           414:        vfRunAssert = false;  /* so we are not recursive entered from IbpFRun */
        !           415:        PushCmd(vsbCmd);        /* save what we are doing */
        !           416:        for (cnt=(pt==ptSingle) ? 1 : -1;cnt != 0; --cnt) {
        !           417:                /* we do the assertions BEFORE the line is executed */
        !           418:                for(iad=0; iad < viadMac; iad++) {
        !           419:                        if ((vrgAd[iad].as == asActive)
        !           420:                            AND (FDoCommand(vrgAd[iad].sbCheck, false))) {
        !           421:                                /* we hit an 'x' (exit) command - stop the parade! */
        !           422:                                printf("\nHit on assertion %d: \"%s\"\n",
        !           423:                                iad, vrgAd[iad].sbCheck);
        !           424:                                printf("Last line executed was:\n");
        !           425:                                PrintPos(vpcLast, fmtFile+fmtProc+fmtLn+fmtPrint+fmtSave);
        !           426:                                printf("Next line to execute is:\n");
        !           427:                                PrintPos(vpc, fmtFile+fmtProc+fmtLn+fmtPrint);
        !           428:                                vfRunAssert = true;
        !           429:                                return(true);
        !           430:                        } /* if */
        !           431:                } /* for */
        !           432:                vpcLast = vpc;  /* remember where the current line is */
        !           433:                /* step the process one statement's worth */
        !           434:                if (ibpNil != IbpFSingle(false, true)) {
        !           435:                        vfRunAssert = true;
        !           436:                        return(false);
        !           437:                } /* if */
        !           438:        } /* for */
        !           439:        PrintPos(vpc, fmtNil);  /* restore our context */
        !           440:        vfRunAssert = true;
        !           441:        return(false);
        !           442: } /* FDoAssert */

unix.superglobalmegacorp.com

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