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

1.1       root        1: /*
                      2:  * Copyright (c) 1983 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)runtime.sun.c      5.2 (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.