|
|
1.1 ! root 1: /* ! 2: * A debugger. ! 3: * Runtime support. ! 4: */ ! 5: #include <stdio.h> ! 6: #include <ctype.h> ! 7: #include <errno.h> ! 8: #include "trace.h" ! 9: #if NOUT ! 10: #include <n.out.h> ! 11: #else ! 12: #include <l.out.h> ! 13: #endif ! 14: #include <sys/uproc.h> ! 15: #include <signal.h> ! 16: ! 17: /* ! 18: * Talk to the user and try to solve his problems. ! 19: */ ! 20: process() ! 21: { ! 22: register BPT *bp; ! 23: register int n; ! 24: register int nibflag; ! 25: register int bptflag; ! 26: register vaddr_t pc; ! 27: register vaddr_t fp; ! 28: register int f; ! 29: ! 30: /* ! 31: * Let the user speak. ! 32: */ ! 33: top: ! 34: bptflag = 0; ! 35: execute(":x\n"); ! 36: for (;;) { ! 37: /* ! 38: * Initialise flags. ! 39: */ ! 40: bitflag = 0; ! 41: nibflag = 0; ! 42: ! 43: /* ! 44: * If in single step mode, set up for single step. ! 45: */ ! 46: if (sinmode!=SNULL && sinmode!=SWAIT) { ! 47: bitflag = 1; ! 48: if (sinmode == SCONT) ! 49: setcont(); ! 50: } ! 51: ! 52: /* ! 53: * Place all breakpoints. ! 54: */ ! 55: pc = getpc(); ! 56: for (n=NBPT, bp=&bpt[0]; n--; bp++) { ! 57: if (bp->b_flag == 0) ! 58: continue; ! 59: add = bp->b_badd; ! 60: if (getb(1, bp->b_bins, sizeof(BIN)) == 0) { ! 61: fprintf( stderr, "cannot read\n"); ! 62: printb(bp->b_badd); ! 63: goto err; ! 64: } ! 65: if (bptflag!=0 && bp->b_badd==pc) { ! 66: bitflag = 1; ! 67: continue; ! 68: } ! 69: add = bp->b_badd; ! 70: if (putb(1, bin, sizeof(BIN)) == 0) { ! 71: fprintf( stderr, "cannot install\n"); ! 72: printb(bp->b_badd); ! 73: goto err; ! 74: } ! 75: } ! 76: bptflag = 0; ! 77: ! 78: /* ! 79: * Set flags and call machine dependent restore routine. ! 80: */ ! 81: if (testbpt(pc) != 0) ! 82: nibflag = 1; ! 83: if (restret() == 0) ! 84: goto err; ! 85: ! 86: /* ! 87: * Start up the child. ! 88: */ ! 89: errno = 0; ! 90: ptrace(bitflag?9:7, pid, (int *)1, 0); ! 91: if (errno) { ! 92: printr("Ptrace error (%d)", errno); ! 93: goto err; ! 94: } ! 95: if (waitc() == 0) ! 96: goto err; ! 97: ! 98: /* ! 99: * Get registers and call machine dependent trap routine. ! 100: */ ! 101: if (trapint() == 0) ! 102: goto err; ! 103: if (setregs() == 0) ! 104: goto err; ! 105: if ((f=settrap()) == 0) ! 106: goto err; ! 107: /* ! 108: * Replace breakpoints with instructions. ! 109: */ ! 110: for (n=NBPT, bp=&bpt[0]; n--; bp++) { ! 111: if (bp->b_flag == 0) ! 112: continue; ! 113: add = bp->b_badd; ! 114: if (putb(1, bp->b_bins, sizeof(BIN)) == 0) { ! 115: fprintf( stderr, "cannot replace instr\n"); ! 116: printb(bp->b_badd); ! 117: goto err; ! 118: } ! 119: } ! 120: ! 121: /* ! 122: * If trap was not a breakpoint, tell the user, accept input. ! 123: */ ! 124: if (f != SIGTRAP) { ! 125: execute(":f\n:x\n"); ! 126: continue; ! 127: } ! 128: ! 129: /* ! 130: * Find the breakpoint we are at. ! 131: */ ! 132: pc = getpc() - sizeof(BIN); ! 133: if (bitflag==0 || nibflag!=0) { ! 134: for (n=NBPT, bp=&bpt[0]; n--; bp++) { ! 135: if (bp->b_flag == 0) ! 136: continue; ! 137: if (bp->b_badd != pc) ! 138: continue; ! 139: setpc((vaddr_t)pc); ! 140: bptflag = 1; ! 141: break; ! 142: } ! 143: } ! 144: ! 145: /* ! 146: * If in single step mode, execute command. ! 147: */ ! 148: switch (sinmode) { ! 149: case SSTEP: ! 150: case SCONT: ! 151: execute(sinp); ! 152: if (--sindecr == 0) ! 153: execute(":x\n"); ! 154: continue; ! 155: case SCSET: ! 156: for (n=0, bp=&bpt[0]; n<NBPT; n++, bp++) ! 157: bp->b_flag &= ~BSIN; ! 158: sinmode = SWAIT; ! 159: intcont(); ! 160: break; ! 161: } ! 162: ! 163: /* ! 164: * If we got an unexpected trace trap or unknown ! 165: * breakpoint, we handle it here. ! 166: */ ! 167: if (bp == NULL) { ! 168: if (bitflag==0 || nibflag!=0) ! 169: execute(":f\n:x\n"); ! 170: continue; ! 171: } ! 172: ! 173: /* ! 174: * Single step breakpoints have highest priority. ! 175: */ ! 176: fp = getfp(); ! 177: if ((bp->b_flag&BSIN) != 0) { ! 178: if (bp->b_sfpt==0 || bp->b_sfpt==fp) { ! 179: bp->b_flag &= ~BSIN; ! 180: if (sinmode == SWAIT) { ! 181: sinmode = SCONT; ! 182: execute(sinp); ! 183: if (--sindecr == 0) ! 184: execute(":x\n"); ! 185: continue; ! 186: } ! 187: } ! 188: } ! 189: ! 190: /* ! 191: * Return breakpoints are next. ! 192: */ ! 193: if ((bp->b_flag&BRET) != 0) { ! 194: if (fp == bp->b_rfpt) { ! 195: bp->b_flag &= ~BRET; ! 196: execute(bp->b_rcom); ! 197: continue; ! 198: } ! 199: } ! 200: ! 201: /* ! 202: * Your conventional everyday ordinary breakpoint. ! 203: */ ! 204: if ((bp->b_flag&BBPT) != 0) { ! 205: execute(bp->b_bcom); ! 206: continue; ! 207: } ! 208: } ! 209: ! 210: /* ! 211: * Something is terribly wrong. Kill off our child, ! 212: * and generally reset everything to the start. ! 213: */ ! 214: err: ! 215: killc(); ! 216: reslout(); ! 217: bptinit(); ! 218: goto top; ! 219: ! 220: /* ! 221: * They say psychiatry is one of the hardest occupations. ! 222: * I think I agree. ! 223: */ ! 224: } ! 225: ! 226: /* ! 227: * Reset segmentation for an l.out. ! 228: */ ! 229: reslout() ! 230: { ! 231: struct ldheader ldh; ! 232: ! 233: clramap(); ! 234: objflag = 0; ! 235: fseek(lfp, (long)0, 0); ! 236: if (fread(&ldh, sizeof(ldh), 1, lfp) != 1) { ! 237: printr("Can't read object file"); ! 238: return (0); ! 239: } ! 240: canlout(&ldh); ! 241: if (ldh.l_magic != L_MAGIC) { ! 242: printr("not an object file"); ! 243: return (0); ! 244: } ! 245: objflag = 1; ! 246: setaseg(&ldh); ! 247: return (1); ! 248: } ! 249: ! 250: /* ! 251: * Given a command line in `miscbuf', parse the command line, kill the ! 252: * current child and start up a new one. 0 is returned on success, 1 ! 253: * on failure. ! 254: */ ! 255: runfile() ! 256: { ! 257: register char *bp, *cp; ! 258: register int c; ! 259: char *ifn, *ofn, *argl[ARGSIZE]; ! 260: int qflag, aflag, n; ! 261: ! 262: killc(); ! 263: if (objflag == 0) { ! 264: printe("No l.out"); ! 265: return (1); ! 266: } ! 267: ifn = NULL; ! 268: ofn = NULL; ! 269: qflag = 0; ! 270: aflag = 0; ! 271: n = 0; ! 272: bp = miscbuf; ! 273: cp = miscbuf; ! 274: c = *bp++; ! 275: while (c != '\n') { ! 276: switch (c) { ! 277: case '<': ! 278: ifn = cp; ! 279: c = *bp++; ! 280: break; ! 281: case '>': ! 282: ofn = cp; ! 283: if ((c=*bp++) == '>') { ! 284: aflag = 1; ! 285: c = *bp++; ! 286: } ! 287: break; ! 288: default: ! 289: if (n >= ARGSIZE-1) { ! 290: printe("Too many arguments"); ! 291: return (1); ! 292: } ! 293: argl[n++] = cp; ! 294: } ! 295: while (qflag || !isascii(c) || !isspace(c)) { ! 296: if (c == '\n') ! 297: break; ! 298: if (c == '"') { ! 299: qflag ^= 1; ! 300: c = *bp++; ! 301: continue; ! 302: } ! 303: if (c == '\\') { ! 304: if ((c=*bp++) == '\n') { ! 305: printe("Syntax error"); ! 306: return (1); ! 307: } ! 308: } ! 309: *cp++ = c; ! 310: c = *bp++; ! 311: } ! 312: if (qflag) { ! 313: printe("Missing \""); ! 314: return (1); ! 315: } ! 316: *cp++ = '\0'; ! 317: if (c == '\n') ! 318: break; ! 319: while (isascii(c) && isspace(c)) ! 320: c = *bp++; ! 321: } ! 322: if (n == 0) ! 323: argl[n++] = lfn; ! 324: argl[n] = NULL; ! 325: if (startup(argl, ifn, ofn, aflag) == 0) ! 326: return (1); ! 327: return (0); ! 328: } ! 329: ! 330: /* ! 331: * Start execution of the child. `argv' is the argument list, `ifnp' is ! 332: * the name of the input file, `ofnp' is the name of the output file and ! 333: * `appf' tells us whether the output file is opened for append or write. ! 334: */ ! 335: startup(argv, ifnp, ofnp, appf) ! 336: char **argv; ! 337: char *ifnp; ! 338: char *ofnp; ! 339: { ! 340: register int n; ! 341: ! 342: if ((pid=fork()) < 0) { ! 343: printr("Cannot fork"); ! 344: return (0); ! 345: } ! 346: if (pid == 0) { ! 347: if (ifnp != NULL) { ! 348: if ((n=open(ifnp, 0)) < 0) ! 349: panic("Cannot open %s", ifnp); ! 350: dup2(n, 0); ! 351: close(n); ! 352: } ! 353: if (ofnp != NULL) { ! 354: n = -1; ! 355: if (appf) { ! 356: if ((n=open(ofnp, 1)) >= 0) ! 357: lseek(n, 0L, 2); ! 358: } ! 359: if (n < 0) { ! 360: if ((n=creat(ofnp, 0644)) < 0) ! 361: panic("%s: cannot create", ofnp); ! 362: } ! 363: dup2(n, 1); ! 364: close(n); ! 365: } ! 366: ptrace(0, 0, NULL, 0); ! 367: execv(lfn, argv); ! 368: exit(1); ! 369: } ! 370: if (waitc() == 0) ! 371: return (0); ! 372: clramap(); ! 373: DSPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)0, ! 374: getp, putp, 1); ! 375: ISPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)0, ! 376: getp, putp, 0); ! 377: USPACE = setsmap(NULL, (fsize_t)0, (fsize_t)UPASIZE, (fsize_t)0, ! 378: getp, putp, 2); ! 379: excflag = 1; ! 380: regflag = 1; ! 381: return (1); ! 382: } ! 383: ! 384: /* ! 385: * Given a newly started child, find out necessary information. ! 386: */ ! 387: shiftup() ! 388: { ! 389: if (trapint() == 0) ! 390: return (0); ! 391: if (setregs() == 0) ! 392: return (0); ! 393: return (settrap()); ! 394: } ! 395: ! 396: /* ! 397: * Kill off our child. ! 398: */ ! 399: killc() ! 400: { ! 401: if (excflag) { ! 402: ptrace(8, pid, 0, 0); ! 403: waitc(); ! 404: } ! 405: excflag = 0; ! 406: regflag = 0; ! 407: trapstr = NULL; ! 408: } ! 409: ! 410: /* ! 411: * Wait for the traced process to stop. ! 412: */ ! 413: waitc() ! 414: { ! 415: register int p; ! 416: int s; ! 417: ! 418: while ((p=wait(&s)) != pid) { ! 419: if (p >= 0) { ! 420: printr("Adopted a child %d", p); ! 421: continue; ! 422: } ! 423: if (intflag == 0) { ! 424: excflag = 0; ! 425: printr("Nonexistant child"); ! 426: return (0); ! 427: } ! 428: intflag = 0; ! 429: } ! 430: if ((s&0377) != 0177) { ! 431: excflag = 0; ! 432: printr("Child process terminated (%d)", (s>>8)&0377); ! 433: return (0); ! 434: } ! 435: return (1); ! 436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.