1*22276Sdist /*
2*22276Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22276Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22276Sdist  * specifies the terms and conditions for redistribution.
5*22276Sdist  */
65464Slinton 
7*22276Sdist #ifndef lint
8*22276Sdist static char sccsid[] = "@(#)bpact.c	5.1 (Berkeley) 06/05/85";
9*22276Sdist #endif not lint
105464Slinton /*
115464Slinton  * Routines for doing the right thing when a breakpoint is reached.
125464Slinton  */
135464Slinton 
145464Slinton #include "defs.h"
155464Slinton #include "breakpoint.h"
165464Slinton #include "sym.h"
175464Slinton #include "tree.h"
185464Slinton #include "source.h"
195464Slinton #include "mappings.h"
205464Slinton #include "runtime.h"
215464Slinton #include "process.h"
225464Slinton #include "machine.h"
235464Slinton #include "main.h"
245464Slinton #include "bp.rep"
255464Slinton #include "tree/tree.rep"
265464Slinton 
275464Slinton typedef enum { SAVE, NOSAVE } SAVEBP;
285464Slinton 
295464Slinton LOCAL SAVEBP handlebp();
305464Slinton 
315464Slinton /*
325464Slinton  * A "delayed" breakpoint is one that has an action involving execution
335464Slinton  * of code, e.g. at a CALL we want to step from the beginning of the
345464Slinton  * procedure to the first line before printing parameters.
355464Slinton  */
365464Slinton 
375464Slinton LOCAL short delayed;
385464Slinton 
395464Slinton #define NONE 0
405464Slinton #define DELAY_CALL 1
415464Slinton #define DELAY_STOP 2
425464Slinton 
435464Slinton /*
445464Slinton  * Take action at a breakpoint; if it's not a breakpoint return FALSE.
455464Slinton  *
465464Slinton  * As we go through the list of breakpoints, we have to remember
475464Slinton  * the previous one so that "handlebp" can delete breakpoints on
485464Slinton  * the fly if necessary.
495464Slinton  *
505464Slinton  * If the breakpoint is a STOP_BP, handlebp will set "isstopped".  After
515464Slinton  * going through the loop, bpact checks if "isstopped" is set and calls
525464Slinton  * printstatus if it is.  This is so multiple breakpoints at the same
535464Slinton  * address, one of which is a STOP_BP, still work.
545464Slinton  */
555464Slinton 
565464Slinton #define isswitch(bptype) ( \
575464Slinton 	bptype == ALL_ON || bptype == ALL_OFF || \
585464Slinton 	bptype == TERM_ON || bptype == TERM_OFF || \
595464Slinton 	bptype == BLOCK_ON || bptype == BLOCK_OFF || \
605464Slinton 	bptype == STOP_ON || bptype == STOP_OFF \
615464Slinton )
625464Slinton 
635464Slinton BOOLEAN bpact()
645464Slinton {
655464Slinton 	register BPINFO *p;
665464Slinton 	BPINFO *prev, *next;
675464Slinton 	BOOLEAN found;
685464Slinton 	ADDRESS oldpc;
695464Slinton 
705464Slinton 	delayed = NONE;
715464Slinton 	found = FALSE;
725464Slinton 	prev = NIL;
735464Slinton 	for (p = bphead; p != NIL; p = next) {
745464Slinton 		next = p->bpnext;
755464Slinton 		if (p->bpaddr == pc) {
765464Slinton 			prbpfound(p);
775464Slinton 			found = TRUE;
785464Slinton 			if (p->bpcond == NIL || isswitch(p->bptype) || cond(p->bpcond)) {
795464Slinton 				prbphandled();
805464Slinton 				if (handlebp(p) == NOSAVE) {
815464Slinton 					prbpnosave();
825464Slinton 					if (prev == NIL) {
835464Slinton 						bphead = next;
845464Slinton 					} else {
855464Slinton 						prev->bpnext = next;
865464Slinton 					}
875464Slinton 					dispose(p);
885464Slinton 				} else {
895464Slinton 					prbpsave();
905464Slinton 					prev = p;
915464Slinton 				}
925464Slinton 			} else {
935464Slinton 				prev = p;
945464Slinton 			}
955464Slinton 		} else {
965464Slinton 			prev = p;
975464Slinton 		}
985464Slinton 	}
995464Slinton 	if (delayed != NONE) {
1005464Slinton 		oldpc = pc;
1015464Slinton 		runtofirst();
1025464Slinton 		if ((delayed&DELAY_CALL) == DELAY_CALL) {
1035464Slinton 			SYM *s, *t;
1045464Slinton 
1055464Slinton 			s = curfunc;
1065464Slinton 			t = whatblock(return_addr());
1075464Slinton 			if (t == NIL) {
1085464Slinton 				panic("can't find block for caller addr %d", caller_addr());
1095464Slinton 			}
1105464Slinton 			printcall(s, t);
1115464Slinton 			addbp(return_addr(), RETURN, s, NIL, NIL, 0);
1125464Slinton 		}
1135464Slinton 		if (pc != oldpc) {
1145464Slinton 			bpact();
1155464Slinton 		}
1165464Slinton 		if (isstopped) {
1175464Slinton 			printstatus();
1185464Slinton 		}
1195464Slinton 	} else {
1205464Slinton 		if (isstopped) {
1215464Slinton 			printstatus();
1225464Slinton 		}
1235464Slinton 	}
1245464Slinton 	fflush(stdout);
1255464Slinton 	return(found);
1265464Slinton }
1275464Slinton 
1285464Slinton /*
1295464Slinton  * Handle an expected breakpoint appropriately, return whether
1305464Slinton  * or not to save the breakpoint.
1315464Slinton  */
1325464Slinton 
1335464Slinton LOCAL SAVEBP handlebp(p)
1345464Slinton BPINFO *p;
1355464Slinton {
1365464Slinton 	register SYM *s, *t;
1375464Slinton 	SAVEBP r;
1385464Slinton 
1395464Slinton 	r = SAVE;
1405464Slinton 	switch(p->bptype) {
1415464Slinton 		case ALL_ON:
1425464Slinton 			curfunc = p->bpblock;
1435464Slinton 			addcond(TRPRINT, p->bpcond);
1445464Slinton 			if (p->bpline >= 0) {
1455464Slinton 				tracing++;
1465464Slinton 			} else {
1475464Slinton 				inst_tracing++;
1485464Slinton 			}
1495464Slinton 			addbp(return_addr(), ALL_OFF, curfunc, p->bpcond, NIL, 0);
1505464Slinton 			break;
1515464Slinton 
1525464Slinton 		case ALL_OFF:
1535464Slinton 			r = NOSAVE;
1545464Slinton 			if (p->bpline >= 0) {
1555464Slinton 				tracing--;
1565464Slinton 			} else {
1575464Slinton 				inst_tracing--;
1585464Slinton 			}
1595464Slinton 			delcond(TRPRINT, p->bpcond);
1605464Slinton 			curfunc = p->bpblock;
1615464Slinton 			break;
1625464Slinton 
1635464Slinton 		case STOP_ON:
1645464Slinton 			var_tracing++;
1655464Slinton 			curfunc = p->bpblock;
1665464Slinton 			if (p->bpnode != NIL) {
1675464Slinton 				addvar(TRSTOP, p->bpnode, p->bpcond);
1685464Slinton 			} else if (p->bpcond != NIL) {
1695464Slinton 				addcond(TRSTOP, p->bpcond);
1705464Slinton 			}
1715464Slinton 			addbp(return_addr(), STOP_OFF, curfunc, p->bpcond, p->bpnode, 0);
1725464Slinton 			break;
1735464Slinton 
1745464Slinton 		case STOP_OFF:
1755464Slinton 			r = NOSAVE;
1765464Slinton 			delcond(TRSTOP, p->bpcond);
1775464Slinton 			var_tracing--;
1785464Slinton 			curfunc = p->bpblock;
1795464Slinton 			break;
1805464Slinton 
1815464Slinton 		case INST:
1825464Slinton 			curline = p->bpline;
1835464Slinton 			if (curline > 0) {
1845464Slinton 				printf("trace:  ");
1855464Slinton 				printlines(curline, curline);
1865464Slinton 			} else {
1875464Slinton 				printf("inst trace:	");
1885464Slinton 				printinst(pc, pc);
1895464Slinton 			}
1905464Slinton 			break;
1915464Slinton 
1925464Slinton 		case STOP_BP:
1935464Slinton 			if (p->bpblock != NIL) {
1945464Slinton 				delayed |= DELAY_STOP;
1955464Slinton 				curfunc = p->bpblock;
1965464Slinton 			}
1975464Slinton 			curline = p->bpline;
1985464Slinton 			isstopped = TRUE;
1995464Slinton 			break;
2005464Slinton 
2015464Slinton 		case BLOCK_ON: {
2025464Slinton 			BPINFO *nbp;
2035464Slinton 
2045464Slinton 			s = p->bpblock;
2055464Slinton 			t = p->bpnode->nameval;
2065464Slinton 			nbp = newbp(codeloc(t), CALL, t, p->bpcond, NIL, 0);
2075464Slinton 			addbp(return_addr(), BLOCK_OFF, (SYM *) nbp, NIL, NIL, 0);
2085464Slinton 			break;
2095464Slinton 		}
2105464Slinton 
2115464Slinton 		case BLOCK_OFF: {
2125464Slinton 			BPINFO *oldbp;
2135464Slinton 
2145464Slinton 			r = NOSAVE;
2155464Slinton 			oldbp = (BPINFO *) p->bpblock;
2165464Slinton 			delbp(oldbp->bpid);
2175464Slinton 			break;
2185464Slinton 		}
2195464Slinton 
2205464Slinton 		case CALL:
2215464Slinton 			delayed |= DELAY_CALL;
2225464Slinton 			curfunc = p->bpblock;
2235464Slinton 			break;
2245464Slinton 
2255464Slinton 		case RETURN:
2265464Slinton 			r = NOSAVE;
2275464Slinton 			s = p->bpblock;
2285464Slinton 			printrtn(s);
2295464Slinton 			break;
2305464Slinton 
2315464Slinton 		case TERM_ON: {
2325464Slinton 			ADDRESS addr;
2335464Slinton 
2345464Slinton 			curfunc = p->bpblock;
2355464Slinton 			addvar(TRPRINT, p->bpnode, p->bpcond);
2365464Slinton 			addr = return_addr();
2375464Slinton 			addbp(addr, TERM_OFF, curfunc, p->bpcond, p->bpnode, 0);
2385464Slinton 			var_tracing++;
2395464Slinton 			break;
2405464Slinton 		}
2415464Slinton 
2425464Slinton 		case TERM_OFF:
2435464Slinton 			r = NOSAVE;
2445464Slinton 			var_tracing--;
2455464Slinton 			delvar(TRPRINT, p->bpnode, p->bpcond);
2465464Slinton 			curfunc = p->bpblock;
2475464Slinton 			break;
2485464Slinton 
2495464Slinton 		case AT_BP:
2505464Slinton 			printf("at line %d: ", p->bpline);
2515464Slinton 			eval(p->bpnode);
2525464Slinton 			prtree(p->bpnode);
2535464Slinton 			printf(" = ");
2545464Slinton 			printval(p->bpnode->nodetype);
2555464Slinton 			putchar('\n');
2565464Slinton 			break;
2575464Slinton 
2585464Slinton 		/*
2595464Slinton 		 * Returning from a called procedure.
2605464Slinton 		 * Further breakpoint processing is not done, since if
2615464Slinton 		 * there were any it wouldn't be associated with the call.
2625464Slinton 		 */
2635464Slinton 		case CALLPROC:
2645464Slinton 			procreturn(p->bpblock);
2655464Slinton 			delbp(p->bpid);
2665464Slinton 			erecover();
2675464Slinton 			/* NOTREACHED */
2685464Slinton 
2695464Slinton 		case END_BP:
2705464Slinton 			r = NOSAVE;
2715464Slinton 			endprogram();
2725464Slinton 
2735464Slinton 		default:
2745464Slinton 			panic("unknown bptype %d in cont", p->bptype);
2755464Slinton 			/* NOTREACHED */
2765464Slinton 	}
2775464Slinton 	return(r);
2785464Slinton }
2795464Slinton 
2805464Slinton /*
2815464Slinton  * Internal trace routines.
2825464Slinton  */
2835464Slinton 
2845464Slinton LOCAL char *prbptype[] ={
2855464Slinton 	"ALL_ON", "ALL_OFF", "INST", "CALL", "RETURN", "BLOCK_ON", "BLOCK_OFF",
2865464Slinton 	"TERM_ON", "TERM_OFF", "AT_BP", "STOP_BP", "CALLPROC", "END_BP",
2875464Slinton 	"STOP_ON", "STOP_OFF",
2885464Slinton };
2895464Slinton 
2905464Slinton LOCAL prbpfound(p)
2915464Slinton BPINFO *p;
2925464Slinton {
2935464Slinton 	if (option('b')) {
2945464Slinton 		printf("%s breakpoint found at pc %d, line %d -- ",
2955464Slinton 			prbptype[(int) p->bptype], p->bpaddr, p->bpline);
2965464Slinton 	}
2975464Slinton }
2985464Slinton 
2995464Slinton LOCAL prbphandled()
3005464Slinton {
3015464Slinton 	if (option('b')) {
3025464Slinton 		printf("handled, ");
3035464Slinton 	}
3045464Slinton }
3055464Slinton 
3065464Slinton LOCAL prbpnosave()
3075464Slinton {
3085464Slinton 	if (option('b')) {
3095464Slinton 		printf("not saved\n");
3105464Slinton 		fflush(stdout);
3115464Slinton 	}
3125464Slinton }
3135464Slinton 
3145464Slinton LOCAL prbpsave()
3155464Slinton {
3165464Slinton 	if (option('b')) {
3175464Slinton 		printf("saved\n");
3185464Slinton 		fflush(stdout);
3195464Slinton 	}
3205464Slinton }
321