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: }