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