|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.