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

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

unix.superglobalmegacorp.com

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