|
|
1.1 ! root 1: /* Copyright (c) 1982 Regents of the University of California */ ! 2: ! 3: static char sccsid[] = "@(#)bpact.c 1.1 1/18/82"; ! 4: ! 5: /* ! 6: * Routines for doing the right thing when a breakpoint is reached. ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include "breakpoint.h" ! 11: #include "sym.h" ! 12: #include "tree.h" ! 13: #include "source.h" ! 14: #include "mappings.h" ! 15: #include "runtime.h" ! 16: #include "process.h" ! 17: #include "machine.h" ! 18: #include "main.h" ! 19: #include "bp.rep" ! 20: #include "tree/tree.rep" ! 21: ! 22: typedef enum { SAVE, NOSAVE } SAVEBP; ! 23: ! 24: LOCAL SAVEBP handlebp(); ! 25: ! 26: /* ! 27: * A "delayed" breakpoint is one that has an action involving execution ! 28: * of code, e.g. at a CALL we want to step from the beginning of the ! 29: * procedure to the first line before printing parameters. ! 30: */ ! 31: ! 32: LOCAL short delayed; ! 33: ! 34: #define NONE 0 ! 35: #define DELAY_CALL 1 ! 36: #define DELAY_STOP 2 ! 37: ! 38: /* ! 39: * Take action at a breakpoint; if it's not a breakpoint return FALSE. ! 40: * ! 41: * As we go through the list of breakpoints, we have to remember ! 42: * the previous one so that "handlebp" can delete breakpoints on ! 43: * the fly if necessary. ! 44: * ! 45: * If the breakpoint is a STOP_BP, handlebp will set "isstopped". After ! 46: * going through the loop, bpact checks if "isstopped" is set and calls ! 47: * printstatus if it is. This is so multiple breakpoints at the same ! 48: * address, one of which is a STOP_BP, still work. ! 49: */ ! 50: ! 51: #define isswitch(bptype) ( \ ! 52: bptype == ALL_ON || bptype == ALL_OFF || \ ! 53: bptype == TERM_ON || bptype == TERM_OFF || \ ! 54: bptype == BLOCK_ON || bptype == BLOCK_OFF || \ ! 55: bptype == STOP_ON || bptype == STOP_OFF \ ! 56: ) ! 57: ! 58: BOOLEAN bpact() ! 59: { ! 60: register BPINFO *p; ! 61: BPINFO *prev, *next; ! 62: BOOLEAN found; ! 63: ADDRESS oldpc; ! 64: ! 65: delayed = NONE; ! 66: found = FALSE; ! 67: prev = NIL; ! 68: for (p = bphead; p != NIL; p = next) { ! 69: next = p->bpnext; ! 70: if (p->bpaddr == pc) { ! 71: prbpfound(p); ! 72: found = TRUE; ! 73: if (p->bpcond == NIL || isswitch(p->bptype) || cond(p->bpcond)) { ! 74: prbphandled(); ! 75: if (handlebp(p) == NOSAVE) { ! 76: prbpnosave(); ! 77: if (prev == NIL) { ! 78: bphead = next; ! 79: } else { ! 80: prev->bpnext = next; ! 81: } ! 82: dispose(p); ! 83: } else { ! 84: prbpsave(); ! 85: prev = p; ! 86: } ! 87: } else { ! 88: prev = p; ! 89: } ! 90: } else { ! 91: prev = p; ! 92: } ! 93: } ! 94: if (delayed != NONE) { ! 95: oldpc = pc; ! 96: runtofirst(); ! 97: if ((delayed&DELAY_CALL) == DELAY_CALL) { ! 98: SYM *s, *t; ! 99: ! 100: s = curfunc; ! 101: t = whatblock(return_addr()); ! 102: if (t == NIL) { ! 103: panic("can't find block for caller addr %d", caller_addr()); ! 104: } ! 105: printcall(s, t); ! 106: addbp(return_addr(), RETURN, s, NIL, NIL, 0); ! 107: } ! 108: if (pc != oldpc) { ! 109: bpact(); ! 110: } ! 111: if (isstopped) { ! 112: printstatus(); ! 113: } ! 114: } else { ! 115: if (isstopped) { ! 116: printstatus(); ! 117: } ! 118: } ! 119: fflush(stdout); ! 120: return(found); ! 121: } ! 122: ! 123: /* ! 124: * Handle an expected breakpoint appropriately, return whether ! 125: * or not to save the breakpoint. ! 126: */ ! 127: ! 128: LOCAL SAVEBP handlebp(p) ! 129: BPINFO *p; ! 130: { ! 131: register SYM *s, *t; ! 132: SAVEBP r; ! 133: ! 134: r = SAVE; ! 135: switch(p->bptype) { ! 136: case ALL_ON: ! 137: curfunc = p->bpblock; ! 138: addcond(TRPRINT, p->bpcond); ! 139: if (p->bpline >= 0) { ! 140: tracing++; ! 141: } else { ! 142: inst_tracing++; ! 143: } ! 144: addbp(return_addr(), ALL_OFF, curfunc, p->bpcond, NIL, 0); ! 145: break; ! 146: ! 147: case ALL_OFF: ! 148: r = NOSAVE; ! 149: if (p->bpline >= 0) { ! 150: tracing--; ! 151: } else { ! 152: inst_tracing--; ! 153: } ! 154: delcond(TRPRINT, p->bpcond); ! 155: curfunc = p->bpblock; ! 156: break; ! 157: ! 158: case STOP_ON: ! 159: var_tracing++; ! 160: curfunc = p->bpblock; ! 161: if (p->bpnode != NIL) { ! 162: addvar(TRSTOP, p->bpnode, p->bpcond); ! 163: } else if (p->bpcond != NIL) { ! 164: addcond(TRSTOP, p->bpcond); ! 165: } ! 166: addbp(return_addr(), STOP_OFF, curfunc, p->bpcond, p->bpnode, 0); ! 167: break; ! 168: ! 169: case STOP_OFF: ! 170: r = NOSAVE; ! 171: delcond(TRSTOP, p->bpcond); ! 172: var_tracing--; ! 173: curfunc = p->bpblock; ! 174: break; ! 175: ! 176: case INST: ! 177: curline = p->bpline; ! 178: if (curline > 0) { ! 179: printf("trace: "); ! 180: printlines(curline, curline); ! 181: } else { ! 182: printf("inst trace: "); ! 183: printinst(pc, pc); ! 184: } ! 185: break; ! 186: ! 187: case STOP_BP: ! 188: if (p->bpblock != NIL) { ! 189: delayed |= DELAY_STOP; ! 190: curfunc = p->bpblock; ! 191: } ! 192: curline = p->bpline; ! 193: isstopped = TRUE; ! 194: break; ! 195: ! 196: case BLOCK_ON: { ! 197: BPINFO *nbp; ! 198: ! 199: s = p->bpblock; ! 200: t = p->bpnode->nameval; ! 201: nbp = newbp(codeloc(t), CALL, t, p->bpcond, NIL, 0); ! 202: addbp(return_addr(), BLOCK_OFF, (SYM *) nbp, NIL, NIL, 0); ! 203: break; ! 204: } ! 205: ! 206: case BLOCK_OFF: { ! 207: BPINFO *oldbp; ! 208: ! 209: r = NOSAVE; ! 210: oldbp = (BPINFO *) p->bpblock; ! 211: delbp(oldbp->bpid); ! 212: break; ! 213: } ! 214: ! 215: case CALL: ! 216: delayed |= DELAY_CALL; ! 217: curfunc = p->bpblock; ! 218: break; ! 219: ! 220: case RETURN: ! 221: r = NOSAVE; ! 222: s = p->bpblock; ! 223: printrtn(s); ! 224: break; ! 225: ! 226: case TERM_ON: { ! 227: ADDRESS addr; ! 228: ! 229: curfunc = p->bpblock; ! 230: addvar(TRPRINT, p->bpnode, p->bpcond); ! 231: addr = return_addr(); ! 232: addbp(addr, TERM_OFF, curfunc, p->bpcond, p->bpnode, 0); ! 233: var_tracing++; ! 234: break; ! 235: } ! 236: ! 237: case TERM_OFF: ! 238: r = NOSAVE; ! 239: var_tracing--; ! 240: delvar(TRPRINT, p->bpnode, p->bpcond); ! 241: curfunc = p->bpblock; ! 242: break; ! 243: ! 244: case AT_BP: ! 245: printf("at line %d: ", p->bpline); ! 246: eval(p->bpnode); ! 247: prtree(p->bpnode); ! 248: printf(" = "); ! 249: printval(p->bpnode->nodetype); ! 250: putchar('\n'); ! 251: break; ! 252: ! 253: /* ! 254: * Returning from a called procedure. ! 255: * Further breakpoint processing is not done, since if ! 256: * there were any it wouldn't be associated with the call. ! 257: */ ! 258: case CALLPROC: ! 259: procreturn(p->bpblock); ! 260: delbp(p->bpid); ! 261: erecover(); ! 262: /* NOTREACHED */ ! 263: ! 264: case END_BP: ! 265: r = NOSAVE; ! 266: endprogram(); ! 267: ! 268: default: ! 269: panic("unknown bptype %d in cont", p->bptype); ! 270: /* NOTREACHED */ ! 271: } ! 272: return(r); ! 273: } ! 274: ! 275: /* ! 276: * Internal trace routines. ! 277: */ ! 278: ! 279: LOCAL char *prbptype[] ={ ! 280: "ALL_ON", "ALL_OFF", "INST", "CALL", "RETURN", "BLOCK_ON", "BLOCK_OFF", ! 281: "TERM_ON", "TERM_OFF", "AT_BP", "STOP_BP", "CALLPROC", "END_BP", ! 282: "STOP_ON", "STOP_OFF", ! 283: }; ! 284: ! 285: LOCAL prbpfound(p) ! 286: BPINFO *p; ! 287: { ! 288: if (option('b')) { ! 289: printf("%s breakpoint found at pc %d, line %d -- ", ! 290: prbptype[(int) p->bptype], p->bpaddr, p->bpline); ! 291: } ! 292: } ! 293: ! 294: LOCAL prbphandled() ! 295: { ! 296: if (option('b')) { ! 297: printf("handled, "); ! 298: } ! 299: } ! 300: ! 301: LOCAL prbpnosave() ! 302: { ! 303: if (option('b')) { ! 304: printf("not saved\n"); ! 305: fflush(stdout); ! 306: } ! 307: } ! 308: ! 309: LOCAL prbpsave() ! 310: { ! 311: if (option('b')) { ! 312: printf("saved\n"); ! 313: fflush(stdout); ! 314: } ! 315: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.