|
|
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.1 (Berkeley) 6/6/85";
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: if (exp->op != O_RVAL && exp->op != O_CALL) {
208: error("can't trace expressions");
209: }
210: if (block == NIL) {
211: t = tcontainer(exp->left);
212: } else if (block->op == O_NAME) {
213: t = block->nameval;
214: } else {
215: trerror("found %t, expected procedure or function", block);
216: }
217: if (exp->left->op == O_NAME) {
218: s = exp->left->nameval;
219: if (isblock(s)) {
220: addbp(codeloc(t), BLOCK_ON, t, cond, exp->left, 0);
221: if (t == program) {
222: addbp(codeloc(s), CALL, s, cond, NIL, 0);
223: }
224: return;
225: }
226: }
227: addbp(codeloc(t), TERM_ON, t, cond, exp, 0);
228: if (curfunc == t) {
229: var_tracing++;
230: addvar(TRPRINT, exp, cond);
231: addbp(return_addr(), TERM_OFF, t, cond, exp, 0);
232: }
233: }
234:
235: /*
236: * Setting and unsetting of stops.
237: */
238:
239: stop(cmd, exp, where, cond)
240: int cmd;
241: NODE *exp;
242: NODE *where;
243: NODE *cond;
244: {
245: SYM *s;
246: LINENO n;
247:
248: if (exp != NIL) {
249: stopvar(cmd, exp, where, cond);
250: } else if (cond != NIL) {
251: if (where == NIL) {
252: s = program;
253: } else if (where->op == O_NAME) {
254: s = where->nameval;
255: } else {
256: error("bad location for stop");
257: }
258: n = codeloc(s);
259: addbp(n, STOP_ON, s, cond, NIL, n);
260: addcond(TRSTOP, cond);
261: var_tracing++;
262: } else if (where->op == O_NAME) {
263: s = where->nameval;
264: if (!isblock(s)) {
265: error("\"%s\" is not a procedure or function", name(s));
266: }
267: n = codeloc(s);
268: addbp(n, STOP_BP, s, cond, NIL, srcline(firstline(s)));
269: } else {
270: stopinst(cmd, where, cond);
271: }
272: if (where != NIL) {
273: tfree(where);
274: }
275: }
276:
277: LOCAL stopinst(cmd, where, cond)
278: int cmd;
279: NODE *where;
280: NODE *cond;
281: {
282: LINENO line;
283: ADDRESS addr;
284:
285: if (where->op != O_QLINE) {
286: error("expected line number");
287: }
288: if (cmd == O_STOP) {
289: line = (LINENO) where->right->lconval;
290: addr = objaddr(line, where->left->sconval);
291: if (addr == (ADDRESS) -1) {
292: error("can't stop at that line");
293: }
294: } else {
295: line = -1;
296: addr = (ADDRESS) where->right->lconval;
297: }
298: addbp(addr, STOP_BP, NIL, cond, NIL, line);
299: }
300:
301: /*
302: * Implement stopping on assignment to a variable by adding it to
303: * the variable list.
304: */
305:
306: LOCAL stopvar(cmd, exp, where, cond)
307: int cmd;
308: NODE *exp;
309: NODE *where;
310: NODE *cond;
311: {
312: SYM *s;
313:
314: if (exp->op != O_RVAL) {
315: trerror("found %t, expected variable", exp);
316: }
317: if (cmd == O_STOPI) {
318: inst_tracing++;
319: }
320: var_tracing++;
321: addvar(TRSTOP, exp, cond);
322: if (where == NIL) {
323: s = program;
324: } else if (where->op == O_NAME) {
325: s = where->nameval;
326: } else {
327: error("bad location for stop");
328: }
329: addbp(codeloc(s), STOP_ON, s, cond, exp, 0);
330: }
331:
332: /*
333: * Figure out the block that contains the symbols
334: * in the given variable expression.
335: */
336:
337: LOCAL SYM *tcontainer(var)
338: NODE *var;
339: {
340: NODE *p;
341:
342: p = var;
343: while (p->op != O_NAME) {
344: if (isleaf(p->op)) {
345: panic("unexpected op %d in tcontainer", p->op);
346: /* NOTREACHED */
347: }
348: p = p->left;
349: }
350: return container(p->nameval);
351: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.