Annotation of 43BSDTahoe/ucb/dbx/runtime.vax.c, revision 1.1.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[] = "@(#)runtime.vax.c      5.3 (Berkeley) 1/12/88";
                      9: #endif not lint
                     10: 
                     11: static char rcsid[] = "$Header: runtime.vax.c,v 1.3 88/01/11 21:27:00 donn Exp $";
                     12: 
                     13: /*
                     14:  * Runtime organization dependent routines, mostly dealing with
                     15:  * activation records.
                     16:  */
                     17: 
                     18: #include "defs.h"
                     19: #include "runtime.h"
                     20: #include "process.h"
                     21: #include "machine.h"
                     22: #include "events.h"
                     23: #include "mappings.h"
                     24: #include "symbols.h"
                     25: #include "tree.h"
                     26: #include "eval.h"
                     27: #include "operators.h"
                     28: #include "object.h"
                     29: #include <sys/param.h>
                     30: #include <signal.h>
                     31: 
                     32: #ifndef public
                     33: typedef struct Frame *Frame;
                     34: 
                     35: #include "machine.h"
                     36: #endif
                     37: 
                     38: #define NSAVEREG 12
                     39: 
                     40: struct Frame {
                     41:     integer condition_handler;
                     42:     integer mask;
                     43:     Address save_ap;           /* argument pointer */
                     44:     Address save_fp;           /* frame pointer */
                     45:     Address save_pc;           /* program counter */
                     46:     Word save_reg[NSAVEREG];   /* not necessarily there */
                     47: };
                     48: 
                     49: private Frame curframe = nil;
                     50: private struct Frame curframerec;
                     51: private Boolean walkingstack = false;
                     52: 
                     53: #define frameeq(f1, f2) ((f1)->save_fp == (f2)->save_fp)
                     54: 
                     55: #define inSignalHandler(addr) \
                     56:     (((addr) < 0x80000000) and ((addr) > 0x80000000 - ctob(UPAGES)))
                     57: 
                     58: typedef struct {
                     59:     Node callnode;
                     60:     Node cmdnode;
                     61:     boolean isfunc;
                     62: } CallEnv;
                     63: 
                     64: private CallEnv endproc;
                     65: 
                     66: /*
                     67:  * Set a frame to the current activation record.
                     68:  */
                     69: 
                     70: private getcurframe(frp)
                     71: Frame frp;
                     72: {
                     73:     register int i;
                     74: 
                     75:     checkref(frp);
                     76:     frp->mask = reg(NREG);
                     77:     frp->save_ap = reg(ARGP);
                     78:     frp->save_fp = reg(FRP);
                     79:     frp->save_pc = reg(PROGCTR);
                     80:     for (i = 0; i < NSAVEREG; i++) {
                     81:        frp->save_reg[i] = reg(i);
                     82:     }
                     83: }
                     84: 
                     85: /*
                     86:  * Get the saved registers from one frame to another
                     87:  * given mask specifying which registers were actually saved.
                     88:  */
                     89: 
                     90: #define bis(b, n) ((b & (1 << (n))) != 0)
                     91: 
                     92: private getsaveregs (newfrp, frp, mask)
                     93: Frame newfrp, frp;
                     94: integer mask;
                     95: {
                     96:     integer i, j;
                     97: 
                     98:     j = 0;
                     99:     for (i = 0; i < NSAVEREG; i++) {
                    100:        if (bis(mask, i)) {
                    101:            newfrp->save_reg[i] = frp->save_reg[j];
                    102:            ++j;
                    103:        }
                    104:     }
                    105: }
                    106: 
                    107: /*
                    108:  * Return a pointer to the next activation record up the stack.
                    109:  * Return nil if there is none.
                    110:  * Writes over space pointed to by given argument.
                    111:  */
                    112: 
                    113: private Frame nextframe(frp)
                    114: Frame frp;
                    115: {
                    116:     Frame newfrp;
                    117:     struct Frame frame;
                    118:     integer mask;
                    119:     Address prev_frame, callpc;
                    120:     static integer ntramp = 0;
                    121: 
                    122:     newfrp = frp;
                    123:     prev_frame = frp->save_fp;
                    124: 
                    125: /*
                    126:  *  The check for interrupt generated frames is taken from adb with only
                    127:  *  partial understanding.  If you're in "sub" and on a sigxxx "sigsub"
                    128:  *  gets control, then the stack does NOT look like <main, sub, sigsub>.
                    129:  *
                    130:  *  As best I can make out it looks like:
                    131:  *
                    132:  *     <main, (machine check exception block + sub), sysframe, sigsub>.
                    133:  *
                    134:  *  When the signal occurs an exception block and a frame for the routine
                    135:  *  in which it occured are pushed on the user stack.  Then another frame
                    136:  *  is pushed corresponding to a call from the kernel to sigsub.
                    137:  *
                    138:  *  The addr in sub at which the exception occured is not in sub.save_pc
                    139:  *  but in the machine check exception block.  It is at the magic address
                    140:  *  fp + 84.
                    141:  *
                    142:  *  The current approach ignores the sys_frame (what adb reports as sigtramp)
                    143:  *  and takes the pc for sub from the exception block.  This allows the
                    144:  *  "where" command to report <main, sub, sigsub>, which seems reasonable.
                    145:  */
                    146: 
                    147: nextf:
                    148:     if (prev_frame + sizeof(struct Frame) <= USRSTACK) {
                    149:        dread(&frame, prev_frame, sizeof(struct Frame));
                    150:     } else if (USRSTACK - prev_frame > 2 * sizeof(Word)) {
                    151:        dread(&frame, prev_frame, USRSTACK - prev_frame);
                    152:     } else {
                    153:        frame.save_fp = nil;
                    154:     }
                    155:     if (ntramp == 1) {
                    156:        dread(&callpc, prev_frame + 92, sizeof(callpc));
                    157:     } else {
                    158:        callpc = frame.save_pc;
                    159:     }
                    160:     if (frame.save_fp == nil or frame.save_pc == (Address) -1) {
                    161:        newfrp = nil;
                    162:     } else {
                    163:        if (inSignalHandler(callpc)) {
                    164:            ntramp++;
                    165:            prev_frame = frame.save_fp;
                    166:            goto nextf;
                    167:        }
                    168:        frame.save_pc = callpc;
                    169:         ntramp = 0;
                    170:        newfrp->save_fp = frame.save_fp;
                    171:        newfrp->save_pc = frame.save_pc;
                    172:        mask = ((frame.mask >> 16) & 0x0fff);
                    173:        getsaveregs(newfrp, &frame, mask);
                    174:        newfrp->condition_handler = frame.condition_handler;
                    175:        newfrp->mask = mask;
                    176:        newfrp->save_ap = frame.save_ap;
                    177:     }
                    178:     return newfrp;
                    179: }
                    180: 
                    181: /*
                    182:  * Get the current frame information in the given Frame and store the
                    183:  * associated function in the given value-result parameter.
                    184:  */
                    185: 
                    186: private getcurfunc (frp, fp)
                    187: Frame frp;
                    188: Symbol *fp;
                    189: {
                    190:     getcurframe(frp);
                    191:     *fp = whatblock(frp->save_pc);
                    192: }
                    193: 
                    194: /*
                    195:  * Return the frame associated with the next function up the call stack, or
                    196:  * nil if there is none.  The function is returned in a value-result parameter.
                    197:  * For "inline" functions the statically outer function and same frame
                    198:  * are returned.
                    199:  */
                    200: 
                    201: public Frame nextfunc (frp, fp)
                    202: Frame frp;
                    203: Symbol *fp;
                    204: {
                    205:     Symbol t;
                    206:     Frame nfrp;
                    207: 
                    208:     t = *fp;
                    209:     checkref(t);
                    210:     if (isinline(t)) {
                    211:        t = container(t);
                    212:        nfrp = frp;
                    213:     } else {
                    214:        nfrp = nextframe(frp);
                    215:        if (nfrp == nil) {
                    216:            t = nil;
                    217:        } else {
                    218:            t = whatblock(nfrp->save_pc);
                    219:        }
                    220:     }
                    221:     *fp = t;
                    222:     return nfrp;
                    223: }
                    224: 
                    225: /*
                    226:  * Return the frame associated with the given function.
                    227:  * If the function is nil, return the most recently activated frame.
                    228:  *
                    229:  * Static allocation for the frame.
                    230:  */
                    231: 
                    232: public Frame findframe(f)
                    233: Symbol f;
                    234: {
                    235:     Frame frp;
                    236:     static struct Frame frame;
                    237:     Symbol p;
                    238:     Boolean done;
                    239: 
                    240:     frp = &frame;
                    241:     getcurframe(frp);
                    242:     if (f != nil) {
                    243:        if (f == curfunc and curframe != nil) {
                    244:            *frp = *curframe;
                    245:        } else {
                    246:            done = false;
                    247:            p = whatblock(frp->save_pc);
                    248:            do {
                    249:                if (p == f) {
                    250:                    done = true;
                    251:                } else if (p == program) {
                    252:                    done = true;
                    253:                    frp = nil;
                    254:                } else {
                    255:                    frp = nextfunc(frp, &p);
                    256:                    if (frp == nil) {
                    257:                        done = true;
                    258:                    }
                    259:                }
                    260:            } while (not done);
                    261:        }
                    262:     }
                    263:     return frp;
                    264: }
                    265: 
                    266: /*
                    267:  * Set the registers according to the given frame pointer.
                    268:  */
                    269: 
                    270: public getnewregs (addr)
                    271: Address addr;
                    272: {
                    273:     struct Frame frame;
                    274:     integer i, j, mask;
                    275: 
                    276:     dread(&frame, addr, sizeof(frame));
                    277:     setreg(FRP, frame.save_fp);
                    278:     setreg(PROGCTR, frame.save_pc);
                    279:     setreg(ARGP, frame.save_ap);
                    280:     mask = ((frame.mask >> 16) & 0x0fff);
                    281:     j = 0;
                    282:     for (i = 0; i < NSAVEREG; i++) {
                    283:        if (bis(mask, i)) {
                    284:        setreg(i, frame.save_reg[j]);
                    285:        ++j;
                    286:        }
                    287:     }
                    288:     pc = frame.save_pc;
                    289:     setcurfunc(whatblock(pc));
                    290: }
                    291: 
                    292: /*
                    293:  * Find the return address of the current procedure/function.
                    294:  */
                    295: 
                    296: public Address return_addr()
                    297: {
                    298:     Frame frp;
                    299:     Address addr;
                    300:     struct Frame frame;
                    301: 
                    302:     frp = &frame;
                    303:     getcurframe(frp);
                    304:     frp = nextframe(frp);
                    305:     if (frp == nil) {
                    306:        addr = 0;
                    307:     } else {
                    308:        addr = frp->save_pc;
                    309:     }
                    310:     return addr;
                    311: }
                    312: 
                    313: /*
                    314:  * Push the value associated with the current function.
                    315:  */
                    316: 
                    317: public pushretval(len, isindirect)
                    318: integer len;
                    319: boolean isindirect;
                    320: {
                    321:     Word r0;
                    322: 
                    323:     r0 = reg(0);
                    324:     if (isindirect) {
                    325:        rpush((Address) r0, len);
                    326:     } else {
                    327:        switch (len) {
                    328:            case sizeof(char):
                    329:                push(char, r0);
                    330:                break;
                    331: 
                    332:            case sizeof(short):
                    333:                push(short, r0);
                    334:                break;
                    335: 
                    336:            default:
                    337:                if (len == sizeof(Word)) {
                    338:                    push(Word, r0);
                    339:                } else if (len == 2*sizeof(Word)) {
                    340:                    push(Word, r0);
                    341:                    push(Word, reg(1));
                    342:                } else {
                    343:                    error("[internal error: bad size %d in pushretval]", len);
                    344:                }
                    345:                break;
                    346:        }
                    347:     }
                    348: }
                    349: 
                    350: /*
                    351:  * Return the base address for locals in the given frame.
                    352:  */
                    353: 
                    354: public Address locals_base(frp)
                    355: Frame frp;
                    356: {
                    357:     return (frp == nil) ? reg(FRP) : frp->save_fp;
                    358: }
                    359: 
                    360: /*
                    361:  * Return the base address for arguments in the given frame.
                    362:  */
                    363: 
                    364: public Address args_base(frp)
                    365: Frame frp;
                    366: {
                    367:     return (frp == nil) ? reg(ARGP) : frp->save_ap;
                    368: }
                    369: 
                    370: /*
                    371:  * Return saved register n from the given frame.
                    372:  */
                    373: 
                    374: public Word savereg(n, frp)
                    375: integer n;
                    376: Frame frp;
                    377: {
                    378:     Word w;
                    379: 
                    380:     if (frp == nil) {
                    381:        w = reg(n);
                    382:     } else {
                    383:        switch (n) {
                    384:            case ARGP:
                    385:                w = frp->save_ap;
                    386:                break;
                    387: 
                    388:            case FRP:
                    389:                w = frp->save_fp;
                    390:                break;
                    391: 
                    392:            case STKP:
                    393:                w = reg(STKP);
                    394:                break;
                    395: 
                    396:            case PROGCTR:
                    397:                w = frp->save_pc;
                    398:                break;
                    399: 
                    400:            default:
                    401:                assert(n >= 0 and n < NSAVEREG);
                    402:                w = frp->save_reg[n];
                    403:                break;
                    404:        }
                    405:     }
                    406:     return w;
                    407: }
                    408: 
                    409: /*
                    410:  * Return the nth argument to the current procedure.
                    411:  */
                    412: 
                    413: public Word argn(n, frp)
                    414: integer n;
                    415: Frame frp;
                    416: {
                    417:     Address argaddr;
                    418:     Word w;
                    419: 
                    420:     argaddr = args_base(frp) + (n * sizeof(Word));
                    421:     dread(&w, argaddr, sizeof(w));
                    422:     return w;
                    423: }
                    424: 
                    425: /*
                    426:  * Print a list of currently active blocks starting with most recent.
                    427:  */
                    428: 
                    429: public wherecmd()
                    430: {
                    431:     walkstack(false);
                    432: }
                    433: 
                    434: /*
                    435:  * Print the variables in the given frame or the current one if nil.
                    436:  */
                    437: 
                    438: public dump (func)
                    439: Symbol func;
                    440: {
                    441:     Symbol f;
                    442:     Frame frp;
                    443: 
                    444:     if (func == nil) {
                    445:        f = curfunc;
                    446:        if (curframe != nil) {
                    447:            frp = curframe;
                    448:        } else {
                    449:            frp = findframe(f);
                    450:        }
                    451:     } else {
                    452:        f = func;
                    453:        frp = findframe(f);
                    454:     }
                    455:     showaggrs = true;
                    456:     printcallinfo(f, frp);
                    457:     dumpvars(f, frp);
                    458: }
                    459: 
                    460: /*
                    461:  * Dump all values.
                    462:  */
                    463: 
                    464: public dumpall ()
                    465: {
                    466:     walkstack(true);
                    467: }
                    468: 
                    469: /*
                    470:  * Walk the stack of active procedures printing information
                    471:  * about each active procedure.
                    472:  */
                    473: 
                    474: private walkstack(dumpvariables)
                    475: Boolean dumpvariables;
                    476: {
                    477:     Frame frp;
                    478:     boolean save;
                    479:     Symbol f;
                    480:     struct Frame frame;
                    481: 
                    482:     if (notstarted(process) or isfinished(process)) {
                    483:        error("program is not active");
                    484:     } else {
                    485:        save = walkingstack;
                    486:        walkingstack = true;
                    487:        showaggrs = dumpvariables;
                    488:        frp = &frame;
                    489:        getcurfunc(frp, &f);
                    490:        for (;;) {
                    491:            printcallinfo(f, frp);
                    492:            if (dumpvariables) {
                    493:                dumpvars(f, frp);
                    494:                putchar('\n');
                    495:            }
                    496:            frp = nextfunc(frp, &f);
                    497:            if (frp == nil or f == program) {
                    498:                break;
                    499:            }
                    500:        }
                    501:        if (dumpvariables) {
                    502:            printf("in \"%s\":\n", symname(program));
                    503:            dumpvars(program, nil);
                    504:            putchar('\n');
                    505:        }
                    506:        walkingstack = save;
                    507:     }
                    508: }
                    509: 
                    510: /*
                    511:  * Print out the information about a call, i.e.,
                    512:  * routine name, parameter values, and source location.
                    513:  */
                    514: 
                    515: private printcallinfo (f, frp)
                    516: Symbol f;
                    517: Frame frp;
                    518: {
                    519:     Lineno line;
                    520:     Address savepc;
                    521: 
                    522:     savepc = frp->save_pc;
                    523:     if (frp->save_fp != reg(FRP)) {
                    524:        savepc -= 1;
                    525:     }
                    526:     printname(stdout, f);
                    527:     if (not isinline(f)) {
                    528:        printparams(f, frp);
                    529:     }
                    530:     line = srcline(savepc);
                    531:     if (line != 0) {
                    532:        printf(", line %d", line);
                    533:        printf(" in \"%s\"\n", srcfilename(savepc));
                    534:     } else {
                    535:        printf(" at 0x%x\n", savepc);
                    536:     }
                    537: }
                    538: 
                    539: /*
                    540:  * Set the current function to the given symbol.
                    541:  * We must adjust "curframe" so that subsequent operations are
                    542:  * not confused; for simplicity we simply clear it.
                    543:  */
                    544: 
                    545: public setcurfunc (f)
                    546: Symbol f;
                    547: {
                    548:     curfunc = f;
                    549:     curframe = nil;
                    550: }
                    551: 
                    552: /*
                    553:  * Return the frame for the current function.
                    554:  * The space for the frame is allocated statically.
                    555:  */
                    556: 
                    557: public Frame curfuncframe ()
                    558: {
                    559:     static struct Frame frame;
                    560:     Frame frp;
                    561: 
                    562:     if (curframe == nil) {
                    563:        frp = findframe(curfunc);
                    564:        curframe = &curframerec;
                    565:        *curframe = *frp;
                    566:     } else {
                    567:        frp = &frame;
                    568:        *frp = *curframe;
                    569:     }
                    570:     return frp;
                    571: }
                    572: 
                    573: /*
                    574:  * Set curfunc to be N up/down the stack from its current value.
                    575:  */
                    576: 
                    577: public up (n)
                    578: integer n;
                    579: {
                    580:     integer i;
                    581:     Symbol f;
                    582:     Frame frp;
                    583:     boolean done;
                    584: 
                    585:     if (not isactive(program)) {
                    586:        error("program is not active");
                    587:     } else if (curfunc == nil) {
                    588:        error("no current function");
                    589:     } else {
                    590:        i = 0;
                    591:        f = curfunc;
                    592:        frp = curfuncframe();
                    593:        done = false;
                    594:        do {
                    595:            if (frp == nil) {
                    596:                done = true;
                    597:                error("not that many levels");
                    598:            } else if (i >= n) {
                    599:                done = true;
                    600:                curfunc = f;
                    601:                curframe = &curframerec;
                    602:                *curframe = *frp;
                    603:                showaggrs = false;
                    604:                printcallinfo(curfunc, curframe);
                    605:            } else if (f == program) {
                    606:                done = true;
                    607:                error("not that many levels");
                    608:            } else {
                    609:                frp = nextfunc(frp, &f);
                    610:            }
                    611:            ++i;
                    612:        } while (not done);
                    613:     }
                    614: }
                    615: 
                    616: public down (n)
                    617: integer n;
                    618: {
                    619:     integer i, depth;
                    620:     Frame frp, curfrp;
                    621:     Symbol f;
                    622:     struct Frame frame;
                    623: 
                    624:     if (not isactive(program)) {
                    625:        error("program is not active");
                    626:     } else if (curfunc == nil) {
                    627:        error("no current function");
                    628:     } else {
                    629:        depth = 0;
                    630:        frp = &frame;
                    631:        getcurfunc(frp, &f);
                    632:        if (curframe == nil) {
                    633:            curfrp = findframe(curfunc);
                    634:            curframe = &curframerec;
                    635:            *curframe = *curfrp;
                    636:        }
                    637:        while ((f != curfunc or !frameeq(frp, curframe)) and f != nil) {
                    638:            frp = nextfunc(frp, &f);
                    639:            ++depth;
                    640:        }
                    641:        if (f == nil or n > depth) {
                    642:            error("not that many levels");
                    643:        } else {
                    644:            depth -= n;
                    645:            frp = &frame;
                    646:            getcurfunc(frp, &f);
                    647:            for (i = 0; i < depth; i++) {
                    648:                frp = nextfunc(frp, &f);
                    649:                assert(frp != nil);
                    650:            }
                    651:            curfunc = f;
                    652:            *curframe = *frp;
                    653:            showaggrs = false;
                    654:            printcallinfo(curfunc, curframe);
                    655:        }
                    656:     }
                    657: }
                    658: 
                    659: /*
                    660:  * Find the entry point of a procedure or function.
                    661:  *
                    662:  * On the VAX we add the size of the register mask (FUNCOFFSET) or
                    663:  * the size of the Modula-2 internal entry sequence, on other machines
                    664:  * (68000's) we add the entry sequence size (FUNCOFFSET) unless
                    665:  * we're right at the beginning of the program.
                    666:  */
                    667: 
                    668: public findbeginning (f)
                    669: Symbol f;
                    670: {
                    671:     if (isinternal(f)) {
                    672:        f->symvalue.funcv.beginaddr += 18;      /* VAX only */
                    673:     } else {
                    674:        f->symvalue.funcv.beginaddr += FUNCOFFSET;
                    675:     }
                    676: }
                    677: 
                    678: /*
                    679:  * Return the address corresponding to the first line in a function.
                    680:  */
                    681: 
                    682: public Address firstline(f)
                    683: Symbol f;
                    684: {
                    685:     Address addr;
                    686: 
                    687:     addr = codeloc(f);
                    688:     while (linelookup(addr) == 0 and addr < objsize) {
                    689:        ++addr;
                    690:     }
                    691:     if (addr == objsize) {
                    692:        addr = -1;
                    693:     }
                    694:     return addr;
                    695: }
                    696: 
                    697: /*
                    698:  * Catcher drops strike three ...
                    699:  */
                    700: 
                    701: public runtofirst()
                    702: {
                    703:     Address addr, endaddr;
                    704: 
                    705:     addr = pc;
                    706:     endaddr = objsize + CODESTART;
                    707:     while (linelookup(addr) == 0 and addr < endaddr) {
                    708:        ++addr;
                    709:     }
                    710:     if (addr < endaddr) {
                    711:        stepto(addr);
                    712:     }
                    713: }
                    714: 
                    715: /*
                    716:  * Return the address corresponding to the end of the program.
                    717:  *
                    718:  * We look for the entry to "exit".
                    719:  */
                    720: 
                    721: public Address lastaddr()
                    722: {
                    723:     Symbol s;
                    724: 
                    725:     s = lookup(identname("exit", true));
                    726:     if (s == nil) {
                    727:        panic("can't find exit");
                    728:     }
                    729:     return codeloc(s);
                    730: }
                    731: 
                    732: /*
                    733:  * Decide if the given function is currently active.
                    734:  *
                    735:  * We avoid calls to "findframe" during a stack trace for efficiency.
                    736:  * Presumably information evaluated while walking the stack is active.
                    737:  */
                    738: 
                    739: public Boolean isactive (f)
                    740: Symbol f;
                    741: {
                    742:     Boolean b;
                    743: 
                    744:     if (isfinished(process)) {
                    745:        b = false;
                    746:     } else {
                    747:        if (walkingstack or f == program or f == nil or
                    748:          (ismodule(f) and isactive(container(f)))) {
                    749:            b = true;
                    750:        } else {
                    751:            b = (Boolean) (findframe(f) != nil);
                    752:        }
                    753:     }
                    754:     return b;
                    755: }
                    756: 
                    757: /*
                    758:  * Evaluate a call to a procedure.
                    759:  */
                    760: 
                    761: public callproc(exprnode, isfunc)
                    762: Node exprnode;
                    763: boolean isfunc;
                    764: {
                    765:     Node procnode, arglist;
                    766:     Symbol proc;
                    767:     integer argc;
                    768: 
                    769:     procnode = exprnode->value.arg[0];
                    770:     arglist = exprnode->value.arg[1];
                    771:     if (procnode->op != O_SYM) {
                    772:        beginerrmsg();
                    773:        fprintf(stderr, "can't call \"");
                    774:        prtree(stderr, procnode);
                    775:        fprintf(stderr, "\"");
                    776:        enderrmsg();
                    777:     }
                    778:     assert(procnode->op == O_SYM);
                    779:     proc = procnode->value.sym;
                    780:     if (not isblock(proc)) {
                    781:        error("\"%s\" is not a procedure or function", symname(proc));
                    782:     }
                    783:     endproc.isfunc = isfunc;
                    784:     endproc.callnode = exprnode;
                    785:     endproc.cmdnode = topnode;
                    786:     pushenv();
                    787:     pc = codeloc(proc);
                    788:     argc = pushargs(proc, arglist);
                    789:     setreg(FRP, 1);    /* have to ensure it's non-zero for return_addr() */
                    790:     beginproc(proc, argc);
                    791:     event_once(
                    792:        build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym)),
                    793:        buildcmdlist(build(O_PROCRTN, proc))
                    794:     );
                    795:     isstopped = false;
                    796:     if (not bpact()) {
                    797:        isstopped = true;
                    798:        cont(0);
                    799:     }
                    800:     /*
                    801:      * bpact() won't return true, it will call printstatus() and go back
                    802:      * to command input if a breakpoint is found.
                    803:      */
                    804:     /* NOTREACHED */
                    805: }
                    806: 
                    807: /*
                    808:  * Push the arguments on the process' stack.  We do this by first
                    809:  * evaluating them on the "eval" stack, then copying into the process'
                    810:  * space.
                    811:  */
                    812: 
                    813: private integer pushargs(proc, arglist)
                    814: Symbol proc;
                    815: Node arglist;
                    816: {
                    817:     Stack *savesp;
                    818:     int argc, args_size;
                    819: 
                    820:     savesp = sp;
                    821:     if (varIsSet("$unsafecall")) {
                    822:        argc = unsafe_evalargs(proc, arglist);
                    823:     } else {
                    824:        argc = evalargs(proc, arglist);
                    825:     }
                    826:     args_size = sp - savesp;
                    827:     setreg(STKP, reg(STKP) - args_size);
                    828:     dwrite(savesp, reg(STKP), args_size);
                    829:     sp = savesp;
                    830:     return argc;
                    831: }
                    832: 
                    833: /*
                    834:  * Check to see if an expression is correct for a given parameter.
                    835:  * If the given parameter is false, don't worry about type inconsistencies.
                    836:  *
                    837:  * Return whether or not it is ok.
                    838:  */
                    839: 
                    840: private boolean chkparam (actual, formal, chk)
                    841: Node actual;
                    842: Symbol formal;
                    843: boolean chk;
                    844: {
                    845:     boolean b;
                    846: 
                    847:     b = true;
                    848:     if (chk) {
                    849:        if (formal == nil) {
                    850:            beginerrmsg();
                    851:            fprintf(stderr, "too many parameters");
                    852:            b = false;
                    853:        } else if (not compatible(formal->type, actual->nodetype)) {
                    854:            beginerrmsg();
                    855:            fprintf(stderr, "type mismatch for %s", symname(formal));
                    856:            b = false;
                    857:        }
                    858:     }
                    859:     if (b and formal != nil and
                    860:        isvarparam(formal) and not isopenarray(formal->type) and
                    861:        not (
                    862:            actual->op == O_RVAL or actual->nodetype == t_addr or
                    863:            (
                    864:                actual->op == O_TYPERENAME and
                    865:                (
                    866:                    actual->value.arg[0]->op == O_RVAL or
                    867:                    actual->value.arg[0]->nodetype == t_addr
                    868:                )
                    869:            )
                    870:        )
                    871:     ) {
                    872:        beginerrmsg();
                    873:        fprintf(stderr, "expected variable, found \"");
                    874:        prtree(stderr, actual);
                    875:        fprintf(stderr, "\"");
                    876:        b = false;
                    877:     }
                    878:     return b;
                    879: }
                    880: 
                    881: /*
                    882:  * Pass an expression to a particular parameter.
                    883:  *
                    884:  * Normally we pass either the address or value, but in some cases
                    885:  * (such as C strings) we want to copy the value onto the stack and
                    886:  * pass its address.
                    887:  *
                    888:  * Another special case raised by strings is the possibility that
                    889:  * the actual parameter will be larger than the formal, even with
                    890:  * appropriate type-checking.  This occurs because we assume during
                    891:  * evaluation that strings are null-terminated, whereas some languages,
                    892:  * notably Pascal, do not work under that assumption.
                    893:  */
                    894: 
                    895: private passparam (actual, formal)
                    896: Node actual;
                    897: Symbol formal;
                    898: {
                    899:     boolean b;
                    900:     Address addr;
                    901:     Stack *savesp;
                    902:     integer actsize, formsize;
                    903: 
                    904:     if (formal != nil and isvarparam(formal) and
                    905:        (not isopenarray(formal->type))
                    906:     ) {
                    907:        addr = lval(actual->value.arg[0]);
                    908:        push(Address, addr);
                    909:     } else if (passaddr(formal, actual->nodetype)) {
                    910:        savesp = sp;
                    911:        eval(actual);
                    912:        actsize = sp - savesp;
                    913:        setreg(STKP,
                    914:            reg(STKP) - ((actsize + sizeof(Word) - 1) & ~(sizeof(Word) - 1))
                    915:        );
                    916:        dwrite(savesp, reg(STKP), actsize);
                    917:        sp = savesp;
                    918:        push(Address, reg(STKP));
                    919:        if (formal != nil and isopenarray(formal->type)) {
                    920:            push(integer, actsize div size(formal->type->type));
                    921:        }
                    922:     } else if (formal != nil) {
                    923:        formsize = size(formal);
                    924:        savesp = sp;
                    925:        eval(actual);
                    926:        actsize = sp - savesp;
                    927:        if (actsize > formsize) {
                    928:            sp -= (actsize - formsize);
                    929:        }
                    930:     } else {
                    931:        eval(actual);
                    932:     }
                    933: }
                    934: 
                    935: /*
                    936:  * Evaluate an argument list left-to-right.
                    937:  */
                    938: 
                    939: private integer evalargs(proc, arglist)
                    940: Symbol proc;
                    941: Node arglist;
                    942: {
                    943:     Node p, actual;
                    944:     Symbol formal;
                    945:     Stack *savesp;
                    946:     integer count;
                    947:     boolean chk;
                    948: 
                    949:     savesp = sp;
                    950:     count = 0;
                    951:     formal = proc->chain;
                    952:     chk = (boolean) (not nosource(proc));
                    953:     for (p = arglist; p != nil; p = p->value.arg[1]) {
                    954:        assert(p->op == O_COMMA);
                    955:        actual = p->value.arg[0];
                    956:        if (not chkparam(actual, formal, chk)) {
                    957:            fprintf(stderr, " in call to %s", symname(proc));
                    958:            sp = savesp;
                    959:            enderrmsg();
                    960:        }
                    961:        passparam(actual, formal);
                    962:        if (formal != nil) {
                    963:            formal = formal->chain;
                    964:        }
                    965:        ++count;
                    966:     }
                    967:     if (chk) {
                    968:        if (formal != nil) {
                    969:            sp = savesp;
                    970:            error("not enough parameters to %s", symname(proc));
                    971:        }
                    972:     }
                    973:     return count;
                    974: }
                    975: 
                    976: /*
                    977:  * Evaluate an argument list without any type checking.
                    978:  * This is only useful for procedures with a varying number of
                    979:  * arguments that are compiled -g.
                    980:  */
                    981: 
                    982: private integer unsafe_evalargs (proc, arglist)
                    983: Symbol proc;
                    984: Node arglist;
                    985: {
                    986:     Node p;
                    987:     integer count;
                    988: 
                    989:     count = 0;
                    990:     for (p = arglist; p != nil; p = p->value.arg[1]) {
                    991:        assert(p->op == O_COMMA);
                    992:        eval(p->value.arg[0]);
                    993:        ++count;
                    994:     }
                    995:     return count;
                    996: }
                    997: 
                    998: public procreturn(f)
                    999: Symbol f;
                   1000: {
                   1001:     integer retvalsize;
                   1002:     Node tmp;
                   1003:     char *copy;
                   1004: 
                   1005:     flushoutput();
                   1006:     popenv();
                   1007:     if (endproc.isfunc) {
                   1008:        retvalsize = size(f->type);
                   1009:        if (retvalsize > sizeof(long)) {
                   1010:            pushretval(retvalsize, true);
                   1011:            copy = newarr(char, retvalsize);
                   1012:            popn(retvalsize, copy);
                   1013:            tmp = build(O_SCON, copy);
                   1014:        } else {
                   1015:            tmp = build(O_LCON, (long) (reg(0)));
                   1016:        }
                   1017:        tmp->nodetype = f->type;
                   1018:        tfree(endproc.callnode);
                   1019:        *(endproc.callnode) = *(tmp);
                   1020:        dispose(tmp);
                   1021:        eval(endproc.cmdnode);
                   1022:     } else {
                   1023:        putchar('\n');
                   1024:        printname(stdout, f);
                   1025:        printf(" returns successfully\n");
                   1026:     }
                   1027:     erecover();
                   1028: }
                   1029: 
                   1030: /*
                   1031:  * Push the current environment.
                   1032:  */
                   1033: 
                   1034: private pushenv()
                   1035: {
                   1036:     push(Address, pc);
                   1037:     push(Lineno, curline);
                   1038:     push(String, cursource);
                   1039:     push(Boolean, isstopped);
                   1040:     push(Symbol, curfunc);
                   1041:     push(Frame, curframe);
                   1042:     push(struct Frame, curframerec);
                   1043:     push(CallEnv, endproc);
                   1044:     push(Word, reg(PROGCTR));
                   1045:     push(Word, reg(STKP));
                   1046:     push(Word, reg(FRP));
                   1047: }
                   1048: 
                   1049: /*
                   1050:  * Pop back to the real world.
                   1051:  */
                   1052: 
                   1053: public popenv()
                   1054: {
                   1055:     String filename;
                   1056: 
                   1057:     setreg(FRP, pop(Word));
                   1058:     setreg(STKP, pop(Word));
                   1059:     setreg(PROGCTR, pop(Word));
                   1060:     endproc = pop(CallEnv);
                   1061:     curframerec = pop(struct Frame);
                   1062:     curframe = pop(Frame);
                   1063:     curfunc = pop(Symbol);
                   1064:     isstopped = pop(Boolean);
                   1065:     filename = pop(String);
                   1066:     curline = pop(Lineno);
                   1067:     pc = pop(Address);
                   1068:     setsource(filename);
                   1069: }
                   1070: 
                   1071: /*
                   1072:  * Flush the debuggee's standard output.
                   1073:  *
                   1074:  * This is VERY dependent on the use of stdio.
                   1075:  */
                   1076: 
                   1077: public flushoutput()
                   1078: {
                   1079:     Symbol p, iob;
                   1080:     Stack *savesp;
                   1081: 
                   1082:     p = lookup(identname("fflush", true));
                   1083:     while (p != nil and not isblock(p)) {
                   1084:        p = p->next_sym;
                   1085:     }
                   1086:     if (p != nil) {
                   1087:        iob = lookup(identname("_iob", true));
                   1088:        if (iob != nil) {
                   1089:            pushenv();
                   1090:            pc = codeloc(p) - FUNCOFFSET;
                   1091:            savesp = sp;
                   1092:            push(long, address(iob, nil) + sizeof(*stdout));
                   1093:            setreg(STKP, reg(STKP) - sizeof(long));
                   1094:            dwrite(savesp, reg(STKP), sizeof(long));
                   1095:            sp = savesp;
                   1096:            beginproc(p, 1);
                   1097:            stepto(return_addr());
                   1098:            popenv();
                   1099:        }
                   1100:     }
                   1101: }

unix.superglobalmegacorp.com

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