Commit | Line | Data |
---|---|---|
d8be300a DF |
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 | */ | |
d1a17f17 | 6 | |
d8be300a | 7 | #ifndef lint |
95f51977 | 8 | static char sccsid[] = "@(#)bpact.c 5.1 (Berkeley) 6/5/85"; |
d8be300a | 9 | #endif not lint |
d1a17f17 ML |
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 | } |