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