|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)pcs.c 5.5 (Berkeley) 4/9/89"; ! 3: #endif ! 4: ! 5: /* ! 6: * adb - subprocess control ! 7: */ ! 8: ! 9: #include "defs.h" ! 10: #include "bkpt.h" ! 11: #include <machine/reg.h> /* for getpc() *//* XXX */ ! 12: #include <sys/file.h> ! 13: #include <sys/ptrace.h> ! 14: #include <sys/wait.h> ! 15: ! 16: extern char NOBKPT[]; ! 17: extern char SZBKPT[]; ! 18: extern char EXBKPT[]; ! 19: extern char NOPCS[]; ! 20: extern char BADMOD[]; ! 21: extern char NOFORK[]; ! 22: extern char ENDPCS[]; ! 23: extern char BADWAIT[]; ! 24: ! 25: struct bkpt *bkpthead; /* head of breakpoint list */ ! 26: ! 27: static long runcount; /* number of times to loop past breakpoints */ ! 28: ! 29: /* bpstate remembers whether we have installed the breakpoints */ ! 30: static enum { BPOUT, BPIN } bpstate; ! 31: ! 32: char *malloc(); ! 33: ! 34: /* run modes */ ! 35: #define CONTINUOUS 0 ! 36: #define SINGLESTEP 1 ! 37: ! 38: /* sub process control */ ! 39: ! 40: subpcs(modif) ! 41: int modif; ! 42: { ! 43: register int check; ! 44: register struct bkpt *bp; ! 45: int execsig, runmode; ! 46: char *comptr; ! 47: ! 48: switch (modif) { ! 49: ! 50: case 'd': ! 51: /* delete breakpoint */ ! 52: if ((bp = scanbkpt(dot)) == NULL) ! 53: error(NOBKPT); ! 54: bp->state = BKPT_FREE; ! 55: return; ! 56: ! 57: case 'D': ! 58: /* delete all breapoints */ ! 59: for (bp = bkpthead; bp != NULL; bp = bp->next) ! 60: bp->state = BKPT_FREE; ! 61: return; ! 62: ! 63: case 'b': ! 64: case 'B': ! 65: /* set breakpoint */ ! 66: if ((bp = scanbkpt(dot)) == NULL) { ! 67: /* find a free one, or make one */ ! 68: for (bp = bkpthead; bp != NULL; bp = bp->next) ! 69: if (bp->state == BKPT_FREE) ! 70: break; ! 71: if (bp == NULL) { ! 72: bp = (struct bkpt *)malloc(sizeof *bp); ! 73: if (bp == NULL) ! 74: error(EXBKPT); ! 75: bp->next = bkpthead; ! 76: bkpthead = bp; ! 77: } ! 78: } ! 79: bp->loc = dot; ! 80: bp->initcnt = bp->count = ecount; ! 81: bp->state = BKPT_SET; ! 82: check = MAX_BKPTCOM - 1; ! 83: comptr = bp->comm; ! 84: (void) rdc(); ! 85: unreadc(); ! 86: do { ! 87: *comptr++ = readchar(); ! 88: } while (check-- && lastc != '\n'); ! 89: *comptr = 0; ! 90: unreadc(); ! 91: if (check == 0) ! 92: error(SZBKPT); ! 93: return; ! 94: ! 95: case 'k': ! 96: case 'K': ! 97: /* kill process */ ! 98: if (pid == 0) ! 99: error(NOPCS); ! 100: adbprintf("%d: killed", pid); ! 101: endpcs(); ! 102: return; ! 103: ! 104: case 'r': ! 105: case 'R': ! 106: /* run program */ ! 107: endpcs(); ! 108: setup(); ! 109: runcount = ecount; ! 110: runmode = CONTINUOUS; ! 111: execsig = 0; ! 112: /* if starting at a breakpoint, run over it */ ! 113: if (scanbkpt(gavedot ? dot : entrypc()) != NULL) ! 114: runcount++; ! 115: break; ! 116: ! 117: case 's': ! 118: case 'S': ! 119: /* single step, with optional signal */ ! 120: runcount = ecount; ! 121: if (pid) { ! 122: runmode = SINGLESTEP; ! 123: execsig = oexpr() ? expv : signo; ! 124: } else { ! 125: setup(); ! 126: runmode = SINGLESTEP; ! 127: execsig = 0; ! 128: runcount--; ! 129: } ! 130: break; ! 131: ! 132: case 'c': ! 133: case 'C': ! 134: case 0: ! 135: /* continue with optional signal */ ! 136: runcount = ecount; ! 137: if (pid == 0) ! 138: error(NOPCS); ! 139: runmode = CONTINUOUS; ! 140: execsig = oexpr() ? expv : signo; ! 141: break; ! 142: ! 143: default: ! 144: error(BADMOD); ! 145: /* NOTREACHED */ ! 146: } ! 147: ! 148: if (runcount > 0 && runpcs(runmode, execsig)) ! 149: adbprintf("breakpoint%16t"); ! 150: else ! 151: adbprintf("stopped at%16t"); ! 152: delbp(); ! 153: printpc(); ! 154: } ! 155: ! 156: /* ! 157: * Print all breakpoints. ! 158: */ ! 159: printbkpts() ! 160: { ! 161: register struct bkpt *b; ! 162: ! 163: adbprintf("breakpoints\ncount%8tbkpt%24tcommand\n"); ! 164: for (b = bkpthead; b != NULL; b = b->next) { ! 165: if (b->state != BKPT_FREE) { ! 166: adbprintf("%-8.8D", b->count); ! 167: psymoff("%R", b->loc, SP_INSTR, maxoff, "%24t"); ! 168: prints(b->comm); ! 169: } ! 170: } ! 171: } ! 172: ! 173: /* ! 174: * Remove (restore to original instruction(s)) all breakpoints. ! 175: */ ! 176: delbp() ! 177: { ! 178: register struct bkpt *b; ! 179: ! 180: if (bpstate != BPOUT) { ! 181: for (b = bkpthead; b != NULL; b = b->next) ! 182: if (b->state != BKPT_FREE && clr_bpt(b)) ! 183: bperr(b, "clear"); ! 184: bpstate = BPOUT; ! 185: } ! 186: } ! 187: ! 188: /* ! 189: * Insert all breakpoints. ! 190: */ ! 191: setbp() ! 192: { ! 193: register struct bkpt *b; ! 194: ! 195: if (bpstate != BPIN) { ! 196: for (b = bkpthead; b != NULL; b = b->next) ! 197: if (b->state != BKPT_FREE && set_bpt(b)) ! 198: bperr(b, "set"); ! 199: bpstate = BPIN; ! 200: } ! 201: } ! 202: ! 203: static ! 204: bperr(b, how) ! 205: struct bkpt *b; ! 206: char *how; ! 207: { ! 208: ! 209: adbprintf("cannot %s breakpoint: ", how); ! 210: psymoff("%R", b->loc, SP_INSTR, maxoff, "\n"); ! 211: } ! 212: ! 213: /* ! 214: * Run subprocess for a while. ! 215: * Return true iff stopped due to breakpoint. ! 216: */ ! 217: int ! 218: runpcs(runmode, execsig) ! 219: int runmode, execsig; ! 220: { ! 221: register struct bkpt *bkpt; ! 222: int rc; ! 223: ! 224: /* always set pc, so that expr>pc works too */ ! 225: setpc(gavedot ? dot : getpc()); ! 226: adbprintf("%s: running\n", symfile.name); ! 227: while (--runcount >= 0) { ! 228: /* BEGIN XXX (machine dependent?, delete ptrace, etc) */ ! 229: if (runmode == SINGLESTEP) ! 230: delbp(); /* hardware handles single-stepping */ ! 231: else { /* continuing from a breakpoint is hard */ ! 232: if ((bkpt = scanbkpt(getpc())) != NULL) { ! 233: execbkpt(bkpt, execsig); ! 234: execsig = 0; ! 235: } ! 236: setbp(); ! 237: } ! 238: (void) ptrace(runmode == CONTINUOUS ? PT_CONTINUE : PT_STEP, ! 239: pid, (int *)getpc(), execsig); ! 240: /* END XXX */ ! 241: ! 242: /* paranoia, SP_DATA usually sufficient, but this is easy */ ! 243: cacheinval(SP_INSTR | SP_DATA); ! 244: ! 245: bpwait(); ! 246: checkerr(); ! 247: execsig = 0; ! 248: delbp(); ! 249: readregs(); ! 250: ! 251: if (signo != 0 || (bkpt = scanbkpt(getpc())) == NULL) { ! 252: execsig = signo; ! 253: rc = 0; ! 254: continue; ! 255: } ! 256: /* stopped by BPT instruction */ ! 257: #ifdef DEBUG ! 258: adbprintf("\n BPT code: comm=%s%8tstate=%d", ! 259: bkpt->comm, bkpt->state); ! 260: #endif ! 261: dot = bkpt->loc; ! 262: switch (bkpt->state) { ! 263: char *p; ! 264: ! 265: case BKPT_SET: ! 266: bkpt->state = BKPT_TRIPPED; ! 267: if (*bkpt->comm == '\n') ! 268: break; ! 269: p = lp; ! 270: command(bkpt->comm, ':'); ! 271: lp = p; ! 272: if (gavedot && edot == 0) /* maybe dot==0 ??? */ ! 273: break; ! 274: if (--bkpt->count == 0) ! 275: break; ! 276: /* FALLTHROUGH */ ! 277: ! 278: case BKPT_TRIPPED: ! 279: execbkpt(bkpt, execsig); ! 280: execsig = 0; ! 281: runcount++; ! 282: continue; ! 283: ! 284: default: ! 285: panic("runpcs"); ! 286: /* NOTREACHED */ ! 287: } ! 288: bkpt->count = bkpt->initcnt; ! 289: rc = 1; ! 290: } ! 291: return (rc); ! 292: } ! 293: ! 294: endpcs() ! 295: { ! 296: register struct bkpt *bp; ! 297: ! 298: if (pid) { ! 299: (void) ptrace(PT_KILL, pid, (int *)0, 0); /* XXX */ ! 300: pid = 0; ! 301: for (bp = bkpthead; bp != NULL; bp = bp->next) ! 302: if (bp->state != BKPT_FREE) ! 303: bp->state = BKPT_SET; ! 304: } ! 305: bpstate = BPOUT; ! 306: } ! 307: ! 308: #ifdef VFORK ! 309: nullsig() ! 310: { ! 311: ! 312: } ! 313: #endif ! 314: ! 315: setup() ! 316: { ! 317: ! 318: cacheinval(SP_INSTR | SP_DATA); /* paranoia */ ! 319: (void) close(symfile.fd); ! 320: symfile.fd = -1; ! 321: #ifndef VFORK ! 322: #define vfork fork ! 323: #endif ! 324: if ((pid = vfork()) == 0) { ! 325: (void) ptrace(PT_TRACE_ME, 0, (int *)0, 0); /* XXX */ ! 326: #ifdef VFORK ! 327: (void) signal(SIGTRAP, nullsig); ! 328: #endif ! 329: (void) signal(SIGINT, sigint); ! 330: (void) signal(SIGQUIT, sigquit); ! 331: doexec(); ! 332: exit(0); ! 333: } else if (pid == -1) { ! 334: pid = 0; ! 335: error(NOFORK); ! 336: } else { ! 337: bpwait(); ! 338: readregs(); ! 339: symfile.fd = open(symfile.name, wtflag); ! 340: if (errflag) { ! 341: adbprintf("%s: cannot execute\n", symfile.name); ! 342: endpcs(); ! 343: error((char *)0); ! 344: } ! 345: } ! 346: bpstate = BPOUT; ! 347: } ! 348: ! 349: /* ! 350: * Single step over a location containing a breakpoint. ! 351: */ ! 352: execbkpt(bp, execsig) ! 353: struct bkpt *bp; ! 354: int execsig; ! 355: { ! 356: ! 357: #ifdef DEBUG ! 358: adbprintf("exbkpt: %d\n", bp->count); ! 359: #endif ! 360: delbp(); ! 361: (void) ptrace(PT_STEP, pid, (int *)bp->loc, execsig); /* XXX */ ! 362: bp->state = BKPT_SET; ! 363: bpwait(); ! 364: checkerr(); ! 365: readregs(); ! 366: } ! 367: ! 368: static char separators[] = "<> \t\n"; ! 369: ! 370: doexec() ! 371: { ! 372: register char *p, **ap; ! 373: register int c; ! 374: char *argl[LINELEN / 2 + 1]; ! 375: char args[LINELEN]; ! 376: extern char **environ; ! 377: char *index(); ! 378: ! 379: ap = argl; ! 380: p = args; ! 381: *ap++ = symfile.name; ! 382: do { ! 383: switch (c = rdc()) { ! 384: ! 385: case '\n': ! 386: break; ! 387: ! 388: case '<': ! 389: setfile(0, O_RDONLY, 0, p, "open"); ! 390: break; ! 391: ! 392: case '>': ! 393: setfile(1, O_CREAT|O_WRONLY, 0666, p, "create"); ! 394: break; ! 395: ! 396: default: ! 397: *ap = p; ! 398: while (index(separators, c) == NULL) { ! 399: *p++ = c; ! 400: c = readchar(); ! 401: } ! 402: *p++ = '\0'; ! 403: ap++; ! 404: } ! 405: } while (c != '\n'); ! 406: unreadc(); ! 407: *ap++ = 0; ! 408: execve(symfile.name, argl, environ); ! 409: perror(symfile.name); ! 410: } ! 411: ! 412: static int ! 413: setfile(fd, flags, mode, namebuf, err) ! 414: int fd, flags, mode; ! 415: char *namebuf, *err; ! 416: { ! 417: register char *p = namebuf; ! 418: register int c = rdc(); ! 419: ! 420: while (index(separators, c) == NULL) { ! 421: *p++ = c; ! 422: c = readchar(); ! 423: } ! 424: *p = 0; ! 425: (void) close(fd); ! 426: if (open(namebuf, flags, mode) < 0) { ! 427: adbprintf("%s: cannot %s\n", namebuf, err); ! 428: _exit(0); ! 429: /* NOTREACHED */ ! 430: } ! 431: } ! 432: ! 433: struct bkpt * ! 434: scanbkpt(a) ! 435: register addr_t a; ! 436: { ! 437: register struct bkpt *bp; ! 438: ! 439: for (bp = bkpthead; bp != NULL; bp = bp->next) ! 440: if (bp->state != BKPT_FREE && bp->loc == a) ! 441: break; ! 442: return (bp); ! 443: } ! 444: ! 445: bpwait() ! 446: { ! 447: register int w; ! 448: union wait status; ! 449: ! 450: (void) signal(SIGINT, SIG_IGN); ! 451: while ((w = wait(&status)) != pid && w != -1) ! 452: /* void */ ; ! 453: (void) signal(SIGINT, intcatch); ! 454: if (w == -1) { ! 455: pid = 0; ! 456: errflag = BADWAIT; ! 457: } else if (!WIFSTOPPED(status)) { ! 458: sigcode = 0; ! 459: if ((signo = status.w_termsig) != 0) ! 460: sigprint(); ! 461: if (status.w_coredump) { ! 462: prints(" - core dumped"); ! 463: (void) close(corefile.fd); ! 464: setcore(); ! 465: } ! 466: pid = 0; ! 467: bpstate = BPOUT; ! 468: errflag = ENDPCS; ! 469: } else { ! 470: signo = status.w_stopsig; ! 471: sigcode = ptrace(PT_READ_U, pid, ! 472: &((struct user *)0)->u_code, 0); /* XXX */ ! 473: if (signo != SIGTRAP) ! 474: sigprint(); ! 475: else ! 476: signo = 0; ! 477: flushbuf(); ! 478: } ! 479: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.