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