1*48103Sbostic /*- 2*48103Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48103Sbostic * All rights reserved. 4*48103Sbostic * 5*48103Sbostic * %sccs.include.redist.c% 622276Sdist */ 75464Slinton 822276Sdist #ifndef lint 9*48103Sbostic static char sccsid[] = "@(#)bpact.c 5.2 (Berkeley) 04/16/91"; 10*48103Sbostic #endif /* not lint */ 11*48103Sbostic 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 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 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 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 3015464Slinton LOCAL prbphandled() 3025464Slinton { 3035464Slinton if (option('b')) { 3045464Slinton printf("handled, "); 3055464Slinton } 3065464Slinton } 3075464Slinton 3085464Slinton LOCAL prbpnosave() 3095464Slinton { 3105464Slinton if (option('b')) { 3115464Slinton printf("not saved\n"); 3125464Slinton fflush(stdout); 3135464Slinton } 3145464Slinton } 3155464Slinton 3165464Slinton LOCAL prbpsave() 3175464Slinton { 3185464Slinton if (option('b')) { 3195464Slinton printf("saved\n"); 3205464Slinton fflush(stdout); 3215464Slinton } 3225464Slinton } 323