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