Annotation of 43BSDReno/pgrm/dbx/runtime.tahoe.c, revision 1.1

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

unix.superglobalmegacorp.com

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