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