Annotation of 42BSD/ucb/dbx/machine.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1982 Regents of the University of California */
                      2: 
                      3: static char sccsid[] = "@(#)machine.c 1.9 8/5/83";
                      4: 
                      5: /*
                      6:  * Target machine dependent stuff.
                      7:  */
                      8: 
                      9: #include "defs.h"
                     10: #include "machine.h"
                     11: #include "process.h"
                     12: #include "events.h"
                     13: #include "main.h"
                     14: #include "symbols.h"
                     15: #include "source.h"
                     16: #include "mappings.h"
                     17: #include "object.h"
                     18: #include "ops.h"
                     19: #include <signal.h>
                     20: 
                     21: #ifndef public
                     22: typedef unsigned int Address;
                     23: typedef unsigned char Byte;
                     24: typedef unsigned int Word;
                     25: 
                     26: #define NREG 16
                     27: 
                     28: #define ARGP 12
                     29: #define FRP 13
                     30: #define STKP 14
                     31: #define PROGCTR 15
                     32: 
                     33: #define BITSPERBYTE 8
                     34: #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
                     35: 
                     36: #define nargspassed(frame) argn(0, frame)
                     37: 
                     38: #include "source.h"
                     39: #include "symbols.h"
                     40: 
                     41: Address pc;
                     42: Address prtaddr;
                     43: 
                     44: #endif
                     45: 
                     46: private Address printop();
                     47: 
                     48: /*
                     49:  * Decode and print the instructions within the given address range.
                     50:  */
                     51: 
                     52: public printinst(lowaddr, highaddr)
                     53: Address lowaddr;
                     54: Address highaddr;
                     55: {
                     56:     register Address addr;
                     57: 
                     58:     for (addr = lowaddr; addr <= highaddr; ) {
                     59:        addr = printop(addr);
                     60:     }
                     61:     prtaddr = addr;
                     62: }
                     63: 
                     64: /*
                     65:  * Another approach:  print n instructions starting at the given address.
                     66:  */
                     67: 
                     68: public printninst(count, addr)
                     69: int count;
                     70: Address addr;
                     71: {
                     72:     register Integer i;
                     73:     register Address newaddr;
                     74: 
                     75:     if (count <= 0) {
                     76:        error("non-positive repetition count");
                     77:     } else {
                     78:        newaddr = addr;
                     79:        for (i = 0; i < count; i++) {
                     80:            newaddr = printop(newaddr);
                     81:        }
                     82:        prtaddr = newaddr;
                     83:     }
                     84: }
                     85: 
                     86: /*
                     87:  * Hacked version of adb's VAX instruction decoder.
                     88:  */
                     89: 
                     90: private Address printop(addr)
                     91: Address addr;
                     92: {
                     93:     Optab op;
                     94:     VaxOpcode ins;
                     95:     unsigned char mode;
                     96:     int argtype, amode, argno, argval;
                     97:     String reg;
                     98:     Boolean indexf;
                     99:     short offset;
                    100: 
                    101:     argval = 0;
                    102:     indexf = false;
                    103:     printf("%08x  ", addr);
                    104:     iread(&ins, addr, sizeof(ins));
                    105:     addr += 1;
                    106:     op = optab[ins];
                    107:     printf("%s", op.iname);
                    108:     for (argno = 0; argno < op.numargs; argno++) {
                    109:        if (indexf == true) {
                    110:            indexf = false;
                    111:        } else if (argno == 0) {
                    112:            printf("\t");
                    113:        } else {
                    114:            printf(",");
                    115:        }
                    116:        argtype = op.argtype[argno];
                    117:        if (is_branch_disp(argtype)) {
                    118:            mode = 0xAF + (typelen(argtype) << 5);
                    119:        } else {
                    120:            iread(&mode, addr, sizeof(mode));
                    121:            addr += 1;
                    122:        }
                    123:        reg = regname[regnm(mode)];
                    124:        amode = addrmode(mode);
                    125:        switch (amode) {
                    126:            case LITSHORT:
                    127:            case LITUPTO31:
                    128:            case LITUPTO47:
                    129:            case LITUPTO63:
                    130:                if (typelen(argtype) == TYPF || typelen(argtype) ==TYPD)
                    131:                    printf("$%s", fltimm[mode]);
                    132:                else
                    133:                    printf("$%x", mode);
                    134:                argval = mode;
                    135:                break;
                    136: 
                    137:            case INDEX:
                    138:                printf("[%s]", reg);
                    139:                indexf = true;
                    140:                argno--;
                    141:                break;
                    142: 
                    143:            case REG:
                    144:                printf("%s", reg);
                    145:                break;
                    146: 
                    147:            case REGDEF:
                    148:                printf("(%s)", reg);
                    149:                break;
                    150: 
                    151:            case AUTODEC:
                    152:                printf("-(%s)", reg);
                    153:                break;
                    154: 
                    155:            case AUTOINC:
                    156:                if (reg != regname[PROGCTR]) {
                    157:                    printf("(%s)+", reg);
                    158:                } else {
                    159:                    printf("$");
                    160:                    switch (typelen(argtype)) {
                    161:                        case TYPB:
                    162:                            argval = printdisp(addr, 1, reg, amode);
                    163:                            addr += 1;
                    164:                            break;
                    165: 
                    166:                        case TYPW:
                    167:                            argval = printdisp(addr, 2, reg, amode);
                    168:                            addr += 2;
                    169:                            break;
                    170: 
                    171:                        case TYPL:
                    172:                            argval = printdisp(addr, 4, reg, amode);
                    173:                            addr += 4;
                    174:                            break;
                    175: 
                    176:                        case TYPF:
                    177:                            iread(&argval, addr, sizeof(argval));
                    178:                            printf("%06x", argval);
                    179:                            addr += 4;
                    180:                            break;
                    181: 
                    182:                        case TYPQ:
                    183:                        case TYPD:
                    184:                            iread(&argval, addr, sizeof(argval));
                    185:                            printf("%06x", argval);
                    186:                            iread(&argval, addr+4, sizeof(argval));
                    187:                            printf("%06x", argval);
                    188:                            addr += 8;
                    189:                            break;
                    190:                    }
                    191:                }
                    192:                break;
                    193: 
                    194:            case AUTOINCDEF:
                    195:                if (reg == regname[PROGCTR]) {
                    196:                    printf("*$");
                    197:                    argval = printdisp(addr, 4, reg, amode);
                    198:                    addr += 4;
                    199:                } else {
                    200:                    printf("*(%s)+", reg);
                    201:                }
                    202:                break;
                    203: 
                    204:            case BYTEDISP:
                    205:                argval = printdisp(addr, 1, reg, amode);
                    206:                addr += 1;
                    207:                break;
                    208: 
                    209:            case BYTEDISPDEF:
                    210:                printf("*");
                    211:                argval = printdisp(addr, 1, reg, amode);
                    212:                addr += 1;
                    213:                break;
                    214: 
                    215:            case WORDDISP:
                    216:                argval = printdisp(addr, 2, reg, amode);
                    217:                addr += 2;
                    218:                break;
                    219: 
                    220:            case WORDDISPDEF:
                    221:                printf("*");
                    222:                argval = printdisp(addr, 2, reg, amode);
                    223:                addr += 2;
                    224:                break;
                    225: 
                    226:            case LONGDISP:
                    227:                argval = printdisp(addr, 4, reg, amode);
                    228:                addr += 4;
                    229:                break;
                    230: 
                    231:            case LONGDISPDEF:
                    232:                printf("*");
                    233:                argval = printdisp(addr, 4, reg, amode);
                    234:                addr += 4;
                    235:                break;
                    236:        }
                    237:     }
                    238:     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
                    239:        for (argno = 0; argno <= argval; argno++) {
                    240:            iread(&offset, addr, sizeof(offset));
                    241:            printf("\n\t\t%d", offset);
                    242:            addr += 2;
                    243:        }
                    244:     }
                    245:     printf("\n");
                    246:     return addr;
                    247: }
                    248: 
                    249: /*
                    250:  * Print the displacement of an instruction that uses displacement
                    251:  * addressing.
                    252:  */
                    253: 
                    254: private int printdisp(addr, nbytes, reg, mode)
                    255: Address addr;
                    256: int nbytes;
                    257: char *reg;
                    258: int mode;
                    259: {
                    260:     char byte;
                    261:     short hword;
                    262:     int argval;
                    263:     Symbol f;
                    264: 
                    265:     switch (nbytes) {
                    266:        case 1:
                    267:            iread(&byte, addr, sizeof(byte));
                    268:            argval = byte;
                    269:            break;
                    270: 
                    271:        case 2:
                    272:            iread(&hword, addr, sizeof(hword));
                    273:            argval = hword;
                    274:            break;
                    275: 
                    276:        case 4:
                    277:            iread(&argval, addr, sizeof(argval));
                    278:            break;
                    279:     }
                    280:     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
                    281:        argval += addr + nbytes;
                    282:     }
                    283:     if (reg == regname[PROGCTR]) {
                    284:        f = whatblock((Address) argval + 2);
                    285:        if (codeloc(f) == argval + 2) {
                    286:            printf("%s", symname(f));
                    287:        } else {
                    288:            printf("%x", argval);
                    289:        }
                    290:     } else {
                    291:        printf("%d(%s)", argval, reg);
                    292:     }
                    293:     return argval;
                    294: }
                    295: 
                    296: /*
                    297:  * Print the contents of the addresses within the given range
                    298:  * according to the given format.
                    299:  */
                    300: 
                    301: typedef struct {
                    302:     String name;
                    303:     String printfstring;
                    304:     int length;
                    305: } Format;
                    306: 
                    307: private Format fmt[] = {
                    308:     { "d", " %d", sizeof(short) },
                    309:     { "D", " %ld", sizeof(long) },
                    310:     { "o", " %o", sizeof(short) },
                    311:     { "O", " %lo", sizeof(long) },
                    312:     { "x", " %04x", sizeof(short) },
                    313:     { "X", " %08x", sizeof(long) },
                    314:     { "b", " \\%o", sizeof(char) },
                    315:     { "c", " '%c'", sizeof(char) },
                    316:     { "s", "%c", sizeof(char) },
                    317:     { "f", " %f", sizeof(float) },
                    318:     { "g", " %g", sizeof(double) },
                    319:     { nil, nil, 0 }
                    320: };
                    321: 
                    322: private Format *findformat(s)
                    323: String s;
                    324: {
                    325:     register Format *f;
                    326: 
                    327:     f = &fmt[0];
                    328:     while (f->name != nil and not streq(f->name, s)) {
                    329:        ++f;
                    330:     }
                    331:     if (f->name == nil) {
                    332:        error("bad print format \"%s\"", s);
                    333:     }
                    334:     return f;
                    335: }
                    336: 
                    337: public Address printdata(lowaddr, highaddr, format)
                    338: Address lowaddr;
                    339: Address highaddr;
                    340: String format;
                    341: {
                    342:     register int n;
                    343:     register Address addr;
                    344:     register Format *f;
                    345:     int value;
                    346: 
                    347:     if (lowaddr > highaddr) {
                    348:        error("first address larger than second");
                    349:     }
                    350:     f = findformat(format);
                    351:     n = 0;
                    352:     value = 0;
                    353:     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
                    354:        if (n == 0) {
                    355:            printf("%08x: ", addr);
                    356:        }
                    357:        dread(&value, addr, f->length);
                    358:        printf(f->printfstring, value);
                    359:        ++n;
                    360:        if (n >= (16 div f->length)) {
                    361:            putchar('\n');
                    362:            n = 0;
                    363:        }
                    364:     }
                    365:     if (n != 0) {
                    366:        putchar('\n');
                    367:     }
                    368:     prtaddr = addr;
                    369:     return addr;
                    370: }
                    371: 
                    372: /*
                    373:  * The other approach is to print n items starting with a given address.
                    374:  */
                    375: 
                    376: public printndata(count, startaddr, format)
                    377: int count;
                    378: Address startaddr;
                    379: String format;
                    380: {
                    381:     register int i, n;
                    382:     register Address addr;
                    383:     register Format *f;
                    384:     register Boolean isstring;
                    385:     char c;
                    386:     union {
                    387:        char charv;
                    388:        short shortv;
                    389:        int intv;
                    390:        float floatv;
                    391:        double doublev;
                    392:     } value;
                    393: 
                    394:     if (count <= 0) {
                    395:        error("non-positive repetition count");
                    396:     }
                    397:     f = findformat(format);
                    398:     isstring = (Boolean) streq(f->name, "s");
                    399:     n = 0;
                    400:     addr = startaddr;
                    401:     value.intv = 0;
                    402:     for (i = 0; i < count; i++) {
                    403:        if (n == 0) {
                    404:            printf("%08x: ", addr);
                    405:        }
                    406:        if (isstring) {
                    407:            putchar('"');
                    408:            dread(&c, addr, sizeof(char));
                    409:            while (c != '\0') {
                    410:                printchar(c);
                    411:                ++addr;
                    412:                dread(&c, addr, sizeof(char));
                    413:            }
                    414:            putchar('"');
                    415:            putchar('\n');
                    416:            n = 0;
                    417:            addr += sizeof(String);
                    418:        } else {
                    419:            dread(&value, addr, f->length);
                    420:            printf(f->printfstring, value);
                    421:            ++n;
                    422:            if (n >= (16 div f->length)) {
                    423:                putchar('\n');
                    424:                n = 0;
                    425:            }
                    426:            addr += f->length;
                    427:        }
                    428:     }
                    429:     if (n != 0) {
                    430:        putchar('\n');
                    431:     }
                    432:     prtaddr = addr;
                    433: }
                    434: 
                    435: /*
                    436:  * Print out a value according to the given format.
                    437:  */
                    438: 
                    439: public printvalue(v, format)
                    440: long v;
                    441: String format;
                    442: {
                    443:     Format *f;
                    444:     char *p, *q;
                    445: 
                    446:     f = findformat(format);
                    447:     if (streq(f->name, "s")) {
                    448:        putchar('"');
                    449:        p = (char *) &v;
                    450:        q = p + sizeof(v);
                    451:        while (p < q) {
                    452:            printchar(*p);
                    453:            ++p;
                    454:        }
                    455:        putchar('"');
                    456:     } else {
                    457:        printf(f->printfstring, v);
                    458:     }
                    459:     putchar('\n');
                    460: }
                    461: 
                    462: /*
                    463:  * Print out an execution time error.
                    464:  * Assumes the source position of the error has been calculated.
                    465:  *
                    466:  * Have to check if the -r option was specified; if so then
                    467:  * the object file information hasn't been read in yet.
                    468:  */
                    469: 
                    470: public printerror()
                    471: {
                    472:     extern Integer sys_nsig;
                    473:     extern String sys_siglist[];
                    474:     Integer err;
                    475: 
                    476:     if (isfinished(process)) {
                    477:        printf("\"%s\" exits with code %d\n", objname, exitcode(process));
                    478:        erecover();
                    479:     }
                    480:     if (runfirst) {
                    481:        fprintf(stderr, "Entering debugger ...");
                    482:        init();
                    483:        fprintf(stderr, " type 'help' for help\n");
                    484:     }
                    485:     err = errnum(process);
                    486:     if (err == SIGINT) {
                    487:        printf("\n\ninterrupt ");
                    488:        printloc();
                    489:     } else if (err == SIGTRAP) {
                    490:        printf("\nerror ");
                    491:        printloc();
                    492:     } else {
                    493:        if (err < 0 or err > sys_nsig) {
                    494:            printf("\nsignal %d ", err);
                    495:        } else {
                    496:            printf("\n%s ", sys_siglist[err]);
                    497:        }
                    498:        printloc();
                    499:     }
                    500:     putchar('\n');
                    501:     if (curline > 0) {
                    502:        printlines(curline, curline);
                    503:     } else {
                    504:        printinst(pc, pc);
                    505:     }
                    506:     erecover();
                    507: }
                    508: 
                    509: /*
                    510:  * Note the termination of the program.  We do this so as to avoid
                    511:  * having the process exit, which would make the values of variables
                    512:  * inaccessible.  We do want to flush all output buffers here,
                    513:  * otherwise it'll never get done.
                    514:  */
                    515: 
                    516: public endprogram()
                    517: {
                    518:     Integer exitcode;
                    519: 
                    520:     stepto(nextaddr(pc, true));
                    521:     printnews();
                    522:     exitcode = argn(1, nil);
                    523:     printf("\nexecution completed, exit code is %d\n", exitcode);
                    524:     getsrcpos();
                    525:     erecover();
                    526: }
                    527: 
                    528: /*
                    529:  * Single step the machine a source line (or instruction if "inst_tracing"
                    530:  * is true).  If "isnext" is true, skip over procedure calls.
                    531:  */
                    532: 
                    533: private Address getcall();
                    534: 
                    535: public dostep(isnext)
                    536: Boolean isnext;
                    537: {
                    538:     register Address addr;
                    539:     register Lineno line;
                    540:     String filename;
                    541: 
                    542:     addr = nextaddr(pc, isnext);
                    543:     if (not inst_tracing and nlhdr.nlines != 0) {
                    544:        line = linelookup(addr);
                    545:        while (line == 0) {
                    546:            addr = nextaddr(addr, isnext);
                    547:            line = linelookup(addr);
                    548:        }
                    549:        curline = line;
                    550:     } else {
                    551:        curline = 0;
                    552:     }
                    553:     stepto(addr);
                    554:     filename = srcfilename(addr);
                    555:     setsource(filename);
                    556: }
                    557: 
                    558: /*
                    559:  * Compute the next address that will be executed from the given one.
                    560:  * If "isnext" is true then consider a procedure call as straight line code.
                    561:  *
                    562:  * We must unfortunately do much of the same work that is necessary
                    563:  * to print instructions.  In addition we have to deal with branches.
                    564:  * Unconditional branches we just follow, for conditional branches
                    565:  * we continue execution to the current location and then single step
                    566:  * the machine.  We assume that the last argument in an instruction
                    567:  * that branches is the branch address (or relative offset).
                    568:  */
                    569: 
                    570: public Address nextaddr(startaddr, isnext)
                    571: Address startaddr;
                    572: Boolean isnext;
                    573: {
                    574:     register Address addr;
                    575:     Optab op;
                    576:     VaxOpcode ins;
                    577:     unsigned char mode;
                    578:     int argtype, amode, argno, argval;
                    579:     String r;
                    580:     Boolean indexf;
                    581:     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
                    582: 
                    583:     argval = 0;
                    584:     indexf = false;
                    585:     addr = startaddr;
                    586:     iread(&ins, addr, sizeof(ins));
                    587:     switch (ins) {
                    588:        case O_BRB:
                    589:        case O_BRW:
                    590:        case O_JMP:
                    591:            addrstatus = BRANCH;
                    592:            break;
                    593:            
                    594:        case O_BSBB:
                    595:        case O_BSBW:
                    596:        case O_JSB:
                    597:        case O_CALLG:
                    598:        case O_CALLS:
                    599:            if (isnext) {
                    600:                addrstatus = SEQUENTIAL;
                    601:            } else {
                    602:                addrstatus = KNOWN;
                    603:                stepto(addr);
                    604:                pstep(process);
                    605:                addr = reg(PROGCTR);
                    606:                pc = addr;
                    607:                curfunc = whatblock(pc);
                    608:                if (not isbperr()) {
                    609:                    printstatus();
                    610:                    /* NOTREACHED */
                    611:                }
                    612:                bpact();
                    613:                if (nosource(curfunc) and canskip(curfunc) and
                    614:                  nlhdr.nlines != 0) {
                    615:                    addrstatus = KNOWN;
                    616:                    addr = return_addr();
                    617:                    stepto(addr);
                    618:                    bpact();
                    619:                } else {
                    620:                    callnews(/* iscall = */ true);
                    621:                }
                    622:            }
                    623:            break;
                    624: 
                    625:        case O_RSB:
                    626:        case O_RET:
                    627:            addrstatus = KNOWN;
                    628:            callnews(/* iscall = */ false);
                    629:            addr = return_addr();
                    630:            stepto(addr);
                    631:            bpact();
                    632:            break;
                    633: 
                    634:        case O_BNEQ: case O_BEQL: case O_BGTR:
                    635:        case O_BLEQ: case O_BGEQ: case O_BLSS:
                    636:        case O_BGTRU: case O_BLEQU: case O_BVC:
                    637:        case O_BVS: case O_BCC: case O_BCS:
                    638:        case O_CASEB: case O_CASEW: case O_CASEL:
                    639:        case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
                    640:        case O_BBSC: case O_BBCC: case O_BBSSI:
                    641:        case O_BBCCI: case O_BLBS: case O_BLBC:
                    642:        case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
                    643:        case O_SOBGEQ: case O_SOBGTR:
                    644:            addrstatus = KNOWN;
                    645:            stepto(addr);
                    646:            pstep(process);
                    647:            addr = reg(PROGCTR);
                    648:            pc = addr;
                    649:            if (not isbperr()) {
                    650:                printstatus();
                    651:            }
                    652:            break;
                    653: 
                    654:        default:
                    655:            addrstatus = SEQUENTIAL;
                    656:            break;
                    657:     }
                    658:     if (addrstatus != KNOWN) {
                    659:        addr += 1;
                    660:        op = optab[ins];
                    661:        for (argno = 0; argno < op.numargs; argno++) {
                    662:            if (indexf == true) {
                    663:                indexf = false;
                    664:            }
                    665:            argtype = op.argtype[argno];
                    666:            if (is_branch_disp(argtype)) {
                    667:                mode = 0xAF + (typelen(argtype) << 5);
                    668:            } else {
                    669:                iread(&mode, addr, sizeof(mode));
                    670:                addr += 1;
                    671:            }
                    672:            r = regname[regnm(mode)];
                    673:            amode = addrmode(mode);
                    674:            switch (amode) {
                    675:                case LITSHORT:
                    676:                case LITUPTO31:
                    677:                case LITUPTO47:
                    678:                case LITUPTO63:
                    679:                    argval = mode;
                    680:                    break;
                    681: 
                    682:                case INDEX:
                    683:                    indexf = true;
                    684:                    --argno;
                    685:                    break;
                    686: 
                    687:                case REG:
                    688:                case REGDEF:
                    689:                case AUTODEC:
                    690:                    break;
                    691: 
                    692:                case AUTOINC:
                    693:                    if (r == regname[PROGCTR]) {
                    694:                        switch (typelen(argtype)) {
                    695:                            case TYPB:
                    696:                                argval = getdisp(addr, 1, r, amode);
                    697:                                addr += 1;
                    698:                                break;
                    699: 
                    700:                            case TYPW:
                    701:                                argval = getdisp(addr, 2, r, amode);
                    702:                                addr += 2;
                    703:                                break;
                    704: 
                    705:                            case TYPL:
                    706:                                argval = getdisp(addr, 4, r, amode);
                    707:                                addr += 4;
                    708:                                break;
                    709: 
                    710:                            case TYPF:
                    711:                                iread(&argval, addr, sizeof(argval));
                    712:                                addr += 4;
                    713:                                break;
                    714: 
                    715:                            case TYPQ:
                    716:                            case TYPD:
                    717:                                iread(&argval, addr+4, sizeof(argval));
                    718:                                addr += 8;
                    719:                                break;
                    720:                        }
                    721:                    }
                    722:                    break;
                    723: 
                    724:                case AUTOINCDEF:
                    725:                    if (r == regname[PROGCTR]) {
                    726:                        argval = getdisp(addr, 4, r, amode);
                    727:                        addr += 4;
                    728:                    }
                    729:                    break;
                    730: 
                    731:                case BYTEDISP:
                    732:                case BYTEDISPDEF:
                    733:                    argval = getdisp(addr, 1, r, amode);
                    734:                    addr += 1;
                    735:                    break;
                    736: 
                    737:                case WORDDISP:
                    738:                case WORDDISPDEF:
                    739:                    argval = getdisp(addr, 2, r, amode);
                    740:                    addr += 2;
                    741:                    break;
                    742: 
                    743:                case LONGDISP:
                    744:                case LONGDISPDEF:
                    745:                    argval = getdisp(addr, 4, r, amode);
                    746:                    addr += 4;
                    747:                    break;
                    748:            }
                    749:        }
                    750:        if (ins == O_CALLS or ins == O_CALLG) {
                    751:            argval += 2;
                    752:        }
                    753:        if (addrstatus == BRANCH) {
                    754:            addr = argval;
                    755:        }
                    756:     }
                    757:     return addr;
                    758: }
                    759: 
                    760: /*
                    761:  * Get the displacement of an instruction that uses displacement addressing.
                    762:  */
                    763: 
                    764: private int getdisp(addr, nbytes, reg, mode)
                    765: Address addr;
                    766: int nbytes;
                    767: String reg;
                    768: int mode;
                    769: {
                    770:     char byte;
                    771:     short hword;
                    772:     int argval;
                    773: 
                    774:     switch (nbytes) {
                    775:        case 1:
                    776:            iread(&byte, addr, sizeof(byte));
                    777:            argval = byte;
                    778:            break;
                    779: 
                    780:        case 2:
                    781:            iread(&hword, addr, sizeof(hword));
                    782:            argval = hword;
                    783:            break;
                    784: 
                    785:        case 4:
                    786:            iread(&argval, addr, sizeof(argval));
                    787:            break;
                    788:     }
                    789:     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
                    790:        argval += addr + nbytes;
                    791:     }
                    792:     return argval;
                    793: }
                    794: 
                    795: #define BP_OP       O_BPT       /* breakpoint trap */
                    796: #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
                    797: 
                    798: /*
                    799:  * Setting a breakpoint at a location consists of saving
                    800:  * the word at the location and poking a BP_OP there.
                    801:  *
                    802:  * We save the locations and words on a list for use in unsetting.
                    803:  */
                    804: 
                    805: typedef struct Savelist *Savelist;
                    806: 
                    807: struct Savelist {
                    808:     Address location;
                    809:     Byte save;
                    810:     Byte refcount;
                    811:     Savelist link;
                    812: };
                    813: 
                    814: private Savelist savelist;
                    815: 
                    816: /*
                    817:  * Set a breakpoint at the given address.  Only save the word there
                    818:  * if it's not already a breakpoint.
                    819:  */
                    820: 
                    821: public setbp(addr)
                    822: Address addr;
                    823: {
                    824:     Byte w;
                    825:     Byte save;
                    826:     register Savelist newsave, s;
                    827: 
                    828:     for (s = savelist; s != nil; s = s->link) {
                    829:        if (s->location == addr) {
                    830:            s->refcount++;
                    831:            return;
                    832:        }
                    833:     }
                    834:     iread(&save, addr, sizeof(save));
                    835:     newsave = new(Savelist);
                    836:     newsave->location = addr;
                    837:     newsave->save = save;
                    838:     newsave->refcount = 1;
                    839:     newsave->link = savelist;
                    840:     savelist = newsave;
                    841:     w = BP_OP;
                    842:     iwrite(&w, addr, sizeof(w));
                    843: }
                    844: 
                    845: /*
                    846:  * Unset a breakpoint; unfortunately we have to search the SAVELIST
                    847:  * to find the saved value.  The assumption is that the SAVELIST will
                    848:  * usually be quite small.
                    849:  */
                    850: 
                    851: public unsetbp(addr)
                    852: Address addr;
                    853: {
                    854:     register Savelist s, prev;
                    855: 
                    856:     prev = nil;
                    857:     for (s = savelist; s != nil; s = s->link) {
                    858:        if (s->location == addr) {
                    859:            iwrite(&s->save, addr, sizeof(s->save));
                    860:            s->refcount--;
                    861:            if (s->refcount == 0) {
                    862:                if (prev == nil) {
                    863:                    savelist = s->link;
                    864:                } else {
                    865:                    prev->link = s->link;
                    866:                }
                    867:                dispose(s);
                    868:            }
                    869:            return;
                    870:        }
                    871:        prev = s;
                    872:     }
                    873:     panic("unsetbp: couldn't find address %d", addr);
                    874: }
                    875: 
                    876: /*
                    877:  * Predicate to test if the reason the process stopped was because
                    878:  * of a breakpoint.
                    879:  */
                    880: 
                    881: public Boolean isbperr()
                    882: {
                    883:     return (Boolean) (not isfinished(process) and errnum(process) == SIGTRAP);
                    884: }
                    885: 
                    886: /*
                    887:  * Enter a procedure by creating and executing a call instruction.
                    888:  */
                    889: 
                    890: #define CALLSIZE 7     /* size of call instruction */
                    891: 
                    892: public beginproc(p, argc)
                    893: Symbol p;
                    894: Integer argc;
                    895: {
                    896:     char save[CALLSIZE];
                    897:     struct {
                    898:        VaxOpcode op;
                    899:        unsigned char numargs;
                    900:        unsigned char mode;
                    901:        char addr[sizeof(long)];        /* unaligned long */
                    902:     } call;
                    903:     long dest;
                    904: 
                    905:     pc = 2;
                    906:     iread(save, pc, sizeof(save));
                    907:     call.op = O_CALLS;
                    908:     call.numargs = argc;
                    909:     call.mode = 0xef;
                    910:     dest = codeloc(p) - 2 - (pc + 7);
                    911:     mov(&dest, call.addr, sizeof(call.addr));
                    912:     iwrite(&call, pc, sizeof(call));
                    913:     setreg(PROGCTR, pc);
                    914:     pstep(process);
                    915:     iwrite(save, pc, sizeof(save));
                    916:     pc = reg(PROGCTR);
                    917:     if (not isbperr()) {
                    918:        printstatus();
                    919:     }
                    920: }

unix.superglobalmegacorp.com

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