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

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

unix.superglobalmegacorp.com

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