136559Sbostic #ifndef lint 2*37336Storek static char sccsid[] = "@(#)pcs.c 5.5 (Berkeley) 04/09/89"; 336559Sbostic #endif 436559Sbostic 536559Sbostic /* 636559Sbostic * adb - subprocess control 736559Sbostic */ 836559Sbostic 936559Sbostic #include "defs.h" 1036559Sbostic #include "bkpt.h" 1136559Sbostic #include <machine/reg.h> /* for getpc() *//* XXX */ 1236559Sbostic #include <sys/file.h> 1336559Sbostic #include <sys/ptrace.h> 1436559Sbostic #include <sys/wait.h> 1536559Sbostic 1636559Sbostic extern char NOBKPT[]; 1736559Sbostic extern char SZBKPT[]; 1836559Sbostic extern char EXBKPT[]; 1936559Sbostic extern char NOPCS[]; 2036559Sbostic extern char BADMOD[]; 2136559Sbostic extern char NOFORK[]; 2236559Sbostic extern char ENDPCS[]; 2336559Sbostic extern char BADWAIT[]; 2436559Sbostic 2536559Sbostic struct bkpt *bkpthead; /* head of breakpoint list */ 2636559Sbostic 2736559Sbostic static long runcount; /* number of times to loop past breakpoints */ 2836559Sbostic 2936559Sbostic /* bpstate remembers whether we have installed the breakpoints */ 3036559Sbostic static enum { BPOUT, BPIN } bpstate; 3136559Sbostic 3236559Sbostic char *malloc(); 3336559Sbostic 3436559Sbostic /* run modes */ 3536559Sbostic #define CONTINUOUS 0 3636559Sbostic #define SINGLESTEP 1 3736559Sbostic 3836559Sbostic /* sub process control */ 3936559Sbostic 4036559Sbostic subpcs(modif) 4136559Sbostic int modif; 4236559Sbostic { 4336559Sbostic register int check; 4436559Sbostic register struct bkpt *bp; 4536578Storek int execsig, runmode; 4636559Sbostic char *comptr; 4736559Sbostic 4836559Sbostic switch (modif) { 4936559Sbostic 5036559Sbostic case 'd': 5136559Sbostic /* delete breakpoint */ 5236559Sbostic if ((bp = scanbkpt(dot)) == NULL) 5336559Sbostic error(NOBKPT); 5436559Sbostic bp->state = BKPT_FREE; 5536559Sbostic return; 5636559Sbostic 5736559Sbostic case 'D': 5836559Sbostic /* delete all breapoints */ 5936559Sbostic for (bp = bkpthead; bp != NULL; bp = bp->next) 6036559Sbostic bp->state = BKPT_FREE; 6136559Sbostic return; 6236559Sbostic 6336559Sbostic case 'b': 6436559Sbostic case 'B': 6536559Sbostic /* set breakpoint */ 66*37336Storek if ((bp = scanbkpt(dot)) == NULL) { 67*37336Storek /* find a free one, or make one */ 6836559Sbostic for (bp = bkpthead; bp != NULL; bp = bp->next) 6936559Sbostic if (bp->state == BKPT_FREE) 7036559Sbostic break; 7136559Sbostic if (bp == NULL) { 7236559Sbostic bp = (struct bkpt *)malloc(sizeof *bp); 7336559Sbostic if (bp == NULL) 7436559Sbostic error(EXBKPT); 7536559Sbostic bp->next = bkpthead; 7636559Sbostic bkpthead = bp; 7736559Sbostic } 7836559Sbostic } 7936559Sbostic bp->loc = dot; 8036559Sbostic bp->initcnt = bp->count = ecount; 8136559Sbostic bp->state = BKPT_SET; 8236559Sbostic check = MAX_BKPTCOM - 1; 8336559Sbostic comptr = bp->comm; 8436559Sbostic (void) rdc(); 8536559Sbostic unreadc(); 8636559Sbostic do { 8736559Sbostic *comptr++ = readchar(); 8836559Sbostic } while (check-- && lastc != '\n'); 8936559Sbostic *comptr = 0; 9036559Sbostic unreadc(); 9136559Sbostic if (check == 0) 9236559Sbostic error(SZBKPT); 9336559Sbostic return; 9436559Sbostic 9536559Sbostic case 'k': 9636559Sbostic case 'K': 9736559Sbostic /* kill process */ 9836559Sbostic if (pid == 0) 9936559Sbostic error(NOPCS); 10036559Sbostic adbprintf("%d: killed", pid); 10136559Sbostic endpcs(); 10236559Sbostic return; 10336559Sbostic 10436559Sbostic case 'r': 10536559Sbostic case 'R': 10636559Sbostic /* run program */ 10736559Sbostic endpcs(); 10836559Sbostic setup(); 10936559Sbostic runcount = ecount; 11036578Storek runmode = CONTINUOUS; 11136559Sbostic execsig = 0; 112*37336Storek /* if starting at a breakpoint, run over it */ 113*37336Storek if (scanbkpt(gavedot ? dot : entrypc()) != NULL) 114*37336Storek runcount++; 11536559Sbostic break; 11636559Sbostic 11736559Sbostic case 's': 11836559Sbostic case 'S': 11936559Sbostic /* single step, with optional signal */ 12036559Sbostic runcount = ecount; 12136559Sbostic if (pid) { 12236559Sbostic runmode = SINGLESTEP; 12336559Sbostic execsig = oexpr() ? expv : signo; 12436559Sbostic } else { 12536559Sbostic setup(); 12636578Storek runmode = SINGLESTEP; 12736559Sbostic execsig = 0; 12836578Storek runcount--; 12936559Sbostic } 13036559Sbostic break; 13136559Sbostic 13236559Sbostic case 'c': 13336559Sbostic case 'C': 13436559Sbostic case 0: 13536559Sbostic /* continue with optional signal */ 13636559Sbostic runcount = ecount; 13736559Sbostic if (pid == 0) 13836559Sbostic error(NOPCS); 13936559Sbostic runmode = CONTINUOUS; 14036559Sbostic execsig = oexpr() ? expv : signo; 14136559Sbostic break; 14236559Sbostic 14336559Sbostic default: 14436559Sbostic error(BADMOD); 14536578Storek /* NOTREACHED */ 14636559Sbostic } 14736559Sbostic 14836578Storek if (runcount > 0 && runpcs(runmode, execsig)) 14936559Sbostic adbprintf("breakpoint%16t"); 15036559Sbostic else 15136559Sbostic adbprintf("stopped at%16t"); 15236559Sbostic delbp(); 15336559Sbostic printpc(); 15436559Sbostic } 15536559Sbostic 15636559Sbostic /* 15736559Sbostic * Print all breakpoints. 15836559Sbostic */ 15936559Sbostic printbkpts() 16036559Sbostic { 16136559Sbostic register struct bkpt *b; 16236559Sbostic 16336559Sbostic adbprintf("breakpoints\ncount%8tbkpt%24tcommand\n"); 16436559Sbostic for (b = bkpthead; b != NULL; b = b->next) { 16536559Sbostic if (b->state != BKPT_FREE) { 16636559Sbostic adbprintf("%-8.8D", b->count); 16736559Sbostic psymoff("%R", b->loc, SP_INSTR, maxoff, "%24t"); 16836559Sbostic prints(b->comm); 16936559Sbostic } 17036559Sbostic } 17136559Sbostic } 17236559Sbostic 17336559Sbostic /* 17436559Sbostic * Remove (restore to original instruction(s)) all breakpoints. 17536559Sbostic */ 17636559Sbostic delbp() 17736559Sbostic { 17836559Sbostic register struct bkpt *b; 17936559Sbostic 18036559Sbostic if (bpstate != BPOUT) { 18136559Sbostic for (b = bkpthead; b != NULL; b = b->next) 18236559Sbostic if (b->state != BKPT_FREE && clr_bpt(b)) 18336559Sbostic bperr(b, "clear"); 18436559Sbostic bpstate = BPOUT; 18536559Sbostic } 18636559Sbostic } 18736559Sbostic 18836559Sbostic /* 18936559Sbostic * Insert all breakpoints. 19036559Sbostic */ 19136559Sbostic setbp() 19236559Sbostic { 19336559Sbostic register struct bkpt *b; 19436559Sbostic 19536559Sbostic if (bpstate != BPIN) { 19636559Sbostic for (b = bkpthead; b != NULL; b = b->next) 19736559Sbostic if (b->state != BKPT_FREE && set_bpt(b)) 19836559Sbostic bperr(b, "set"); 19936559Sbostic bpstate = BPIN; 20036559Sbostic } 20136559Sbostic } 20236559Sbostic 20336559Sbostic static 20436559Sbostic bperr(b, how) 20536559Sbostic struct bkpt *b; 20636559Sbostic char *how; 20736559Sbostic { 20836559Sbostic 20936559Sbostic adbprintf("cannot %s breakpoint: ", how); 21036559Sbostic psymoff("%R", b->loc, SP_INSTR, maxoff, "\n"); 21136559Sbostic } 21236559Sbostic 21336559Sbostic /* 21436679Storek * Run subprocess for a while. 21536679Storek * Return true iff stopped due to breakpoint. 21636559Sbostic */ 21736559Sbostic int 21836578Storek runpcs(runmode, execsig) 21936578Storek int runmode, execsig; 22036559Sbostic { 22136559Sbostic register struct bkpt *bkpt; 22236559Sbostic int rc; 22336559Sbostic 22436559Sbostic /* always set pc, so that expr>pc works too */ 22536578Storek setpc(gavedot ? dot : getpc()); 22636559Sbostic adbprintf("%s: running\n", symfile.name); 22736559Sbostic while (--runcount >= 0) { 22836559Sbostic /* BEGIN XXX (machine dependent?, delete ptrace, etc) */ 22936559Sbostic if (runmode == SINGLESTEP) 23036559Sbostic delbp(); /* hardware handles single-stepping */ 23136559Sbostic else { /* continuing from a breakpoint is hard */ 23236578Storek if ((bkpt = scanbkpt(getpc())) != NULL) { 23336559Sbostic execbkpt(bkpt, execsig); 23436559Sbostic execsig = 0; 23536559Sbostic } 23636559Sbostic setbp(); 23736559Sbostic } 23836559Sbostic (void) ptrace(runmode == CONTINUOUS ? PT_CONTINUE : PT_STEP, 23936578Storek pid, (int *)getpc(), execsig); 24036559Sbostic /* END XXX */ 24136679Storek 24236679Storek /* paranoia, SP_DATA usually sufficient, but this is easy */ 24336679Storek cacheinval(SP_INSTR | SP_DATA); 24436679Storek 24536559Sbostic bpwait(); 24636559Sbostic checkerr(); 24736559Sbostic execsig = 0; 24836559Sbostic delbp(); 24936559Sbostic readregs(); 25036559Sbostic 25136559Sbostic if (signo != 0 || (bkpt = scanbkpt(getpc())) == NULL) { 25236559Sbostic execsig = signo; 25336559Sbostic rc = 0; 25436559Sbostic continue; 25536559Sbostic } 25636559Sbostic /* stopped by BPT instruction */ 25736559Sbostic #ifdef DEBUG 25836559Sbostic adbprintf("\n BPT code: comm=%s%8tstate=%d", 25936559Sbostic bkpt->comm, bkpt->state); 26036559Sbostic #endif 26136559Sbostic dot = bkpt->loc; 26236559Sbostic switch (bkpt->state) { 26336559Sbostic char *p; 26436559Sbostic 26536559Sbostic case BKPT_SET: 26636559Sbostic bkpt->state = BKPT_TRIPPED; 26736559Sbostic if (*bkpt->comm == '\n') 26836559Sbostic break; 26936559Sbostic p = lp; 27036559Sbostic command(bkpt->comm, ':'); 27136559Sbostic lp = p; 27236559Sbostic if (gavedot && edot == 0) /* maybe dot==0 ??? */ 27336559Sbostic break; 27436559Sbostic if (--bkpt->count == 0) 27536559Sbostic break; 27636559Sbostic /* FALLTHROUGH */ 27736559Sbostic 27836559Sbostic case BKPT_TRIPPED: 27936559Sbostic execbkpt(bkpt, execsig); 28036559Sbostic execsig = 0; 28136559Sbostic runcount++; 28236559Sbostic continue; 28336559Sbostic 28436559Sbostic default: 28536559Sbostic panic("runpcs"); 28636559Sbostic /* NOTREACHED */ 28736559Sbostic } 28836559Sbostic bkpt->count = bkpt->initcnt; 28936559Sbostic rc = 1; 29036559Sbostic } 29136559Sbostic return (rc); 29236559Sbostic } 29336559Sbostic 29436559Sbostic endpcs() 29536559Sbostic { 29636559Sbostic register struct bkpt *bp; 29736559Sbostic 29836559Sbostic if (pid) { 29936559Sbostic (void) ptrace(PT_KILL, pid, (int *)0, 0); /* XXX */ 30036559Sbostic pid = 0; 30136559Sbostic for (bp = bkpthead; bp != NULL; bp = bp->next) 30236559Sbostic if (bp->state != BKPT_FREE) 30336559Sbostic bp->state = BKPT_SET; 30436559Sbostic } 30536559Sbostic bpstate = BPOUT; 30636559Sbostic } 30736559Sbostic 30836559Sbostic #ifdef VFORK 30936559Sbostic nullsig() 31036559Sbostic { 31136559Sbostic 31236559Sbostic } 31336559Sbostic #endif 31436559Sbostic 31536559Sbostic setup() 31636559Sbostic { 31736559Sbostic 31836679Storek cacheinval(SP_INSTR | SP_DATA); /* paranoia */ 31936559Sbostic (void) close(symfile.fd); 32036559Sbostic symfile.fd = -1; 32136559Sbostic #ifndef VFORK 32236559Sbostic #define vfork fork 32336559Sbostic #endif 32436559Sbostic if ((pid = vfork()) == 0) { 32536559Sbostic (void) ptrace(PT_TRACE_ME, 0, (int *)0, 0); /* XXX */ 32636559Sbostic #ifdef VFORK 32736559Sbostic (void) signal(SIGTRAP, nullsig); 32836559Sbostic #endif 32936559Sbostic (void) signal(SIGINT, sigint); 33036559Sbostic (void) signal(SIGQUIT, sigquit); 33136559Sbostic doexec(); 33236559Sbostic exit(0); 33336679Storek } else if (pid == -1) { 33436679Storek pid = 0; 33536559Sbostic error(NOFORK); 33636679Storek } else { 33736559Sbostic bpwait(); 33836559Sbostic readregs(); 33936559Sbostic symfile.fd = open(symfile.name, wtflag); 34036559Sbostic if (errflag) { 34136559Sbostic adbprintf("%s: cannot execute\n", symfile.name); 34236559Sbostic endpcs(); 34336559Sbostic error((char *)0); 34436559Sbostic } 34536559Sbostic } 34636559Sbostic bpstate = BPOUT; 34736559Sbostic } 34836559Sbostic 349*37336Storek /* 350*37336Storek * Single step over a location containing a breakpoint. 351*37336Storek */ 35236559Sbostic execbkpt(bp, execsig) 35336559Sbostic struct bkpt *bp; 35436559Sbostic int execsig; 35536559Sbostic { 35636559Sbostic 35736559Sbostic #ifdef DEBUG 35836559Sbostic adbprintf("exbkpt: %d\n", bp->count); 35936559Sbostic #endif 36036559Sbostic delbp(); 36136559Sbostic (void) ptrace(PT_STEP, pid, (int *)bp->loc, execsig); /* XXX */ 36236559Sbostic bp->state = BKPT_SET; 36336559Sbostic bpwait(); 36436559Sbostic checkerr(); 36536559Sbostic readregs(); 36636559Sbostic } 36736559Sbostic 36836559Sbostic static char separators[] = "<> \t\n"; 36936559Sbostic 37036559Sbostic doexec() 37136559Sbostic { 37236559Sbostic register char *p, **ap; 37336559Sbostic register int c; 37436559Sbostic char *argl[LINELEN / 2 + 1]; 37536559Sbostic char args[LINELEN]; 37636559Sbostic extern char **environ; 37736559Sbostic char *index(); 37836559Sbostic 37936559Sbostic ap = argl; 38036559Sbostic p = args; 38136559Sbostic *ap++ = symfile.name; 38236559Sbostic do { 38336559Sbostic switch (c = rdc()) { 38436559Sbostic 38536559Sbostic case '\n': 38636559Sbostic break; 38736559Sbostic 38836559Sbostic case '<': 38936559Sbostic setfile(0, O_RDONLY, 0, p, "open"); 39036559Sbostic break; 39136559Sbostic 39236559Sbostic case '>': 39336559Sbostic setfile(1, O_CREAT|O_WRONLY, 0666, p, "create"); 39436559Sbostic break; 39536559Sbostic 39636559Sbostic default: 39736559Sbostic *ap = p; 39836559Sbostic while (index(separators, c) == NULL) { 39936559Sbostic *p++ = c; 40036559Sbostic c = readchar(); 40136559Sbostic } 40236559Sbostic *p++ = '\0'; 40336559Sbostic ap++; 40436559Sbostic } 40536559Sbostic } while (c != '\n'); 40636559Sbostic unreadc(); 40736559Sbostic *ap++ = 0; 40836578Storek execve(symfile.name, argl, environ); 40936559Sbostic perror(symfile.name); 41036559Sbostic } 41136559Sbostic 41236559Sbostic static int 41336559Sbostic setfile(fd, flags, mode, namebuf, err) 41436559Sbostic int fd, flags, mode; 41536559Sbostic char *namebuf, *err; 41636559Sbostic { 41736559Sbostic register char *p = namebuf; 41836559Sbostic register int c = rdc(); 41936559Sbostic 42036559Sbostic while (index(separators, c) == NULL) { 42136559Sbostic *p++ = c; 42236559Sbostic c = readchar(); 42336559Sbostic } 42436559Sbostic *p = 0; 42536559Sbostic (void) close(fd); 42636559Sbostic if (open(namebuf, flags, mode) < 0) { 42736559Sbostic adbprintf("%s: cannot %s\n", namebuf, err); 42836559Sbostic _exit(0); 42936559Sbostic /* NOTREACHED */ 43036559Sbostic } 43136559Sbostic } 43236559Sbostic 43336559Sbostic struct bkpt * 43436559Sbostic scanbkpt(a) 43536559Sbostic register addr_t a; 43636559Sbostic { 43736559Sbostic register struct bkpt *bp; 43836559Sbostic 43936559Sbostic for (bp = bkpthead; bp != NULL; bp = bp->next) 44036559Sbostic if (bp->state != BKPT_FREE && bp->loc == a) 44136559Sbostic break; 44236559Sbostic return (bp); 44336559Sbostic } 44436559Sbostic 44536559Sbostic bpwait() 44636559Sbostic { 44736559Sbostic register int w; 44836559Sbostic union wait status; 44936559Sbostic 45036559Sbostic (void) signal(SIGINT, SIG_IGN); 45136559Sbostic while ((w = wait(&status)) != pid && w != -1) 45236559Sbostic /* void */ ; 45336559Sbostic (void) signal(SIGINT, intcatch); 45436559Sbostic if (w == -1) { 45536559Sbostic pid = 0; 45636559Sbostic errflag = BADWAIT; 45736559Sbostic } else if (!WIFSTOPPED(status)) { 45836559Sbostic sigcode = 0; 45936559Sbostic if ((signo = status.w_termsig) != 0) 46036559Sbostic sigprint(); 46136559Sbostic if (status.w_coredump) { 46236559Sbostic prints(" - core dumped"); 46336559Sbostic (void) close(corefile.fd); 46436559Sbostic setcore(); 46536559Sbostic } 46636559Sbostic pid = 0; 46736559Sbostic bpstate = BPOUT; 46836559Sbostic errflag = ENDPCS; 46936559Sbostic } else { 47036559Sbostic signo = status.w_stopsig; 47136559Sbostic sigcode = ptrace(PT_READ_U, pid, 47236559Sbostic &((struct user *)0)->u_code, 0); /* XXX */ 47336559Sbostic if (signo != SIGTRAP) 47436559Sbostic sigprint(); 47536559Sbostic else 47636559Sbostic signo = 0; 47736559Sbostic flushbuf(); 47836559Sbostic } 47936559Sbostic } 480