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