|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)bpact.c 1.1 1/18/82";
4:
5: /*
6: * Routines for doing the right thing when a breakpoint is reached.
7: */
8:
9: #include "defs.h"
10: #include "breakpoint.h"
11: #include "sym.h"
12: #include "tree.h"
13: #include "source.h"
14: #include "mappings.h"
15: #include "runtime.h"
16: #include "process.h"
17: #include "machine.h"
18: #include "main.h"
19: #include "bp.rep"
20: #include "tree/tree.rep"
21:
22: typedef enum { SAVE, NOSAVE } SAVEBP;
23:
24: LOCAL SAVEBP handlebp();
25:
26: /*
27: * A "delayed" breakpoint is one that has an action involving execution
28: * of code, e.g. at a CALL we want to step from the beginning of the
29: * procedure to the first line before printing parameters.
30: */
31:
32: LOCAL short delayed;
33:
34: #define NONE 0
35: #define DELAY_CALL 1
36: #define DELAY_STOP 2
37:
38: /*
39: * Take action at a breakpoint; if it's not a breakpoint return FALSE.
40: *
41: * As we go through the list of breakpoints, we have to remember
42: * the previous one so that "handlebp" can delete breakpoints on
43: * the fly if necessary.
44: *
45: * If the breakpoint is a STOP_BP, handlebp will set "isstopped". After
46: * going through the loop, bpact checks if "isstopped" is set and calls
47: * printstatus if it is. This is so multiple breakpoints at the same
48: * address, one of which is a STOP_BP, still work.
49: */
50:
51: #define isswitch(bptype) ( \
52: bptype == ALL_ON || bptype == ALL_OFF || \
53: bptype == TERM_ON || bptype == TERM_OFF || \
54: bptype == BLOCK_ON || bptype == BLOCK_OFF || \
55: bptype == STOP_ON || bptype == STOP_OFF \
56: )
57:
58: BOOLEAN bpact()
59: {
60: register BPINFO *p;
61: BPINFO *prev, *next;
62: BOOLEAN found;
63: ADDRESS oldpc;
64:
65: delayed = NONE;
66: found = FALSE;
67: prev = NIL;
68: for (p = bphead; p != NIL; p = next) {
69: next = p->bpnext;
70: if (p->bpaddr == pc) {
71: prbpfound(p);
72: found = TRUE;
73: if (p->bpcond == NIL || isswitch(p->bptype) || cond(p->bpcond)) {
74: prbphandled();
75: if (handlebp(p) == NOSAVE) {
76: prbpnosave();
77: if (prev == NIL) {
78: bphead = next;
79: } else {
80: prev->bpnext = next;
81: }
82: dispose(p);
83: } else {
84: prbpsave();
85: prev = p;
86: }
87: } else {
88: prev = p;
89: }
90: } else {
91: prev = p;
92: }
93: }
94: if (delayed != NONE) {
95: oldpc = pc;
96: runtofirst();
97: if ((delayed&DELAY_CALL) == DELAY_CALL) {
98: SYM *s, *t;
99:
100: s = curfunc;
101: t = whatblock(return_addr());
102: if (t == NIL) {
103: panic("can't find block for caller addr %d", caller_addr());
104: }
105: printcall(s, t);
106: addbp(return_addr(), RETURN, s, NIL, NIL, 0);
107: }
108: if (pc != oldpc) {
109: bpact();
110: }
111: if (isstopped) {
112: printstatus();
113: }
114: } else {
115: if (isstopped) {
116: printstatus();
117: }
118: }
119: fflush(stdout);
120: return(found);
121: }
122:
123: /*
124: * Handle an expected breakpoint appropriately, return whether
125: * or not to save the breakpoint.
126: */
127:
128: LOCAL SAVEBP handlebp(p)
129: BPINFO *p;
130: {
131: register SYM *s, *t;
132: SAVEBP r;
133:
134: r = SAVE;
135: switch(p->bptype) {
136: case ALL_ON:
137: curfunc = p->bpblock;
138: addcond(TRPRINT, p->bpcond);
139: if (p->bpline >= 0) {
140: tracing++;
141: } else {
142: inst_tracing++;
143: }
144: addbp(return_addr(), ALL_OFF, curfunc, p->bpcond, NIL, 0);
145: break;
146:
147: case ALL_OFF:
148: r = NOSAVE;
149: if (p->bpline >= 0) {
150: tracing--;
151: } else {
152: inst_tracing--;
153: }
154: delcond(TRPRINT, p->bpcond);
155: curfunc = p->bpblock;
156: break;
157:
158: case STOP_ON:
159: var_tracing++;
160: curfunc = p->bpblock;
161: if (p->bpnode != NIL) {
162: addvar(TRSTOP, p->bpnode, p->bpcond);
163: } else if (p->bpcond != NIL) {
164: addcond(TRSTOP, p->bpcond);
165: }
166: addbp(return_addr(), STOP_OFF, curfunc, p->bpcond, p->bpnode, 0);
167: break;
168:
169: case STOP_OFF:
170: r = NOSAVE;
171: delcond(TRSTOP, p->bpcond);
172: var_tracing--;
173: curfunc = p->bpblock;
174: break;
175:
176: case INST:
177: curline = p->bpline;
178: if (curline > 0) {
179: printf("trace: ");
180: printlines(curline, curline);
181: } else {
182: printf("inst trace: ");
183: printinst(pc, pc);
184: }
185: break;
186:
187: case STOP_BP:
188: if (p->bpblock != NIL) {
189: delayed |= DELAY_STOP;
190: curfunc = p->bpblock;
191: }
192: curline = p->bpline;
193: isstopped = TRUE;
194: break;
195:
196: case BLOCK_ON: {
197: BPINFO *nbp;
198:
199: s = p->bpblock;
200: t = p->bpnode->nameval;
201: nbp = newbp(codeloc(t), CALL, t, p->bpcond, NIL, 0);
202: addbp(return_addr(), BLOCK_OFF, (SYM *) nbp, NIL, NIL, 0);
203: break;
204: }
205:
206: case BLOCK_OFF: {
207: BPINFO *oldbp;
208:
209: r = NOSAVE;
210: oldbp = (BPINFO *) p->bpblock;
211: delbp(oldbp->bpid);
212: break;
213: }
214:
215: case CALL:
216: delayed |= DELAY_CALL;
217: curfunc = p->bpblock;
218: break;
219:
220: case RETURN:
221: r = NOSAVE;
222: s = p->bpblock;
223: printrtn(s);
224: break;
225:
226: case TERM_ON: {
227: ADDRESS addr;
228:
229: curfunc = p->bpblock;
230: addvar(TRPRINT, p->bpnode, p->bpcond);
231: addr = return_addr();
232: addbp(addr, TERM_OFF, curfunc, p->bpcond, p->bpnode, 0);
233: var_tracing++;
234: break;
235: }
236:
237: case TERM_OFF:
238: r = NOSAVE;
239: var_tracing--;
240: delvar(TRPRINT, p->bpnode, p->bpcond);
241: curfunc = p->bpblock;
242: break;
243:
244: case AT_BP:
245: printf("at line %d: ", p->bpline);
246: eval(p->bpnode);
247: prtree(p->bpnode);
248: printf(" = ");
249: printval(p->bpnode->nodetype);
250: putchar('\n');
251: break;
252:
253: /*
254: * Returning from a called procedure.
255: * Further breakpoint processing is not done, since if
256: * there were any it wouldn't be associated with the call.
257: */
258: case CALLPROC:
259: procreturn(p->bpblock);
260: delbp(p->bpid);
261: erecover();
262: /* NOTREACHED */
263:
264: case END_BP:
265: r = NOSAVE;
266: endprogram();
267:
268: default:
269: panic("unknown bptype %d in cont", p->bptype);
270: /* NOTREACHED */
271: }
272: return(r);
273: }
274:
275: /*
276: * Internal trace routines.
277: */
278:
279: LOCAL char *prbptype[] ={
280: "ALL_ON", "ALL_OFF", "INST", "CALL", "RETURN", "BLOCK_ON", "BLOCK_OFF",
281: "TERM_ON", "TERM_OFF", "AT_BP", "STOP_BP", "CALLPROC", "END_BP",
282: "STOP_ON", "STOP_OFF",
283: };
284:
285: LOCAL prbpfound(p)
286: BPINFO *p;
287: {
288: if (option('b')) {
289: printf("%s breakpoint found at pc %d, line %d -- ",
290: prbptype[(int) p->bptype], p->bpaddr, p->bpline);
291: }
292: }
293:
294: LOCAL prbphandled()
295: {
296: if (option('b')) {
297: printf("handled, ");
298: }
299: }
300:
301: LOCAL prbpnosave()
302: {
303: if (option('b')) {
304: printf("not saved\n");
305: fflush(stdout);
306: }
307: }
308:
309: LOCAL prbpsave()
310: {
311: if (option('b')) {
312: printf("saved\n");
313: fflush(stdout);
314: }
315: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.