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) 06/05/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 } 321