Annotation of 43BSD/ucb/dbx/events.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1983 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)events.c   5.1 (Berkeley) 5/31/85";
        !             9: #endif not lint
        !            10: 
        !            11: static char rcsid[] = "$Header: events.c,v 1.5 84/12/26 10:39:26 linton Exp $";
        !            12: 
        !            13: /*
        !            14:  * Event/breakpoint managment.
        !            15:  */
        !            16: 
        !            17: #include "defs.h"
        !            18: #include "events.h"
        !            19: #include "main.h"
        !            20: #include "symbols.h"
        !            21: #include "tree.h"
        !            22: #include "eval.h"
        !            23: #include "source.h"
        !            24: #include "mappings.h"
        !            25: #include "runtime.h"
        !            26: #include "process.h"
        !            27: #include "machine.h"
        !            28: #include "lists.h"
        !            29: 
        !            30: #ifndef public
        !            31: typedef struct Event *Event;
        !            32: typedef struct Breakpoint *Breakpoint;
        !            33: 
        !            34: boolean inst_tracing;
        !            35: boolean single_stepping;
        !            36: boolean isstopped;
        !            37: 
        !            38: #include "symbols.h"
        !            39: 
        !            40: Symbol linesym;
        !            41: Symbol procsym;
        !            42: Symbol pcsym;
        !            43: Symbol retaddrsym;
        !            44: 
        !            45: #define addevent(cond, cmdlist) event_alloc(false, cond, cmdlist)
        !            46: #define event_once(cond, cmdlist) event_alloc(true, cond, cmdlist)
        !            47: 
        !            48: #endif
        !            49: 
        !            50: struct Event {
        !            51:     unsigned int id;
        !            52:     boolean temporary;
        !            53:     Node condition;
        !            54:     Cmdlist actions;
        !            55: };
        !            56: 
        !            57: struct Breakpoint {
        !            58:     Event event;
        !            59:     Address bpaddr;    
        !            60:     Lineno bpline;
        !            61:     Cmdlist actions;
        !            62:     boolean temporary;
        !            63: };
        !            64: 
        !            65: typedef List Eventlist;
        !            66: typedef List Bplist;
        !            67: 
        !            68: #define eventlist_append(event, el) list_append(list_item(event), nil, el)
        !            69: #define bplist_append(bp, bl) list_append(list_item(bp), nil, bl)
        !            70: 
        !            71: private Eventlist eventlist;           /* list of active events */
        !            72: private Bplist bplist;                 /* list of active breakpoints */
        !            73: private Event curevent;                        /* most recently created event */
        !            74: private integer eventid;               /* id number of current event */
        !            75: private integer trid;                  /* id number of current trace */
        !            76: 
        !            77: typedef struct Trcmd {
        !            78:     Integer trid;
        !            79:     Event event;
        !            80:     Cmdlist cmdlist;
        !            81: } *Trcmd;
        !            82: 
        !            83: private List eachline;         /* commands to execute after each line */
        !            84: private List eachinst;         /* commands to execute after each instruction */
        !            85: 
        !            86: private Breakpoint bp_alloc();
        !            87: 
        !            88: /*
        !            89:  * Initialize breakpoint information.
        !            90:  */
        !            91: 
        !            92: private Symbol builtinsym(str, class, type)
        !            93: String str;
        !            94: Symclass class;
        !            95: Symbol type;
        !            96: {
        !            97:     Symbol s;
        !            98: 
        !            99:     s = insert(identname(str, true));
        !           100:     s->language = findlanguage(".s");
        !           101:     s->class = class;
        !           102:     s->type = type;
        !           103:     return s;
        !           104: }
        !           105: 
        !           106: public bpinit()
        !           107: {
        !           108:     linesym = builtinsym("$line", VAR, t_int);
        !           109:     procsym = builtinsym("$proc", PROC, nil);
        !           110:     pcsym = lookup(identname("$pc", true));
        !           111:     if (pcsym == nil) {
        !           112:        panic("can't find $pc");
        !           113:     }
        !           114:     retaddrsym = builtinsym("$retaddr", VAR, t_int);
        !           115:     eventlist = list_alloc();
        !           116:     bplist = list_alloc();
        !           117:     eachline = list_alloc();
        !           118:     eachinst = list_alloc();
        !           119: }
        !           120: 
        !           121: /*
        !           122:  * Trap an event and do the associated commands when it occurs.
        !           123:  */
        !           124: 
        !           125: public Event event_alloc(istmp, econd, cmdlist)
        !           126: boolean istmp;
        !           127: Node econd;
        !           128: Cmdlist cmdlist;
        !           129: {
        !           130:     register Event e;
        !           131: 
        !           132:     e = new(Event);
        !           133:     ++eventid;
        !           134:     e->id = eventid;
        !           135:     e->temporary = istmp;
        !           136:     e->condition = econd;
        !           137:     e->actions = cmdlist;
        !           138:     eventlist_append(e, eventlist);
        !           139:     curevent = e;
        !           140:     translate(e);
        !           141:     return e;
        !           142: }
        !           143: 
        !           144: /*
        !           145:  * Delete the event with the given id.
        !           146:  * Returns whether it's successful or not.
        !           147:  */
        !           148: 
        !           149: public boolean delevent (id)
        !           150: unsigned int id;
        !           151: {
        !           152:     Event e;
        !           153:     Breakpoint bp;
        !           154:     Trcmd t;
        !           155:     boolean found;
        !           156: 
        !           157:     found = false;
        !           158:     foreach (Event, e, eventlist)
        !           159:        if (e->id == id) {
        !           160:            found = true;
        !           161:            foreach (Breakpoint, bp, bplist)
        !           162:                if (bp->event == e) {
        !           163:                    if (tracebpts) {
        !           164:                        printf("deleting breakpoint at 0x%x\n", bp->bpaddr);
        !           165:                        fflush(stdout);
        !           166:                    }
        !           167:                    list_delete(list_curitem(bplist), bplist);
        !           168:                }
        !           169:            endfor
        !           170:            list_delete(list_curitem(eventlist), eventlist);
        !           171:            break;
        !           172:        }
        !           173:     endfor
        !           174:     foreach (Trcmd, t, eachline)
        !           175:        if (t->event->id == id) {
        !           176:            found = true;
        !           177:            printrmtr(t);
        !           178:            list_delete(list_curitem(eachline), eachline);
        !           179:        }
        !           180:     endfor
        !           181:     foreach (Trcmd, t, eachinst)
        !           182:        if (t->event->id == id) {
        !           183:            found = true;
        !           184:            printrmtr(t);
        !           185:            list_delete(list_curitem(eachinst), eachinst);
        !           186:        }
        !           187:     endfor
        !           188:     if (list_size(eachinst) == 0) {
        !           189:        inst_tracing = false;
        !           190:        if (list_size(eachline) == 0) {
        !           191:            single_stepping = false;
        !           192:        }
        !           193:     }
        !           194:     return found;
        !           195: }
        !           196: 
        !           197: /*
        !           198:  * Translate an event into the appropriate breakpoints and actions.
        !           199:  * While we're at it, turn on the breakpoints if the condition is true.
        !           200:  */
        !           201: 
        !           202: private translate(e)
        !           203: Event e;
        !           204: {
        !           205:     Breakpoint bp;
        !           206:     Symbol s;
        !           207:     Node place;
        !           208:     Lineno line;
        !           209:     Address addr;
        !           210: 
        !           211:     checkref(e->condition);
        !           212:     switch (e->condition->op) {
        !           213:        case O_EQ:
        !           214:            if (e->condition->value.arg[0]->op == O_SYM) {
        !           215:                s = e->condition->value.arg[0]->value.sym;
        !           216:                place = e->condition->value.arg[1];
        !           217:                if (s == linesym) {
        !           218:                    if (place->op == O_QLINE) {
        !           219:                        line = place->value.arg[1]->value.lcon;
        !           220:                        addr = objaddr(line, place->value.arg[0]->value.scon);
        !           221:                    } else {
        !           222:                        eval(place);
        !           223:                        line = pop(long);
        !           224:                        addr = objaddr(line, cursource);
        !           225:                    }
        !           226:                    if (addr == NOADDR) {
        !           227:                        if (not delevent(e->id)) {
        !           228:                            printf("!! dbx.translate: can't undo event %d?\n",
        !           229:                                e->id);
        !           230:                        }
        !           231:                        beginerrmsg();
        !           232:                        fprintf(stderr, "no executable code at line ");
        !           233:                        prtree(stderr, place);
        !           234:                        enderrmsg();
        !           235:                    }
        !           236:                    bp = bp_alloc(e, addr, line, e->actions);
        !           237:                } else if (s == procsym) {
        !           238:                    eval(place);
        !           239:                    s = pop(Symbol);
        !           240:                    bp = bp_alloc(e, codeloc(s), 0, e->actions);
        !           241:                    if (isactive(s) and pc != codeloc(program)) {
        !           242:                        evalcmdlist(e->actions);
        !           243:                    }
        !           244:                } else if (s == pcsym) {
        !           245:                    eval(place);
        !           246:                    bp = bp_alloc(e, pop(Address), 0, e->actions);
        !           247:                } else {
        !           248:                    condbp(e);
        !           249:                }
        !           250:            } else {
        !           251:                condbp(e);
        !           252:            }
        !           253:            break;
        !           254: 
        !           255:        /*
        !           256:         * These should be handled specially.
        !           257:         * But for now I'm ignoring the problem.
        !           258:         */
        !           259:        case O_AND:
        !           260:        case O_OR:
        !           261:        default:
        !           262:            condbp(e);
        !           263:            break;
        !           264:     }
        !           265: }
        !           266: 
        !           267: /*
        !           268:  * Create a breakpoint for a condition that cannot be pinpointed
        !           269:  * to happening at a particular address, but one for which we
        !           270:  * must single step and check the condition after each statement.
        !           271:  */
        !           272: 
        !           273: private condbp(e)
        !           274: Event e;
        !           275: {
        !           276:     Symbol p;
        !           277:     Breakpoint bp;
        !           278:     Cmdlist actions;
        !           279: 
        !           280:     p = tcontainer(e->condition);
        !           281:     if (p == nil) {
        !           282:        p = program;
        !           283:     }
        !           284:     actions = buildcmdlist(build(O_IF, e->condition, e->actions));
        !           285:     actions = buildcmdlist(build(O_TRACEON, false, actions));
        !           286:     bp = bp_alloc(e, codeloc(p), 0, actions);
        !           287: }
        !           288: 
        !           289: /*
        !           290:  * Determine the deepest nested subprogram that still contains
        !           291:  * all elements in the given expression.
        !           292:  */
        !           293: 
        !           294: public Symbol tcontainer(exp)
        !           295: Node exp;
        !           296: {
        !           297:     Integer i;
        !           298:     Symbol s, t, u, v;
        !           299: 
        !           300:     checkref(exp);
        !           301:     s = nil;
        !           302:     if (exp->op == O_SYM) {
        !           303:        s = container(exp->value.sym);
        !           304:     } else if (not isleaf(exp->op)) {
        !           305:        for (i = 0; i < nargs(exp->op); i++) {
        !           306:            t = tcontainer(exp->value.arg[i]);
        !           307:            if (t != nil) {
        !           308:                if (s == nil) {
        !           309:                    s = t;
        !           310:                } else {
        !           311:                    u = s;
        !           312:                    v = t;
        !           313:                    while (u != v and u != nil) {
        !           314:                        u = container(u);
        !           315:                        v = container(v);
        !           316:                    }
        !           317:                    if (u == nil) {
        !           318:                        panic("bad ancestry for \"%s\"", symname(s));
        !           319:                    } else {
        !           320:                        s = u;
        !           321:                    }
        !           322:                }
        !           323:            }
        !           324:        }
        !           325:     }
        !           326:     return s;
        !           327: }
        !           328: 
        !           329: /*
        !           330:  * Determine if the given function can be executed at full speed.
        !           331:  * This can only be done if there are no breakpoints within the function.
        !           332:  */
        !           333: 
        !           334: public boolean canskip(f)
        !           335: Symbol f;
        !           336: {
        !           337:     Breakpoint p;
        !           338:     boolean ok;
        !           339: 
        !           340:     ok = true;
        !           341:     foreach (Breakpoint, p, bplist)
        !           342:        if (whatblock(p->bpaddr) == f) {
        !           343:            ok = false;
        !           344:            break;
        !           345:        }
        !           346:     endfor
        !           347:     return ok;
        !           348: }
        !           349: 
        !           350: /*
        !           351:  * Print out what's currently being traced by looking at
        !           352:  * the currently active events.
        !           353:  *
        !           354:  * Some convolution here to translate internal representation
        !           355:  * of events back into something more palatable.
        !           356:  */
        !           357: 
        !           358: public status()
        !           359: {
        !           360:     Event e;
        !           361: 
        !           362:     foreach (Event, e, eventlist)
        !           363:        if (not e->temporary) {
        !           364:            printevent(e);
        !           365:        }
        !           366:     endfor
        !           367: }
        !           368: 
        !           369: public printevent(e)
        !           370: Event e;
        !           371: {
        !           372:     Command cmd;
        !           373: 
        !           374:     if (not isredirected()) {
        !           375:        printeventid(e->id);
        !           376:     }
        !           377:     cmd = list_element(Command, list_head(e->actions));
        !           378:     if (cmd->op == O_PRINTCALL) {
        !           379:        printf("trace ");
        !           380:        printname(stdout, cmd->value.sym);
        !           381:     } else {
        !           382:        if (list_size(e->actions) > 1) {
        !           383:            printf("{ ");
        !           384:        }
        !           385:        foreach (Command, cmd, e->actions)
        !           386:            printcmd(stdout, cmd);
        !           387:            if (not list_islast()) {
        !           388:                printf("; ");
        !           389:            }
        !           390:        endfor
        !           391:        if (list_size(e->actions) > 1) {
        !           392:            printf(" }");
        !           393:        }
        !           394:        printcond(e->condition);
        !           395:     }
        !           396:     printf("\n");
        !           397: }
        !           398: 
        !           399: private printeventid (id)
        !           400: integer id;
        !           401: {
        !           402:     printf("[%d] ", id);
        !           403: }
        !           404: 
        !           405: /*
        !           406:  * Print out a condition.
        !           407:  */
        !           408: 
        !           409: private printcond(cond)
        !           410: Node cond;
        !           411: {
        !           412:     Symbol s;
        !           413:     Node place;
        !           414: 
        !           415:     if (cond->op == O_EQ and cond->value.arg[0]->op == O_SYM) {
        !           416:        s = cond->value.arg[0]->value.sym;
        !           417:        place = cond->value.arg[1];
        !           418:        if (s == procsym) {
        !           419:            if (place->value.sym != program) {
        !           420:                printf(" in ");
        !           421:                printname(stdout, place->value.sym);
        !           422:            }
        !           423:        } else if (s == linesym) {
        !           424:            printf(" at ");
        !           425:            prtree(stdout, place);
        !           426:        } else if (s == pcsym or s == retaddrsym) {
        !           427:            printf("i at ");
        !           428:            prtree(stdout, place);
        !           429:        } else {
        !           430:            printf(" when ");
        !           431:            prtree(stdout, cond);
        !           432:        }
        !           433:     } else {
        !           434:        printf(" when ");
        !           435:        prtree(stdout, cond);
        !           436:     }
        !           437: }
        !           438: 
        !           439: /*
        !           440:  * Add a breakpoint to the list and return it.
        !           441:  */
        !           442: 
        !           443: private Breakpoint bp_alloc(e, addr, line, actions)
        !           444: Event e;
        !           445: Address addr;
        !           446: Lineno line;
        !           447: Cmdlist actions;
        !           448: {
        !           449:     register Breakpoint p;
        !           450: 
        !           451:     p = new(Breakpoint);
        !           452:     p->event = e;
        !           453:     p->bpaddr = addr;
        !           454:     p->bpline = line;
        !           455:     p->actions = actions;
        !           456:     p->temporary = false;
        !           457:     if (tracebpts) {
        !           458:        if (e == nil) {
        !           459:            printf("new bp at 0x%x for event ??\n", addr, e->id);
        !           460:        } else {
        !           461:            printf("new bp at 0x%x for event %d\n", addr, e->id);
        !           462:        }
        !           463:        fflush(stdout);
        !           464:     }
        !           465:     bplist_append(p, bplist);
        !           466:     return p;
        !           467: }
        !           468: 
        !           469: /*
        !           470:  * Free all storage in the event and breakpoint tables.
        !           471:  */
        !           472: 
        !           473: public bpfree()
        !           474: {
        !           475:     register Event e;
        !           476: 
        !           477:     fixbps();
        !           478:     foreach (Event, e, eventlist)
        !           479:        if (not delevent(e->id)) {
        !           480:            printf("!! dbx.bpfree: can't delete event %d\n", e->id);
        !           481:        }
        !           482:        list_delete(list_curitem(eventlist), eventlist);
        !           483:     endfor
        !           484: }
        !           485: 
        !           486: /*
        !           487:  * Determine if the program stopped at a known breakpoint
        !           488:  * and if so do the associated commands.
        !           489:  */
        !           490: 
        !           491: public boolean bpact()
        !           492: {
        !           493:     register Breakpoint p;
        !           494:     boolean found;
        !           495:     integer eventId;
        !           496: 
        !           497:     found = false;
        !           498:     foreach (Breakpoint, p, bplist)
        !           499:        if (p->bpaddr == pc) {
        !           500:            if (tracebpts) {
        !           501:                printf("breakpoint for event %d found at location 0x%x\n",
        !           502:                    p->event->id, pc);
        !           503:            }
        !           504:            found = true;
        !           505:            if (p->event->temporary) {
        !           506:                if (not delevent(p->event->id)) {
        !           507:                    printf("!! dbx.bpact: can't find event %d\n",
        !           508:                        p->event->id);
        !           509:                }
        !           510:            }
        !           511:            evalcmdlist(p->actions);
        !           512:            if (isstopped) {
        !           513:                eventId = p->event->id;
        !           514:            }
        !           515:            if (p->temporary) {
        !           516:                list_delete(list_curitem(bplist), bplist);
        !           517:            }
        !           518:        }
        !           519:     endfor
        !           520:     if (isstopped) {
        !           521:        if (found) {
        !           522:            printeventid(eventId);
        !           523:        }
        !           524:        printstatus();
        !           525:     }
        !           526:     fflush(stdout);
        !           527:     return found;
        !           528: }
        !           529: 
        !           530: /*
        !           531:  * Begin single stepping and executing the given commands after each step.
        !           532:  * If the first argument is true step by instructions, otherwise
        !           533:  * step by source lines.
        !           534:  *
        !           535:  * We automatically set a breakpoint at the end of the current procedure
        !           536:  * to turn off the given tracing.
        !           537:  */
        !           538: 
        !           539: public traceon(inst, event, cmdlist)
        !           540: boolean inst;
        !           541: Event event;
        !           542: Cmdlist cmdlist;
        !           543: {
        !           544:     register Trcmd trcmd;
        !           545:     Breakpoint bp;
        !           546:     Cmdlist actions;
        !           547:     Address ret;
        !           548:     Event e;
        !           549: 
        !           550:     if (event == nil) {
        !           551:        e = curevent;
        !           552:     } else {
        !           553:        e = event;
        !           554:     }
        !           555:     trcmd = new(Trcmd);
        !           556:     ++trid;
        !           557:     trcmd->trid = trid;
        !           558:     trcmd->event = e;
        !           559:     trcmd->cmdlist = cmdlist;
        !           560:     single_stepping = true;
        !           561:     if (inst) {
        !           562:        inst_tracing = true;
        !           563:        list_append(list_item(trcmd), nil, eachinst);
        !           564:     } else {
        !           565:        list_append(list_item(trcmd), nil, eachline);
        !           566:     }
        !           567:     ret = return_addr();
        !           568:     if (ret != 0) {
        !           569:        actions = buildcmdlist(build(O_TRACEOFF, trcmd->trid));
        !           570:        bp = bp_alloc(e, (Address) ret, 0, actions);
        !           571:        bp->temporary = true;
        !           572:     }
        !           573:     if (tracebpts) {
        !           574:        printf("adding trace %d for event %d\n", trcmd->trid, e->id);
        !           575:     }
        !           576: }
        !           577: 
        !           578: /*
        !           579:  * Turn off some kind of tracing.
        !           580:  * Strictly an internal command, this cannot be invoked by the user.
        !           581:  */
        !           582: 
        !           583: public traceoff(id)
        !           584: Integer id;
        !           585: {
        !           586:     register Trcmd t;
        !           587:     register boolean found;
        !           588: 
        !           589:     found = false;
        !           590:     foreach (Trcmd, t, eachline)
        !           591:        if (t->trid == id) {
        !           592:            printrmtr(t);
        !           593:            list_delete(list_curitem(eachline), eachline);
        !           594:            found = true;
        !           595:            break;
        !           596:        }
        !           597:     endfor
        !           598:     if (not found) {
        !           599:        foreach (Trcmd, t, eachinst)
        !           600:            if (t->event->id == id) {
        !           601:                printrmtr(t);
        !           602:                list_delete(list_curitem(eachinst), eachinst);
        !           603:                found = true;
        !           604:                break;
        !           605:            }
        !           606:        endfor
        !           607:        if (not found) {
        !           608:            beginerrmsg();
        !           609:            fprintf(stderr, "[internal error: trace id %d not found]\n", id);
        !           610:        }
        !           611:     }
        !           612:     if (list_size(eachinst) == 0) {
        !           613:        inst_tracing = false;
        !           614:        if (list_size(eachline) == 0) {
        !           615:            single_stepping = false;
        !           616:        }
        !           617:     }
        !           618: }
        !           619: 
        !           620: /*
        !           621:  * If breakpoints are being traced, note that a Trcmd is being deleted.
        !           622:  */
        !           623: 
        !           624: private printrmtr(t)
        !           625: Trcmd t;
        !           626: {
        !           627:     if (tracebpts) {
        !           628:        printf("removing trace %d", t->trid);
        !           629:        if (t->event != nil) {
        !           630:            printf(" for event %d", t->event->id);
        !           631:        }
        !           632:        printf("\n");
        !           633:     }
        !           634: }
        !           635: 
        !           636: /*
        !           637:  * Print out news during single step tracing.
        !           638:  */
        !           639: 
        !           640: public printnews()
        !           641: {
        !           642:     register Trcmd t;
        !           643: 
        !           644:     foreach (Trcmd, t, eachline)
        !           645:        evalcmdlist(t->cmdlist);
        !           646:     endfor
        !           647:     foreach (Trcmd, t, eachinst)
        !           648:        evalcmdlist(t->cmdlist);
        !           649:     endfor
        !           650:     bpact();
        !           651: }
        !           652: 
        !           653: /*
        !           654:  * A procedure call/return has occurred while single-stepping,
        !           655:  * note it if we're tracing lines.
        !           656:  */
        !           657: 
        !           658: private boolean chklist();
        !           659: 
        !           660: public callnews(iscall)
        !           661: boolean iscall;
        !           662: {
        !           663:     if (not chklist(eachline, iscall)) {
        !           664:        chklist(eachinst, iscall);
        !           665:     }
        !           666: }
        !           667: 
        !           668: private boolean chklist(list, iscall)
        !           669: List list;
        !           670: boolean iscall;
        !           671: {
        !           672:     register Trcmd t;
        !           673:     register Command cmd;
        !           674: 
        !           675:     setcurfunc(whatblock(pc));
        !           676:     foreach (Trcmd, t, list)
        !           677:        foreach (Command, cmd, t->cmdlist)
        !           678:            if (cmd->op == O_PRINTSRCPOS and
        !           679:              (cmd->value.arg[0] == nil or cmd->value.arg[0]->op == O_QLINE)) {
        !           680:                if (iscall) {
        !           681:                    printentry(curfunc);
        !           682:                } else {
        !           683:                    printexit(curfunc);
        !           684:                }
        !           685:                return true;
        !           686:            }
        !           687:        endfor
        !           688:     endfor
        !           689:     return false;
        !           690: }
        !           691: 
        !           692: /*
        !           693:  * When tracing variables we keep a copy of their most recent value
        !           694:  * and compare it to the current one each time a breakpoint occurs.
        !           695:  * MAXTRSIZE is the maximum size variable we allow.
        !           696:  */
        !           697: 
        !           698: #define MAXTRSIZE 512
        !           699: 
        !           700: /*
        !           701:  * List of variables being watched.
        !           702:  */
        !           703: 
        !           704: typedef struct Trinfo *Trinfo;
        !           705: 
        !           706: struct Trinfo {
        !           707:     Node variable;
        !           708:     Address traddr;
        !           709:     Symbol trblock;
        !           710:     char *trvalue;
        !           711: };
        !           712: 
        !           713: private List trinfolist;
        !           714: 
        !           715: /*
        !           716:  * Find the trace information record associated with the given record.
        !           717:  * If there isn't one then create it and add it to the list.
        !           718:  */
        !           719: 
        !           720: private Trinfo findtrinfo(p)
        !           721: Node p;
        !           722: {
        !           723:     register Trinfo tp;
        !           724:     boolean isnew;
        !           725: 
        !           726:     isnew = true;
        !           727:     if (trinfolist == nil) {
        !           728:        trinfolist = list_alloc();
        !           729:     } else {
        !           730:        foreach (Trinfo, tp, trinfolist)
        !           731:            if (tp->variable == p) {
        !           732:                isnew = false;
        !           733:                break;
        !           734:            }
        !           735:        endfor
        !           736:     }
        !           737:     if (isnew) {
        !           738:        if (tracebpts) {
        !           739:            printf("adding trinfo for \"");
        !           740:            prtree(stdout, p);
        !           741:            printf("\"\n");
        !           742:        }
        !           743:        tp = new(Trinfo);
        !           744:        tp->variable = p;
        !           745:        tp->traddr = lval(p);
        !           746:        tp->trvalue = nil;
        !           747:        list_append(list_item(tp), nil, trinfolist);
        !           748:     }
        !           749:     return tp;
        !           750: }
        !           751: 
        !           752: /*
        !           753:  * Print out the value of a variable if it has changed since the
        !           754:  * last time we checked.
        !           755:  */
        !           756: 
        !           757: public printifchanged(p)
        !           758: Node p;
        !           759: {
        !           760:     register Trinfo tp;
        !           761:     register int n;
        !           762:     char buff[MAXTRSIZE];
        !           763:     Filename curfile;
        !           764:     static Lineno prevline;
        !           765:     static Filename prevfile;
        !           766: 
        !           767:     tp = findtrinfo(p);
        !           768:     n = size(p->nodetype);
        !           769:     dread(buff, tp->traddr, n);
        !           770:     curfile = srcfilename(pc);
        !           771:     if (tp->trvalue == nil) {
        !           772:        tp->trvalue = newarr(char, n);
        !           773:        mov(buff, tp->trvalue, n);
        !           774:        mov(buff, sp, n);
        !           775:        sp += n;
        !           776:        printf("initially (at line %d in \"%s\"):\t", curline, curfile);
        !           777:        prtree(stdout, p);
        !           778:        printf(" = ");
        !           779:        printval(p->nodetype);
        !           780:        putchar('\n');
        !           781:     } else if (cmp(tp->trvalue, buff, n) != 0) {
        !           782:        mov(buff, tp->trvalue, n);
        !           783:        mov(buff, sp, n);
        !           784:        sp += n;
        !           785:        printf("after line %d in \"%s\":\t", prevline, prevfile);
        !           786:        prtree(stdout, p);
        !           787:        printf(" = ");
        !           788:        printval(p->nodetype);
        !           789:        putchar('\n');
        !           790:     }
        !           791:     prevline = curline;
        !           792:     prevfile = curfile;
        !           793: }
        !           794: 
        !           795: /*
        !           796:  * Stop if the value of the given expression has changed.
        !           797:  */
        !           798: 
        !           799: public stopifchanged(p)
        !           800: Node p;
        !           801: {
        !           802:     register Trinfo tp;
        !           803:     register int n;
        !           804:     char buff[MAXTRSIZE];
        !           805:     static Lineno prevline;
        !           806: 
        !           807:     tp = findtrinfo(p);
        !           808:     n = size(p->nodetype);
        !           809:     dread(buff, tp->traddr, n);
        !           810:     if (tp->trvalue == nil) {
        !           811:        tp->trvalue = newarr(char, n);
        !           812:        mov(buff, tp->trvalue, n);
        !           813:        isstopped = true;
        !           814:     } else if (cmp(tp->trvalue, buff, n) != 0) {
        !           815:        mov(buff, tp->trvalue, n);
        !           816:        mov(buff, sp, n);
        !           817:        sp += n;
        !           818:        printf("after line %d:\t", prevline);
        !           819:        prtree(stdout, p);
        !           820:        printf(" = ");
        !           821:        printval(p->nodetype);
        !           822:        putchar('\n');
        !           823:        isstopped = true;
        !           824:     }
        !           825:     prevline = curline;
        !           826: }
        !           827: 
        !           828: /*
        !           829:  * Free the tracing table.
        !           830:  */
        !           831: 
        !           832: public trfree()
        !           833: {
        !           834:     register Trinfo tp;
        !           835: 
        !           836:     foreach (Trinfo, tp, trinfolist)
        !           837:        dispose(tp->trvalue);
        !           838:        dispose(tp);
        !           839:        list_delete(list_curitem(trinfolist), trinfolist);
        !           840:     endfor
        !           841: }
        !           842: 
        !           843: /*
        !           844:  * Fix up breakpoint information before continuing execution.
        !           845:  *
        !           846:  * It's necessary to destroy events and breakpoints that were created
        !           847:  * temporarily and still exist because the program terminated abnormally.
        !           848:  */
        !           849: 
        !           850: public fixbps()
        !           851: {
        !           852:     register Event e;
        !           853:     register Trcmd t;
        !           854: 
        !           855:     single_stepping = false;
        !           856:     inst_tracing = false;
        !           857:     trfree();
        !           858:     foreach (Event, e, eventlist)
        !           859:        if (e->temporary) {
        !           860:            if (not delevent(e->id)) {
        !           861:                printf("!! dbx.fixbps: can't find event %d\n", e->id);
        !           862:            }
        !           863:        }
        !           864:     endfor
        !           865:     foreach (Trcmd, t, eachline)
        !           866:        printrmtr(t);
        !           867:        list_delete(list_curitem(eachline), eachline);
        !           868:     endfor
        !           869:     foreach (Trcmd, t, eachinst)
        !           870:        printrmtr(t);
        !           871:        list_delete(list_curitem(eachinst), eachinst);
        !           872:     endfor
        !           873: }
        !           874: 
        !           875: /*
        !           876:  * Set all breakpoints in object code.
        !           877:  */
        !           878: 
        !           879: public setallbps()
        !           880: {
        !           881:     register Breakpoint p;
        !           882: 
        !           883:     foreach (Breakpoint, p, bplist)
        !           884:        setbp(p->bpaddr);
        !           885:     endfor
        !           886: }
        !           887: 
        !           888: /*
        !           889:  * Undo damage done by "setallbps".
        !           890:  */
        !           891: 
        !           892: public unsetallbps()
        !           893: {
        !           894:     register Breakpoint p;
        !           895: 
        !           896:     foreach (Breakpoint, p, bplist)
        !           897:        unsetbp(p->bpaddr);
        !           898:     endfor
        !           899: }

unix.superglobalmegacorp.com

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