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