1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)bpact.c 1.1 01/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 } 316