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