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