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