Annotation of 43BSDReno/pgrm/dbx/runtime.vax.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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