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