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