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

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

unix.superglobalmegacorp.com

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