xref: /csrg-svn/old/adb/common_source/pcs.c (revision 36559)
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