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