xref: /csrg-svn/old/adb/common_source/pcs.c (revision 36559)
1 #ifndef lint
2 static char sccsid[] = "@(#)pcs.c	5.1 (Berkeley) 01/16/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 			runcount--;
134 			execsig = 0;
135 		}
136 		break;
137 
138 	case 'c':
139 	case 'C':
140 	case 0:
141 		/* continue with optional signal */
142 		runcount = ecount;
143 		if (pid == 0)
144 			error(NOPCS);
145 		runmode = CONTINUOUS;
146 		execsig = oexpr() ? expv : signo;
147 		break;
148 
149 	default:
150 		error(BADMOD);
151 	}
152 
153 	if (runcount > 0 && runpcs(runmode & ~NEW, execsig, runmode & NEW))
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  * ... return true iff stopped due to breakpoint
220  */
221 int
222 runpcs(runmode, execsig, newproc)
223 	int runmode, execsig, newproc;
224 {
225 	register struct bkpt *bkpt;
226 	int rc;
227 
228 	/* always set pc, so that expr>pc works too */
229 	setpc(gavedot ? dot : newproc ? entrypc() : getpc());
230 	adbprintf("%s: running\n", symfile.name);
231 	while (--runcount >= 0) {
232 #ifdef DEBUG
233 		adbprintf("\n%s @ %X sig %D\n",
234 			newproc ? "start" : "continue",
235 			getpc(), execsig);		/* XXX */
236 #endif
237 		/* BEGIN XXX (machine dependent?, delete ptrace, etc) */
238 		if (runmode == SINGLESTEP)
239 			delbp();	/* hardware handles single-stepping */
240 		else {	/* continuing from a breakpoint is hard */
241 			if (!newproc && (bkpt = scanbkpt(getpc())) != NULL) {
242 				execbkpt(bkpt, execsig);
243 				execsig = 0;
244 			}
245 			setbp();
246 		}
247 		(void) ptrace(runmode == CONTINUOUS ? PT_CONTINUE : PT_STEP,
248 			pid, (int *)(newproc ? 1 : getpc()), execsig);
249 		/* END XXX */
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 	(void) close(symfile.fd);
324 	symfile.fd = -1;
325 #ifndef VFORK
326 #define vfork fork
327 #endif
328 	if ((pid = vfork()) == 0) {
329 		(void) ptrace(PT_TRACE_ME, 0, (int *)0, 0);	/* XXX */
330 #ifdef VFORK
331 		(void) signal(SIGTRAP, nullsig);
332 #endif
333 		(void) signal(SIGINT, sigint);
334 		(void) signal(SIGQUIT, sigquit);
335 		doexec();
336 		exit(0);
337 	} else if (pid == -1)
338 		error(NOFORK);
339 	else {
340 		bpwait();
341 		readregs();
342 		symfile.fd = open(symfile.name, wtflag);
343 		if (errflag) {
344 			adbprintf("%s: cannot execute\n", symfile.name);
345 			endpcs();
346 			error((char *)0);
347 		}
348 	}
349 	bpstate = BPOUT;
350 }
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 	exect(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