Annotation of cci/usr/src/bin/cdb/single.c, revision 1.1.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.