Annotation of 43BSD/ucb/dbx/machine.c, revision 1.1

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

unix.superglobalmegacorp.com

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