Annotation of 43BSDTahoe/ucb/dbx/runtime.tahoe.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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