|
|
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[] = "@(#)tracestop.c 5.2 (Berkeley) 4/6/87";
9: #endif not lint
10:
11: /*
12: * Handle trace and stop commands.
13: */
14:
15: #include "defs.h"
16: #include "breakpoint.h"
17: #include "sym.h"
18: #include "tree.h"
19: #include "runtime.h"
20: #include "source.h"
21: #include "object.h"
22: #include "mappings.h"
23: #include "machine.h"
24: #include "tree.rep"
25:
26: LOCAL SYM *tcontainer();
27:
28: /*
29: * Process a trace/untrace command, basically checking arguments
30: * and translate to a call of the appropriate routine.
31: */
32:
33: trace(cmd, exp, where, cond)
34: int cmd;
35: NODE *exp;
36: NODE *where;
37: NODE *cond;
38: {
39: if (exp == NIL) {
40: traceall(cmd, where, cond);
41: } else if (exp->op == O_LCON || exp->op == O_QLINE) {
42: traceinst(cmd, exp, where, cond);
43: } else if (where!=NIL && (where->op==O_QLINE || where->op==O_LCON)) {
44: traceat(cmd, exp, where, cond);
45: } else {
46: tracedata(cmd, exp, where, cond);
47: }
48: if (where != NIL) {
49: tfree(where);
50: }
51: }
52:
53: /*
54: * Set a breakpoint that will turn on tracing.
55: *
56: * A line number of 0 in the breakpoint information structure
57: * means it's a normal trace.
58: *
59: * A line number of -1 indicates that we want to trace at the instruction
60: * rather than source line level.
61: *
62: * If location is NIL, turn on tracing because if the user
63: * has the program stopped somewhere and says "trace",
64: * he/she wants to see tracing after continuing execution.
65: */
66:
67: LOCAL traceall(cmd, where, cond)
68: int cmd;
69: NODE *where;
70: NODE *cond;
71: {
72: SYM *s;
73: LINENO line;
74:
75: if (where != NIL && where->op != O_NAME) {
76: error("bad location for trace");
77: }
78: if (cmd == O_TRACE) {
79: line = 0;
80: } else {
81: line = -1;
82: }
83: if (where == NIL) {
84: switch (cmd) {
85: case O_TRACE:
86: if (tracing != 0) {
87: error("already tracing lines");
88: }
89: tracing++;
90: addcond(TRPRINT, cond);
91: break;
92:
93: case O_TRACEI:
94: if (inst_tracing != 0) {
95: error("already tracing instructions");
96: }
97: inst_tracing++;
98: addcond(TRPRINT, cond);
99: break;
100:
101: default:
102: panic("bad cmd in traceall");
103: break;
104: }
105: s = program;
106: } else if (where->op != O_NAME) {
107: trerror("found %t, expected procedure or function", where);
108: } else {
109: s = where->nameval;
110: if (!isblock(s)) {
111: error("\"%s\" is not a procedure or function", name(s));
112: }
113: }
114: addbp(codeloc(s), ALL_ON, s, cond, NIL, line);
115: }
116:
117: /*
118: * Set up the appropriate breakpoint for tracing an instruction.
119: */
120:
121: LOCAL traceinst(cmd, exp, where, cond)
122: int cmd;
123: NODE *exp;
124: NODE *where;
125: NODE *cond;
126: {
127: LINENO line;
128: ADDRESS addr;
129:
130: if (where != NIL) {
131: error("unexpected \"at\" or \"in\"");
132: }
133: if (cmd == O_TRACEI) {
134: if (exp->op == O_QLINE) {
135: addr = (ADDRESS) exp->right->lconval;
136: } else if (exp->op == O_LCON) {
137: addr = (ADDRESS) exp->lconval;
138: } else {
139: trerror("expected integer constant, found %t", exp);
140: }
141: line = -1;
142: } else {
143: if (exp->op == O_QLINE) {
144: line = (LINENO) exp->right->lconval;
145: addr = objaddr(line, exp->left->sconval);
146: } else {
147: line = (LINENO) exp->lconval;
148: addr = objaddr(line, cursource);
149: }
150: if (addr == (ADDRESS) -1) {
151: error("can't trace line %d", line);
152: }
153: }
154: tfree(exp);
155: addbp(addr, INST, NIL, cond, NIL, line);
156: }
157:
158: /*
159: * set a breakpoint to print an expression at a given line or address
160: */
161:
162: LOCAL traceat(cmd, exp, where, cond)
163: int cmd;
164: NODE *exp;
165: NODE *where;
166: NODE *cond;
167: {
168: LINENO line;
169: ADDRESS addr;
170:
171: if (cmd == O_TRACEI) {
172: if (where->op != O_LCON) {
173: trerror("expected integer constant, found %t", where);
174: }
175: line = -1;
176: addr = (ADDRESS) where->lconval;
177: } else {
178: line = (LINENO) where->right->lconval;
179: addr = objaddr(line, where->left->sconval);
180: if (addr == (ADDRESS) -1) {
181: error("can't trace at line %d", line);
182: }
183: }
184: addbp(addr, AT_BP, NIL, cond, exp, line);
185: }
186:
187: /*
188: * Set up breakpoint for tracing data.
189: *
190: * The tracing of blocks lies somewhere between instruction and data;
191: * it's here since a block cannot be distinguished from other terms.
192: *
193: * As in "traceall", if the "block" is the main program then the
194: * user didn't actually specify a block. This means we want to
195: * turn tracing on ourselves because if the program is stopped
196: * we want to be on regardless of whether they say "cont" or "run".
197: */
198:
199: LOCAL tracedata(cmd, exp, block, cond)
200: int cmd;
201: NODE *exp;
202: NODE *block;
203: NODE *cond;
204: {
205: SYM *s, *t;
206:
207: #ifdef lint
208: cmd = cmd;
209: #endif
210: if (exp->op != O_RVAL && exp->op != O_CALL) {
211: error("can't trace expressions");
212: }
213: if (block == NIL) {
214: t = tcontainer(exp->left);
215: } else if (block->op == O_NAME) {
216: t = block->nameval;
217: } else {
218: trerror("found %t, expected procedure or function", block);
219: }
220: if (exp->left->op == O_NAME) {
221: s = exp->left->nameval;
222: if (isblock(s)) {
223: addbp(codeloc(t), BLOCK_ON, t, cond, exp->left, 0);
224: if (t == program) {
225: addbp(codeloc(s), CALL, s, cond, NIL, 0);
226: }
227: return;
228: }
229: }
230: addbp(codeloc(t), TERM_ON, t, cond, exp, 0);
231: if (curfunc == t) {
232: var_tracing++;
233: addvar(TRPRINT, exp, cond);
234: addbp(return_addr(), TERM_OFF, t, cond, exp, 0);
235: }
236: }
237:
238: /*
239: * Setting and unsetting of stops.
240: */
241:
242: stop(cmd, exp, where, cond)
243: int cmd;
244: NODE *exp;
245: NODE *where;
246: NODE *cond;
247: {
248: SYM *s;
249: LINENO n;
250:
251: if (exp != NIL) {
252: stopvar(cmd, exp, where, cond);
253: } else if (cond != NIL) {
254: if (where == NIL) {
255: s = program;
256: } else if (where->op == O_NAME) {
257: s = where->nameval;
258: } else {
259: error("bad location for stop");
260: }
261: n = codeloc(s);
262: addbp(n, STOP_ON, s, cond, NIL, n);
263: addcond(TRSTOP, cond);
264: var_tracing++;
265: } else if (where->op == O_NAME) {
266: s = where->nameval;
267: if (!isblock(s)) {
268: error("\"%s\" is not a procedure or function", name(s));
269: }
270: n = codeloc(s);
271: addbp(n, STOP_BP, s, cond, NIL, srcline(firstline(s)));
272: } else {
273: stopinst(cmd, where, cond);
274: }
275: if (where != NIL) {
276: tfree(where);
277: }
278: }
279:
280: LOCAL stopinst(cmd, where, cond)
281: int cmd;
282: NODE *where;
283: NODE *cond;
284: {
285: LINENO line;
286: ADDRESS addr;
287:
288: if (where->op != O_QLINE) {
289: error("expected line number");
290: }
291: if (cmd == O_STOP) {
292: line = (LINENO) where->right->lconval;
293: addr = objaddr(line, where->left->sconval);
294: if (addr == (ADDRESS) -1) {
295: error("can't stop at that line");
296: }
297: } else {
298: line = -1;
299: addr = (ADDRESS) where->right->lconval;
300: }
301: addbp(addr, STOP_BP, NIL, cond, NIL, line);
302: }
303:
304: /*
305: * Implement stopping on assignment to a variable by adding it to
306: * the variable list.
307: */
308:
309: LOCAL stopvar(cmd, exp, where, cond)
310: int cmd;
311: NODE *exp;
312: NODE *where;
313: NODE *cond;
314: {
315: SYM *s;
316:
317: if (exp->op != O_RVAL) {
318: trerror("found %t, expected variable", exp);
319: }
320: if (cmd == O_STOPI) {
321: inst_tracing++;
322: }
323: var_tracing++;
324: addvar(TRSTOP, exp, cond);
325: if (where == NIL) {
326: s = program;
327: } else if (where->op == O_NAME) {
328: s = where->nameval;
329: } else {
330: error("bad location for stop");
331: }
332: addbp(codeloc(s), STOP_ON, s, cond, exp, 0);
333: }
334:
335: /*
336: * Figure out the block that contains the symbols
337: * in the given variable expression.
338: */
339:
340: LOCAL SYM *tcontainer(var)
341: NODE *var;
342: {
343: NODE *p;
344:
345: p = var;
346: while (p->op != O_NAME) {
347: if (isleaf(p->op)) {
348: panic("unexpected op %d in tcontainer", p->op);
349: /* NOTREACHED */
350: }
351: p = p->left;
352: }
353: return container(p->nameval);
354: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.