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