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