Annotation of coherent/b/bin/db/db3.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * db/db3.c
                      3:  * A debugger.
                      4:  * Command execution and display routines.
                      5:  */
                      6: 
                      7: #include "db.h"
                      8: #include <signal.h>
                      9: 
                     10: /*
                     11:  * Execute a command.
                     12:  * Return 1 if more commands may be read,
                     13:  * 0 to stop reading commands (for :e, :c, :s).
                     14:  */
                     15: int
                     16: command(vp) register VAL *vp;
                     17: {
                     18:        register int c, sig;
                     19: 
                     20:        switch (c = getn()) {
                     21: 
                     22:        /* [addr]:a     Print address (default: .) */
                     23:        case 'a':
                     24:                if (getn() != '\n')
                     25:                        break;
                     26:                putaddr(val_segn(vp), lvalue(vp, dot));
                     27:                putx('\n');
                     28:                return 1;
                     29: 
                     30:        /* [addr]:b[r][cmd]     Set [return] breakpoint */
                     31:        case 'b':
                     32:                if (!IS_OBJ)
                     33:                        break;
                     34:                if ((c = getn()) != 'r') {
                     35:                        ungetn(c);
                     36:                        c = 'b';
                     37:                }
                     38:                getline("i+.:a\ni+.?i\n:x");
                     39:                /* FIX_ME :br only works at current pc, not at specified addr. */
                     40:                if ((c == 'r' && bpt_setr(miscbuf) == 0)
                     41:                 || (c != 'r' && bpt_set(BBPT, lvalue(vp, dot), 0L, miscbuf) == 0))
                     42:                        printe("Cannot set breakpoint");
                     43:                return 1;
                     44: 
                     45:        /* [addr]:c     Continue         */
                     46:        case 'c':
                     47:                if (getn() != '\n')
                     48:                        break;
                     49:                else
                     50:                        c = '\n';
                     51:                if (execflag == 0)
                     52:                        break;
                     53:                if (nvalue(vp) == 0)
                     54:                        set_pc(lvalue(vp, (ADDR_T)0));
                     55:                step_mode = SNULL;
                     56:                return 0;
                     57: 
                     58:        /* [addr]:d[r][s]       Delete breakpoint */
                     59:        case 'd':
                     60:                if (!IS_OBJ)
                     61:                        break;
                     62:                if ((c = getn()) != 'r' && c != 's') {
                     63:                        ungetn(c);
                     64:                        c = 'b';
                     65:                }
                     66:                if (getn() != '\n')
                     67:                        break;
                     68:                if (bpt_del(c, lvalue(vp, dot)) == 0)
                     69:                        printe("Cannot delete breakpoint");
                     70:                return 1;
                     71: 
                     72:        /* [addr]:eargs         Execute */
                     73:        case 'e':
                     74:                if (nvalue(vp) == 0)
                     75:                        set_pc(lvalue(vp, (ADDR_T)0));
                     76:                getline("");
                     77:                return runfile();
                     78: 
                     79:        /* :f           Print fault type */
                     80:        case 'f':
                     81:                if (getn() != '\n')
                     82:                        break;
                     83:                sig = get_sig();
                     84:                printx("%s\n", (sig == 0)   ? "no fault"
                     85:                             : (sig > NSIG) ? "bad signal number"
                     86:                             : signame[sig]);
                     87:                return 1;
                     88: 
                     89:        /* :h[f]                Print help info */
                     90:        case 'h':
                     91:                if ((c = getn()) != 'f')
                     92:                        ungetn(c);
                     93:                if (getn() != '\n')
                     94:                        break;
                     95:                helpinfo(c == 'f');
                     96:                return 1;
                     97: 
                     98:        /* [n]:k        ??? send a signal ??? */
                     99:        case 'k':
                    100:                if (execflag == 0)
                    101:                        break;
                    102:                if (getn() != '\n')
                    103:                        break;
                    104:                if (nvalue(vp) != 0) {
                    105:                        printe("No signal specified");
                    106:                        return 1;
                    107:                }
                    108:                printr("Cannot send %d", (int)rvalue(vp, 0L));
                    109:                return 1;
                    110: 
                    111:        /* :m           Print segmentation map */
                    112:        case 'm':
                    113:                if (getn() != '\n')
                    114:                        break;
                    115:                map_print();
                    116:                return 1;
                    117: 
                    118:        /* case 'n':    Documented but not implemented? */
                    119: 
                    120: #ifndef        NOCANON
                    121:        /* [expr]:o     Change canon type, UNDOCUMENTED... */
                    122:        case 'o':
                    123:                if (getn() != '\n')
                    124:                        break;
                    125:                cantype = rvalue(vp, 0L);
                    126:                return 1;
                    127: #endif
                    128: 
                    129:        /* :p           Print breakpoints */
                    130:        case 'p':
                    131:                if (getn() != '\n')
                    132:                        break;
                    133:                bpt_display();
                    134:                return 1;
                    135: 
                    136:        /* [expr]:q     Quit     */
                    137:        case 'q':
                    138:                if (getn() != '\n')
                    139:                        break;
                    140:                if (rvalue(vp, 1L))
                    141:                        leave();
                    142:                return 1;
                    143: 
                    144:        /* :r[N]        Print registers [including NDP] */
                    145:        case 'r':
                    146:                if ((c = getn()) == 'N')
                    147:                        c = R_ALL;
                    148:                else {
                    149:                        ungetn(c);
                    150:                        c = R_GEN;
                    151:                }
                    152:                if (getn() != '\n')
                    153:                        break;
                    154:                if (reg_flag == R_INVALID)
                    155:                        break;
                    156:                display_reg(c);
                    157:                return 1;
                    158: 
                    159:        /* [addr][,n]:s[c]      Single step [n times] [over calls] */
                    160:        case 's':
                    161:                if (execflag == 0)
                    162:                        break;
                    163:                if (nvalue(vp) == 0)
                    164:                        set_pc(lvalue(vp, (ADDR_T)0));
                    165:                step_count = rvalue(&vp[1], 1L);
                    166:                if ((c = getn()) != 'c') {
                    167:                        step_mode = SSTEP;
                    168:                        ungetn(c);
                    169:                } else
                    170:                        step_mode = SCONT;
                    171:                getline("i+.?i");
                    172:                step_cmd = save_cmd(step_cmd, miscbuf);
                    173:                return 0;
                    174: 
                    175:        /* [expr]:t     Call traceback [expr levels] */
                    176:        case 't':
                    177:                if (getn() != '\n')
                    178:                        break;
                    179:                else
                    180:                        c = '\n';
                    181:                if (reg_flag == R_INVALID)
                    182:                        break;
                    183:                traceback((int)rvalue(vp, 0L));
                    184:                return 1;
                    185: 
                    186:        /* [expr]:x      Read and execute stdin */
                    187:        case 'x':
                    188:                if (getn() != '\n')
                    189:                        break;
                    190:                if (rvalue(vp, 1L)) {
                    191:                        step_prev = step_mode;
                    192:                        step_mode = SNULL;
                    193:                        add_input(IFILE, (char *)stdin);
                    194:                }
                    195:                return 1;
                    196:        }
                    197:        printe("Illegal command");
                    198:        while (c != '\n')
                    199:                c = getn();
                    200:        return 1;
                    201: }
                    202: 
                    203: /*
                    204:  * Print out data from segment 's' according to the given format "t1 t2".
                    205:  */
                    206: char *
                    207: conform(sp, s, t1, t2) register char *sp; int s, t1, t2;
                    208: {
                    209:        register char *lp;
                    210:        char c;
                    211:        unsigned char uc;
                    212:        short sh;
                    213:        unsigned short us;
                    214:        int  i;
                    215:        unsigned int ui;
                    216:        long l;
                    217:        unsigned char v[3];
                    218:        ADDR_T p;
                    219: #ifndef        NOFP
                    220:        float f;
                    221:        double d;
                    222:        struct _fpreg fpreg;
                    223: #endif
                    224: 
                    225:        dbprintf(("conform(... s=%d t1=%c t2=%c)\n", s, t1, t2));
                    226:        switch (t1) {
                    227: 
                    228:        case 'b':                               /* byte */
                    229:                if (getb(s, &uc, sizeof(uc)) == 0)
                    230:                        return NULL;
                    231:                modsize = sizeof(uc);
                    232: 
                    233:                /* Sign-extend or 0-extend depending on display format. */
                    234:                if (t2 != 'd')
                    235:                        i = ui = (unsigned int)uc;
                    236:                else
                    237:                        i = c = uc;
                    238:                sprintf(sp, get_format(t1, t2), i);
                    239:                break;
                    240:        case 'c':                               /* char with escapes */
                    241:                if (getb(s, &uc, sizeof(uc)) == 0)
                    242:                        return NULL;
                    243:                modsize = sizeof(uc);
                    244:                return printable(sp, uc);
                    245:        case 'C':                               /* char */
                    246:                if (getb(s, &uc, sizeof(uc)) == 0)
                    247:                        return NULL;
                    248:                modsize = sizeof(uc);
                    249:                *sp++ = (uc >= 0x20 && uc < 0x7F) ? uc : '.';
                    250:                return sp;
                    251: #ifndef        NOFP
                    252:        case 'f':                               /* float */
                    253:                if (getb(s, (char *)&f, sizeof(f)) == 0)
                    254:                        return NULL;
                    255:                modsize = sizeof(f);
                    256:                sprintf(sp, get_format(t1, t2), f);
                    257:                break;
                    258:        case 'F':                               /* double */
                    259:                if (getb(s, (char *)&d, sizeof(d)) == 0)
                    260:                        return NULL;
                    261:                modsize = sizeof(d);
                    262:                sprintf(sp, get_format(t1, t2), d);
                    263:                break;
                    264:        case 'N':                               /* NDP fp register */
                    265:                if (getb(s, (char *)&fpreg, sizeof(fpreg)) == 0)
                    266:                        return NULL;
                    267:                if (get_fp_reg(&fpreg, &d) == 0)
                    268:                        return NULL;
                    269:                modsize = sizeof(fpreg);
                    270:                sprintf(sp, get_format('F', t2), d);
                    271:                break;
                    272: #endif
                    273:        case 'h':
                    274:                if (getb(s, (char *)&us, sizeof(us)) == 0)
                    275:                        return NULL;
                    276:                modsize = sizeof(us);
                    277: 
                    278:                /* Sign-extend or 0-extend depending on display format. */
                    279:                if (t2 != 'd')
                    280:                        i = ui = us;
                    281:                else
                    282:                        i = sh = us;
                    283:                sprintf(sp, get_format(t1, t2), i);
                    284:                break;
                    285:        case 'i':                               /* machine instruction */
                    286:                modsize = INLEN;
                    287:                return disassemble(sp, s);
                    288:        case 'l':                               /* long */
                    289:                if (getb(s, (char *)&l, sizeof(l)) == 0)
                    290:                        return NULL;
                    291:                modsize = sizeof(l);
                    292:                sprintf(sp, get_format(t1, t2), l);
                    293:                break;
                    294:        case 'p':                               /* pointer */
                    295:                if (getb(s, (char *)&p, sizeof(p)) == 0)
                    296:                        return NULL;
                    297:                modsize = sizeof(p);
                    298:                return cvt_addr(sp, find_seg(p), p);
                    299:        case 's':                               /* string with escapes */
                    300:        case 'S':                               /* string */
                    301:                lp = &sp[DISSIZE];
                    302:                for (;;) {
                    303:                        if (getb(s, &uc, sizeof(uc)) == 0)
                    304:                                return NULL;
                    305:                        if (uc == '\0')
                    306:                                break;
                    307:                        if (t1 == 's')
                    308:                                sp = printable(sp, uc);
                    309:                        else
                    310:                                *sp++ = uc;
                    311:                        if (sp > lp)
                    312:                                return NULL;
                    313:                }
                    314:                modsize = sizeof(i);
                    315:                return sp;
                    316:        case 'v':                               /* l3 */
                    317:                if (getb(s, (char *)v, sizeof(v)) == 0)
                    318:                        return NULL;
                    319:                modsize = sizeof(v);
                    320:                l3tol(&l, v, 1);
                    321:                sprintf(sp, get_format(t1, t2), l);
                    322:                break;
                    323:        case 'w':                               /* word */
                    324:                if (getb(s, (char *)&us, sizeof(us)) == 0)
                    325:                        return NULL;
                    326:                modsize = sizeof(us);
                    327:                sprintf(sp, get_format(t1, t2), (int)us);
                    328:                break;
                    329:        case 'Y':                               /* time */
                    330:                modsize = sizeof(i);
                    331:                return gettime(sp, s);
                    332:        default:
                    333:                return NULL;
                    334:        }
                    335:        return strchr(sp, '\0');
                    336: }
                    337: 
                    338: /*
                    339:  * Print out 'n' data items from segment 's'.
                    340:  */
                    341: int
                    342: display(s, n) int s, n;
                    343: {
                    344:        register char *sp1, *sp2, *fs;
                    345:        register int c, r, t1, t2;
                    346:        register char *sp3, *fp;
                    347:        register ADDR_T nad, pad, uad;
                    348: 
                    349:        dbprintf(("display(%d, %d) dot=%x\n", s, n, dot));
                    350:        r = 1;
                    351:        t2 = '\0';
                    352:        add = nad = pad = uad = dot;
                    353:        sp1 = miscbuf;
                    354:        sp3 = &sp1[DISSIZE];
                    355:        fs = seg_format[s];
                    356:        while (n--) {
                    357:                fp = fs;
                    358:                for (;;) {
                    359:                        c = *fp++;
                    360:                        if (isascii(c) && isdigit(c)) {
                    361:                                r = 0;
                    362:                                do {
                    363:                                        r = r*10 + c-'0';
                    364:                                        c = *fp++;
                    365:                                } while (isascii(c) && isdigit(c));
                    366:                                --fp;
                    367:                                continue;
                    368:                        }
                    369:                        switch (c) {
                    370:                        case '^':
                    371:                                add = uad;
                    372:                                continue;
                    373:                        case '+':
                    374:                                add += r;
                    375:                                r = 1;
                    376:                                continue;
                    377:                        case '-':
                    378:                                add -= r;
                    379:                                r = 1;
                    380:                                continue;
                    381:                        case 'n':
                    382:                                *sp1 = '\0';
                    383:                                flushb(nad);
                    384:                                sp1 = miscbuf;
                    385:                                nad = add;
                    386:                                continue;
                    387:                        case 'd':
                    388:                        case 'o':
                    389:                        case 'u':
                    390:                        case 'x':
                    391:                                t2 = c;
                    392:                                continue;
                    393:                        default:
                    394:                                t1 = c;
                    395:                                if (t1=='\0' && t2=='\0')
                    396:                                        break;
                    397:                                if (t1 == '\0')
                    398:                                        t1 = 'w';
                    399:                                if (t2 == '\0')
                    400:                                        t2 = DDCHR;
                    401:                                uad = add;
                    402:                                while (r--) {
                    403:                                        if (testint())
                    404:                                                return 1;
                    405:                                        *sp1++ = ' ';
                    406:                                        pad = add;
                    407:                                        sp2 = conform(sp1, s, t1, t2);
                    408:                                        if (sp2 == NULL) {
                    409:                                                *--sp1 = '\0';
                    410:                                                if (sp1 != miscbuf)
                    411:                                                        flushb(nad);
                    412:                                                dbprintf(("add=0x%lX cseg=%d\n", add, cseg));
                    413:                                                return printe("Addressing error");
                    414:                                        }
                    415:                                        if (sp2 <= sp3)
                    416:                                                sp1 = sp2;
                    417:                                        else {
                    418:                                                *--sp1 = '\0';
                    419:                                                flushb(nad);
                    420:                                                *sp2 = '\0';
                    421:                                                *sp1 = ' ';
                    422:                                                sp2 = sp1;
                    423:                                                sp1 = miscbuf;
                    424:                                                while (*sp2)
                    425:                                                        *sp1++ = *sp2++;
                    426:                                                nad = pad;
                    427:                                        }
                    428:                                        if (c == 'i') {
                    429:                                                *sp1++ = '\0';
                    430:                                                flushb(nad);
                    431:                                                sp1 = miscbuf;
                    432:                                                nad = add;
                    433:                                        }
                    434:                                }
                    435:                                r = 1;
                    436:                                t2 = '\0';
                    437:                                if (c != '\0')
                    438:                                        continue;
                    439:                        }
                    440:                        break;
                    441:                }
                    442:                old_add = add;
                    443:        }
                    444:        if (sp1 != miscbuf) {
                    445:                *sp1 = '\0';
                    446:                flushb(nad);
                    447:        }
                    448:        return 1;
                    449: }
                    450: 
                    451: /*
                    452:  * Execute a command string.
                    453:  */
                    454: void
                    455: execute(cmd) char *cmd;
                    456: {
                    457:        register INP *ip;
                    458: 
                    459:        dbprintf(("execute(%s)\n", cmd));
                    460: 
                    461:        /* Delete input list starting at "inpp". */
                    462:        while ((ip = inpp) != (INP *)NULL) {
                    463:                inpp = ip->i_next;
                    464:                nfree(ip);
                    465:        }
                    466:        ungotc = '\0';                  /* clear ungot character */
                    467: 
                    468:        /* Muck with some globals. */
                    469:        modsize = sizeof(int);
                    470:        step_prev = SNULL;
                    471:        dot = get_pc();
                    472: 
                    473:        /* Add string "cmd" to the input list and process it. */
                    474:        if (cmd != NULL) {
                    475:                add_input(ICORE, cmd);
                    476:                request();
                    477:        }
                    478: 
                    479:        /* Check for interrupt. */
                    480:        testint();
                    481: }
                    482: 
                    483: /*
                    484:  * Flush the output buffer.
                    485:  * Print the given address 'addr' before the contents of the buffer
                    486:  * and set dot to it.
                    487:  */
                    488: void
                    489: flushb(addr) ADDR_T addr;
                    490: {
                    491:        dot = addr;
                    492:        printx(addr_fmt, dot);
                    493:        printx("\t%s\n", miscbuf);
                    494: }
                    495: 
                    496: /*
                    497:  * Display help info.
                    498:  * The flag is false for :h, true for :hf.
                    499:  */
                    500: void
                    501: helpinfo(flag) int flag;
                    502: {
                    503:        printf(flag
                    504:         ?      "[addr][,n]?[ft]\tDisplay formatted information.\n"
                    505:                "Display formats:\n"
                    506:                "\tb\tbyte\n"
                    507:                "\tc\tchar, control and non-chars escaped\n"
                    508:                "\tC\tchar, control and non-chars print as '.'\n"
                    509:                "\td\tdecimal\n"
                    510:                "\tf\tfloat\n"
                    511:                "\tF\tdouble\n"
                    512:                "\ti\tdisassembled machine instruction\n"
                    513:                "\tl\tlong\n"
                    514:                "\tn\toutput '\\n'\n"
                    515:                "\tN\tNDP (80387) floating point register (10 bytes)\n"
                    516:                "\to\toctal\n"
                    517:                "\tp\tsymbolic address\n"
                    518:                "\ts\tstring (NUL-terminated) with escapes\n"
                    519:                "\tS\tstring (NUL-terminated)\n"
                    520:                "\tu\tunsigned\n"
                    521:                "\tv\tfilesystem l3 block address (3 bytes)\n"
                    522:                "\tw\tword\n"
                    523:                "\tx\thexadecimal\n"
                    524:                "\tY\ttime\n"
                    525:                "[doux] specify numeric bases (decimal, octal, unsigned decimal, hexadecimal).\n"
                    526:                "Each may be followed by [bwl] to indicate a datum size [byte, word, long].\n"
                    527:         :      "Requests:\n"
                    528:                "\t[addr][,n]?[ft]\tDisplay formatted information.\n"
                    529:                "\t\t\tFormats: bcCdfFilnNopsSuvwxY [see :hf for details]\n"
                    530:                "\taddr?\t\tPrint address\n"
                    531:                "\t[addr]=\t\tPrint address\n"
                    532:                "\t[addr]=val...\tPatch address with val...\n"
                    533:                "\t?\t\tPrint last error message\n"
                    534:                "\t!cmd\t\tSend cmd to system\n"
                    535:                "\t[addr]:a\tPrint address\n"
                    536:                "\t[addr]:b[cmd]\tSet breakpoint [to execute cmd]\n"
                    537:                "\t:br[cmd]\tSet return breakpoint [to execute cmd]\n"
                    538:                "\t[addr]:c\tContinue [from addr]\n"
                    539:                "\t[addr]:d[r][s]\tDelete breakpoint\n"
                    540:                "\t[addr]:e args\tExecute\n"
                    541:                "\t:f\t\tPrint fault type\n"
                    542:                "\t:h[f]\t\tPrint help information [about display formats]\n"
                    543: /*             "\t:k\t\t???\n" */
                    544:                "\t:m\t\tPrint segmentation map\n"
                    545: #ifndef        NOCANON
                    546:                "\t[expr]:o\t\tSet canonization type\n"
                    547: #endif
                    548:                "\t:p\t\tPrint breakpoints\n"
                    549:                "\t[expr]:q\tQuit\n"
                    550:                "\t:r[N]\t\tPrint registers [including NDP]\n"
                    551:                "\t[addr][,n]:s[c]\tSingle step [over calls]\n"
                    552:                "\t[expr]:t\tPrint traceback [to expr levels]\n"
                    553:                "\t[expr]:x\tRead commands from stdin\n"
                    554:        );
                    555: }
                    556: 
                    557: /*
                    558:  * Get a long representing the current time and convert it.
                    559:  */
                    560: char *
                    561: gettime(sp, s) register char *sp; int s;
                    562: {
                    563:        long l;
                    564: 
                    565:        if (getb(s, (char *)&l, sizeof(l)) == 0)
                    566:                return NULL;
                    567:        memcpy(sp, ctime(&l), 24);
                    568:        return sp + 24;
                    569: }
                    570: 
                    571: /*
                    572:  * If the given character is unprintable,
                    573:  * convert it into an escape sequence.
                    574:  */
                    575: char *
                    576: printable(sp, c) register char *sp; register int c;
                    577: {
                    578:        *sp++ = '\\';
                    579:        switch (c) {
                    580:        case '\0':      *sp++ = '0';            break;
                    581:        case '\b':      *sp++ = 'b';            break;
                    582:        case '\n':      *sp++ = 'n';            break;
                    583:        case '\f':      *sp++ = 'f';            break;
                    584:        case '\r':      *sp++ = 'r';            break;
                    585:        case '\\':      *sp++ = '\\';           break;
                    586:        default:
                    587:                if (c<040 || c>=0177) {
                    588:                        sprintf(sp, "%03o", c);
                    589:                        while (*sp)
                    590:                                sp++;
                    591:                        break;
                    592:                }
                    593:                sp[-1] = c;
                    594:                break;
                    595:        }
                    596:        return sp;
                    597: }
                    598: 
                    599: /*
                    600:  * Talk to the user and try to solve his problems.
                    601:  */
                    602: void
                    603: process()
                    604: {
                    605:        static char *xcmd = ":x\n";
                    606:        static char *fxcmd = ":f\n:x\n";
                    607:        register BPT *bp;
                    608:        register ADDR_T pc, fp;
                    609:        register int n;
                    610:        register int bpt_next, bpt_skipped;
                    611:        int step_flag;                  /* 0==not step, 1==step, 2==syscall */
                    612: 
                    613:        /*
                    614:         * Reverse-engineered pseudocode, minus global variable garbage.
                    615:         *
                    616:         * forever:
                    617:         *   execute(":x\n") <= Preload interpreter stack.
                    618:         *   (Will come back after traced process traps, e.g. after ":e".)
                    619:         *   forever:
                    620:         *     See if at call instruction.
                    621:         *     Install breakpoints, except at current instruction.
                    622:         *     See if current instruction is a breakpoint opcode.
                    623:         *     Start up traced process, full speed or single step.
                    624:         *     Report any error from ptrace call.
                    625:         *     Wait for traced process.
                    626:         *     Fetch registers and signal received from traced process.
                    627:         *     Replace breakpoints with instructions.
                    628:         *     If signal to child was not SIGTRAP
                    629:         *       display message
                    630:         *       execute(":f\n:x\n");
                    631:         *       continue inner loop
                    632:         *     Back up instruction pointer to start of the breakpoint.
                    633:         *     If single stepping
                    634:         *       Execute single step command string (step_cmd).
                    635:         *       If last single step in count
                    636:         *         execute(":x\n")
                    637:         *   end forever
                    638:         * end forever
                    639:         *
                    640:         */
                    641: top:
                    642:        execute(xcmd);
                    643:        for (;;) {
                    644: 
                    645:                /*
                    646:                 * If in single step mode, set up for single step.
                    647:                 * If in SCONT mode (for :sc),
                    648:                 * change to SCALL mode at call instruction.
                    649:                 */
                    650:                if (step_mode != SNULL && step_mode != SWAIT) {
                    651:                        /* Single stepping. */
                    652:                        step_flag = 1;
                    653:                        if (step_mode == SCONT && is_call())
                    654:                                step_mode = SCALL;
                    655:                } else
                    656:                        step_flag = 0;
                    657: 
                    658:                /* Place all breakpoints. */
                    659:                if (reg_flag != R_INVALID)
                    660:                        pc = get_pc();
                    661:                for (bpt_skipped = 0, bp = &bpt[0]; bp < &bpt[NBPT]; bp++) {
                    662: 
                    663:                        /* Skip unused table entries. */
                    664:                        if (bp->b_flag == 0)
                    665:                                continue;
                    666: 
                    667:                        /*
                    668:                         * If there is a breakpoint at the current PC,
                    669:                         * we do not want to install it, or we'll get nowhere.
                    670:                         * But if we are not single-stepping, we really want
                    671:                         * the breakpoint reinstalled after doing a single step.
                    672:                         * Kludge the mode to SSTEP and set 'bpt_skipped' in
                    673:                         * this case so SNULL mode gets restored after a step.
                    674:                         */
                    675:                        if (reg_flag!=R_INVALID && bp->b_badd == pc) {
                    676:                                if (step_mode == SNULL) {
                    677:                                        step_mode = SSTEP;
                    678:                                        bpt_skipped = step_flag = 1;
                    679:                                }
                    680:                                continue;
                    681:                        }
                    682: 
                    683:                        /* Install a breakpoint. */
                    684:                        add = bp->b_badd;
                    685:                        dbprintf(("setting breakpoint @ %lX\n", add));
                    686:                        if (putb(ISEG, bin, sizeof(BIN)) == 0) {
                    687:                                printb(bp->b_badd);
                    688:                                goto err;
                    689:                        }
                    690:                }
                    691: 
                    692:                /* Set 'bpt_next' if next instruction is a breakpoint. */
                    693:                bpt_next = (reg_flag!=R_INVALID && bpt_test(pc));
                    694: 
                    695:                /* Watch out for system calls if single stepping. */
                    696:                if (is_syscall(&step_flag) == 0)
                    697:                        goto err;
                    698: 
                    699:                /* Run the child. */
                    700:                if (runc() == 0)
                    701:                        goto err;
                    702: 
                    703:                /* Restore if we have stepped past system call. */
                    704:                if (step_flag == 2 && rest_syscall(&step_flag) == 0)
                    705:                        goto err;
                    706: 
                    707:                /* Replace breakpoints with instructions. */
                    708:                dbprintf(("Replace breakpoints with instructions\n"));
                    709:                for (bp = &bpt[0]; bp < &bpt[NBPT]; bp++) {
                    710:                        if (bp->b_flag == 0)
                    711:                                continue;               /* unused */
                    712:                        dbprintf(("Restore instruction %X in bpt[%d]\n", bp->b_bins[0] & 0xFF, bp - bpt));
                    713:                        add = bp->b_badd;
                    714:                        if (putb(ISEG, bp->b_bins, sizeof(BIN)) == 0) {
                    715:                                printb(bp->b_badd);
                    716:                                goto err;
                    717:                        }
                    718:                }
                    719:        
                    720:                /*
                    721:                 * If latest signal to traced process was not SIGTRAP,
                    722:                 * tell the user, then accept input.
                    723:                 */
                    724:                if (get_sig() != SIGTRAP) {
                    725:                        if (get_sig() != SIGINT)
                    726:                                printr("Traced process did not stop at a breakpoint");
                    727:                        printf("Traced process: ");
                    728:                        execute(fxcmd);
                    729:                        continue;
                    730:                }
                    731: 
                    732:                /* Resume running following skipped breakpoint. */
                    733:                if (bpt_skipped) {
                    734:                        step_mode = SNULL;
                    735:                        continue;
                    736:                }
                    737: 
                    738:                /*
                    739:                 * Find the breakpoint we are at.
                    740:                 * Back up pc to start of the breakpoint.
                    741:                 */
                    742:                bp = (BPT *)NULL;
                    743:                pc = get_pc() - sizeof(BIN);
                    744:                dbprintf(("find bpt: --pc=%x step_flag=%d bpt_next=%d\n", pc, step_flag, bpt_next));
                    745:                if (step_flag == 0 || bpt_next) {
                    746:                        for (bp = &bpt[0]; bp < &bpt[NBPT]; bp++) {
                    747:                                if (bp->b_flag == 0)
                    748:                                        continue;
                    749:                                if (bp->b_badd != pc)
                    750:                                        continue;
                    751:                                dbprintf(("found bpt[%d] at %x\n", bp-bpt, pc));
                    752:                                set_pc(pc);
                    753:                                break;
                    754:                        }
                    755:                        if (bp == &bpt[NBPT])
                    756:                                bp = (BPT *)NULL;       /* unknown */
                    757:                }
                    758: 
                    759:                /* If in single step mode, execute command. */
                    760:                dbprintf(("step_mode=%d\n", step_mode));
                    761:                switch (step_mode) {
                    762:                case SSTEP:
                    763:                case SCONT:
                    764:                        execute(step_cmd);
                    765:                        if (--step_count == 0)
                    766:                                execute(xcmd);
                    767:                        continue;
                    768:                case SCALL:
                    769:                        /*
                    770:                         * :sc has stepped into call with step_mode SCALL.
                    771:                         * Clear other BSIN breakpoints, place a BSIN breakpoint
                    772:                         * at the return address, and set step_mode SWAIT
                    773:                         * to run until the return is executed.
                    774:                         */
                    775:                        for (n = 0; n < NBPT; n++)
                    776:                                bpt[n].b_flag &= ~BSIN;
                    777:                        step_mode = SWAIT;
                    778:                        set_ra_bpt();           /* set BSIN bpt at return address */
                    779:                        break;
                    780:                }
                    781: 
                    782:                /*
                    783:                 * Handle an unexpected trace trap or unknown breakpoint.
                    784:                 * One way this can happen: if the child does not handle
                    785:                 * SIGINT, type "100:s" followed by "<Ctrl-C>" and ":c".
                    786:                 * The child is interrupted, the parent prints "Interrupted"
                    787:                 * and prompts, ":c" resumes the child with SNULL (step_flag 0),
                    788:                 * and the child then hits the actual breakpoint.
                    789:                 * t
                    790:                 */
                    791:                if (bp == (BPT *)NULL) {
                    792:                        dbprintf(("step_mode=%d step_flag=%d bpt_next=%d\n", step_mode, step_flag, bpt_next));
                    793:                        if (step_flag == 0 || bpt_next) {
                    794:                                printf("Unexpected ");
                    795:                                execute(fxcmd);
                    796:                        }
                    797:                        continue;
                    798:                }
                    799: 
                    800:                /* Single step breakpoints have highest priority. */
                    801:                fp = get_fp();
                    802:                if (bp->b_flag & BSIN) {
                    803:                        if (bp->b_sfpt==0 || bp->b_sfpt == fp) {
                    804:                                bp->b_flag &= ~BSIN;
                    805:                                if (step_mode == SWAIT) {
                    806:                                        /*
                    807:                                         * We hit the return from a called
                    808:                                         * function with :sc, restore SCONT mode.
                    809:                                         */
                    810:                                        step_mode = SCONT;
                    811:                                        execute(step_cmd);
                    812:                                        if (--step_count == 0)
                    813:                                               execute(xcmd);
                    814:                                        continue;
                    815:                                }
                    816:                        }
                    817:                }
                    818: 
                    819:                /* Return breakpoints are next. */
                    820:                if (bp->b_flag & BRET) {
                    821:                        if (bp->b_rfpt == fp) {
                    822:                                bp->b_flag &= ~BRET;
                    823:                                execute(bp->b_rcom);
                    824:                                continue;
                    825:                        }
                    826:                }
                    827: 
                    828:                /* Your conventional everyday ordinary breakpoint. */
                    829:                if (bp->b_flag & BBPT) {
                    830:                        execute(bp->b_bcom);
                    831:                        continue;
                    832:                }
                    833:        }
                    834: 
                    835:        /*
                    836:         * Something is terribly wrong.
                    837:         * Kill off our child and generally reset everything to the start.
                    838:         */
                    839: err:
                    840:        killc();
                    841:        initialize();
                    842:        map_init();
                    843:        if (IS_LOUT)
                    844:                setloutseg();
                    845:        else if (IS_COFF)
                    846:                setcoffseg();
                    847:        goto top;
                    848: }
                    849: 
                    850: /*
                    851:  * Parse requests and execute them.
                    852:  * This is a loop which eats input and process it,
                    853:  * using command() to execute commands.
                    854:  * It returns when command() returns 0 or on '\n' for single step.
                    855:  */
                    856: void
                    857: request()
                    858: {
                    859:        static int ttyflag = -1;
                    860:        register int c;
                    861:        register char *cp;
                    862:        register unsigned segn;
                    863:        register ADDR_T l, d;
                    864:        VAL val[VALSIZE];
                    865: 
                    866:        for(;;) {
                    867:                /* Prompt if appropriate. */
                    868:                if (ttyflag == -1)
                    869:                        ttyflag = isatty(fileno(stdin));
                    870:                if (ttyflag && inpp->i_type==IFILE && inpp->i_u.i_filp==stdin) {
                    871:                        printf(prompt);
                    872:                        fflush(stdout);
                    873:                }
                    874:                if ((c = getn()) == EOF)
                    875:                        break;
                    876: 
                    877:                /* !cmd         Execute cmd */
                    878:                if (c == '!') {
                    879:                        syscall();
                    880:                        continue;
                    881:                }
                    882: 
                    883:                /* ?            Print fault type */
                    884:                if (c == '?') {
                    885:                        if ((c = getn()) != '\n') {
                    886:                                printe("Syntax error");
                    887:                                goto next;
                    888:                        }
                    889:                        printr("%s", (lasterr == NULL) ? "No error" : lasterr);
                    890:                        continue;
                    891:                }
                    892:                ungetn(c);
                    893:                if (expr_list(val) == 0)                /* get expression list */
                    894:                        goto next;
                    895: 
                    896:                switch (c = getn()) {
                    897: 
                    898:                /* : indicates commands, handled by command(). */
                    899:                case ':':
                    900:                        step_prev = SNULL;
                    901:                        if (command(val) == 0)
                    902:                                return;
                    903:                        continue;
                    904: 
                    905:                /* \n indicates more of the same, single step or display */
                    906:                case '\n':
                    907:                        if (nvalue(&val[0]) && step_prev != SNULL) {
                    908:                                if (execflag == 0) {
                    909:                                        step_prev = SNULL;
                    910:                                        printe("Cannot single step");
                    911:                                        continue;
                    912:                                }
                    913:                                step_mode = step_prev;
                    914:                                step_count = rvalue(&val[1], 1L);
                    915:                                return;
                    916:                        }
                    917:                        /* else fall through to print value */
                    918: 
                    919:                /* addr\n       Print value */
                    920:                /* [addr]=val   Assign value */
                    921:                /* [addr]?      Print value */
                    922:                case '=':
                    923:                        ungetn(c);
                    924:                        /* fall through... */
                    925:                case '?':
                    926:                        step_prev = SNULL;
                    927:                        segn = val_segn(&val[0]);
                    928:                        if ((c = getn()) == '=') {
                    929:                                l = lvalue(&val[0], dot);
                    930:                                if ((c = getn()) == '\n') {
                    931:                                        dbprintf(("print seg=%d loc=%lx fmt=%s\n", segn, l, addr_fmt));
                    932:                                        printx(addr_fmt, l);
                    933:                                        printx("\n");
                    934:                                        continue;
                    935:                                }
                    936:                                ungetn(c);
                    937:                                dbprintf(("assign to seg=%d loc=%lx\n", segn, l));
                    938:                                if (setdata(segn, l) == 0)
                    939:                                        break;
                    940:                                continue;
                    941:                        }
                    942:                        if (c != '\n') {
                    943:                                cp = &seg_format[segn][0];
                    944:                                while (c != '\n') {
                    945:                                        *cp++ = c;
                    946:                                        c = getn();
                    947:                                }
                    948:                                *cp++ = '\0';
                    949:                                dbprintf(("new seg_format[%d]=%s\n", segn, seg_format[segn]));
                    950:                        }
                    951:                        d = dot;
                    952:                        l = old_add;
                    953:                        dot = lvalue(&val[0], old_add);
                    954:                        display(segn, (int)rvalue(&val[1], 1L));
                    955:                        if (segn != USEG)
                    956:                                cseg = segn;    /* set cseg unless USEG */
                    957:                        else {
                    958:                                dot = d;        /* restore dot, old_add if USEG */
                    959:                                old_add = l;
                    960:                        }
                    961:                        continue;
                    962: 
                    963:                default:
                    964:                        step_prev = SNULL;
                    965:                        printe("Syntax error");
                    966:                        break;
                    967:                }
                    968:        next:
                    969:                while ((c = getn()) != '\n')
                    970:                        ;
                    971:        }
                    972: }
                    973: 
                    974: /*
                    975:  * Parse the command line in 'miscbuf',
                    976:  * kill the current child and start up a new one.
                    977:  * Return 0 on success, 1 on failure.
                    978:  */
                    979: int
                    980: runfile()
                    981: {
                    982:        register char *bp, *cp;
                    983:        register int c;
                    984:        char *ifn, *ofn, *argl[ARGSIZE];
                    985:        int qflag, aflag, n;
                    986: 
                    987:        killc();
                    988:        if (!IS_OBJ) {
                    989:                printe("No executable");
                    990:                return 1;
                    991:        }
                    992:        ifn = ofn = NULL;
                    993:        aflag = qflag = n = 0;
                    994:        for (bp = cp = miscbuf, c = *bp++; c != '\n'; ) {
                    995:                switch (c) {
                    996:                case '<':
                    997:                        ifn = cp;
                    998:                        c = *bp++;
                    999:                        break;
                   1000:                case '>':
                   1001:                        ofn = cp;
                   1002:                        if ((c = *bp++) == '>') {
                   1003:                                aflag = 1;
                   1004:                                c = *bp++;
                   1005:                        }
                   1006:                        break;
                   1007:                default:
                   1008:                        if (n >= ARGSIZE-1) {
                   1009:                                printe("Too many arguments");
                   1010:                                return 1;
                   1011:                        }
                   1012:                        argl[n++] = cp;
                   1013:                }
                   1014:                while (qflag || !isascii(c) || !isspace(c)) {
                   1015:                        if (c == '\n')
                   1016:                                break;
                   1017:                        if (c == '"') {
                   1018:                                qflag ^= 1;
                   1019:                                c = *bp++;
                   1020:                                continue;
                   1021:                        }
                   1022:                        if (c == '\\') {
                   1023:                                if ((c=*bp++) == '\n') {
                   1024:                                        printe("Syntax error");
                   1025:                                        return 1;
                   1026:                                }
                   1027:                        }
                   1028:                        *cp++ = c;
                   1029:                        c = *bp++;
                   1030:                }
                   1031:                if (qflag) {
                   1032:                        printe("Missing '\"'");
                   1033:                        return 1;
                   1034:                }
                   1035:                *cp++ = '\0';
                   1036:                if (c == '\n')
                   1037:                        break;
                   1038:                while (isascii(c) && isspace(c))
                   1039:                        c = *bp++;
                   1040:        }
                   1041:        if (n == 0)
                   1042:                argl[n++] = lfn;
                   1043:        argl[n] = NULL;
                   1044:        return startc(argl, ifn, ofn, aflag) == 0;
                   1045: }
                   1046: 
                   1047: /*
                   1048:  * Given a pointer to an allocated buffer and a pointer to a command string,
                   1049:  * copy the command string to the allocated buffer.
                   1050:  * If the buffer hasn't been allocated, allocate it.
                   1051:  */
                   1052: char *
                   1053: save_cmd(buf, s) register char *buf, *s;
                   1054: {
                   1055:        if (buf == NULL)
                   1056:                buf = nalloc(COMSIZE, "command buffer");
                   1057:        buf[COMSIZE-1] = '\0';
                   1058:        return strncpy(buf, s, COMSIZE-1);
                   1059: }
                   1060: 
                   1061: /*
                   1062:  * Change the value of a location.
                   1063:  */
                   1064: int
                   1065: setdata(segn, a) int segn; ADDR_T a;
                   1066: {
                   1067:        register char *cp;
                   1068:        register int n;
                   1069:        register int c;
                   1070:        char b[1];
                   1071:        char l3[3];
                   1072:        int i[1];
                   1073:        long l[1];
                   1074:        VAL val[VALSIZE];
                   1075: 
                   1076:        if (expr_list(val) == 0)
                   1077:                return 0;
                   1078:        if ((c = getn()) != '\n')
                   1079:                return 0;
                   1080:        for (n = 0; n < VALSIZE; n++, a += modsize) {
                   1081:                if (nvalue(&val[n]))
                   1082:                        continue;
                   1083:                l[0] = rvalue(&val[n], 0L);
                   1084:                switch (modsize) {
                   1085:                case (sizeof(char)):
                   1086:                        b[0] = l[0];
                   1087:                        cp = b;
                   1088:                        break;
                   1089:                case (sizeof(short)):
                   1090:                        i[0] = l[0];
                   1091:                        cp = (char *)i;
                   1092:                        break;
                   1093:                case (sizeof(l3)):
                   1094:                        ltol3(l3, l, 1);
                   1095:                        cp = l3;
                   1096:                        break;
                   1097:                case (sizeof(long)):
                   1098:                        cp = (char *)l;
                   1099:                        break;
                   1100:                default:
                   1101:                        printe("Bad change type");
                   1102:                        return 1;
                   1103:                }
                   1104:                add = a;
                   1105:                if (putb(segn, cp, modsize) == 0) {
                   1106:                        printe("Cannot change value");
                   1107:                        return 1;
                   1108:                }
                   1109:        }
                   1110:        if (segn == USEG) {
                   1111:                /* Reread required registers after writing register data. */
                   1112:                reg_flag = R_INVALID;
                   1113:                get_regs(R_SOME);
                   1114:        }
                   1115:        return 1;
                   1116: }
                   1117: 
                   1118: /*
                   1119:  * Send a command to the shell.
                   1120:  * Return its exit status.
                   1121:  */
                   1122: int
                   1123: syscall()
                   1124: {
                   1125:        register int c, status;
                   1126:        register char *cp;
                   1127: 
                   1128:        for (cp = miscbuf; (c = getn()) != '\n'; )
                   1129:                *cp++ = c;
                   1130:        *cp = '\0';
                   1131:        status = system(miscbuf);
                   1132:        testint();
                   1133:        printf("!\n");
                   1134:        return status;
                   1135: }
                   1136: 
                   1137: /* end of db/db3.c */

unix.superglobalmegacorp.com

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