1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)ptrace.c	5.4 (Berkeley) 10/30/90";
9 #endif not lint
10 
11 /*
12  * routines for tracing the execution of a process
13  *
14  * The system call "ptrace" does all the work, these
15  * routines just try to interface easily to it.
16  */
17 
18 #include "defs.h"
19 #include <signal.h>
20 #include <sys/param.h>
21 #include <machine/reg.h>
22 #include "process.h"
23 #include "object.h"
24 #include "process.rep"
25 
26 #       include "pxinfo.h"
27 
28 #ifdef mc68000
29 #	define U_PAGE 0x2400
30 #	define U_AR0  (14*sizeof(int))
31 	LOCAL int ar0val = -1;
32 #endif
33 
34 /*
35  * This magic macro enables us to look at the process' registers
36  * in its user structure.  Very gross.
37  */
38 
39 #if defined(vax) || defined(tahoe)
40 #	define regloc(reg)     (ctob(UPAGES) + ( sizeof(int) * (reg) ))
41 #else
42 #	define regloc(reg)     (ar0val + ( sizeof(int) * (reg) ))
43 #endif
44 
45 #define WMASK           (~(sizeof(WORD) - 1))
46 #define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE))
47 
48 #define ischild(pid)    ((pid) == 0)
49 #define traceme()       ptrace(0, 0, 0, 0)
50 #define setrep(n)       (1 << ((n)-1))
51 #define istraced(p)     (p->sigset&setrep(p->signo))
52 
53 /*
54  * ptrace options (specified in first argument)
55  */
56 
57 #define UREAD   3       /* read from process's user structure */
58 #define UWRITE  6       /* write to process's user structure */
59 #define IREAD   1       /* read from process's instruction space */
60 #define IWRITE  4       /* write to process's instruction space */
61 #define DREAD   2       /* read from process's data space */
62 #define DWRITE  5       /* write to process's data space */
63 #define CONT    7       /* continue stopped process */
64 #define SSTEP   9       /* continue for approximately one instruction */
65 #define PKILL   8       /* terminate the process */
66 
67 /*
68  * Start up a new process by forking and exec-ing the
69  * given argument list, returning when the process is loaded
70  * and ready to execute.  The PROCESS information (pointed to
71  * by the first argument) is appropriately filled.
72  *
73  * If the given PROCESS structure is associated with an already running
74  * process, we terminate it.
75  */
76 
77 /* VARARGS2 */
78 pstart(p, cmd, argv, infile, outfile)
79 PROCESS *p;
80 char *cmd;
81 char **argv;
82 char *infile;
83 char *outfile;
84 {
85     int status;
86     FILE *in, *out;
87 
88     if (p->pid != 0) {                  /* child already running? */
89 	ptrace(PKILL, p->pid, 0, 0);    /* ... kill it! */
90     }
91 #ifdef tahoe
92     INTFP = (ADDRESS)0;
93 #endif tahoe
94     psigtrace(p, SIGTRAP, TRUE);
95     if ((p->pid = fork()) == -1) {
96 	panic("can't fork");
97     }
98     if (ischild(p->pid)) {
99 	traceme();
100 	if (infile != NIL) {
101 	    if ((in = fopen(infile, "r")) == NIL) {
102 		printf("can't read %s\n", infile);
103 		exit(1);
104 	    }
105 	    fswap(0, fileno(in));
106 	}
107 	if (outfile != NIL) {
108 	    if ((out = fopen(outfile, "w")) == NIL) {
109 		printf("can't write %s\n", outfile);
110 		exit(1);
111 	    }
112 	    fswap(1, fileno(out));
113 	}
114 	execvp(cmd, argv);
115 	panic("can't exec %s", argv[0]);
116     }
117     pwait(p->pid, &status);
118     getinfo(p, status);
119 }
120 
121 /*
122  * Continue a stopped process.  The argument points to a PROCESS structure.
123  * Before the process is restarted it's user area is modified according to
124  * the values in the structure.  When this routine finishes,
125  * the structure has the new values from the process's user area.
126  *
127  * Pcont terminates when the process stops with a signal pending that
128  * is being traced (via psigtrace), or when the process terminates.
129  */
130 
131 pcont(p)
132 PROCESS *p;
133 {
134     int status;
135 
136     if (p->pid == 0) {
137 	error("program not active");
138     }
139     do {
140 	setinfo(p);
141 	sigs_off();
142 	if (ptrace(CONT, p->pid, p->pc, p->signo) < 0) {
143 	    panic("can't continue process");
144 	}
145 	pwait(p->pid, &status);
146 	sigs_on();
147 	getinfo(p, status);
148     } while (p->status == STOPPED && !istraced(p));
149 }
150 
151 /*
152  * single step as best ptrace can
153  */
154 
155 pstep(p)
156 PROCESS *p;
157 {
158     int status;
159 
160     setinfo(p);
161     sigs_off();
162     ptrace(SSTEP, p->pid, p->pc, p->signo);
163     pwait(p->pid, &status);
164     sigs_on();
165     getinfo(p, status);
166 }
167 
168 /*
169  * Return from execution when the given signal is pending.
170  */
171 
172 psigtrace(p, sig, sw)
173 PROCESS *p;
174 int sig;
175 int sw;
176 {
177     if (sw) {
178 	p->sigset |= setrep(sig);
179     } else {
180 	p->sigset &= ~setrep(sig);
181     }
182 }
183 
184 /*
185  * Don't catch any signals.
186  * Particularly useful when letting a process finish uninhibited (i.e. px).
187  */
188 
189 unsetsigtraces(p)
190 PROCESS *p;
191 {
192     p->sigset = 0;
193 }
194 
195 /*
196  * turn off attention to signals not being caught
197  */
198 
199 LOCAL void *onintr, *onquit;
200 
201 LOCAL sigs_off()
202 {
203     onintr = signal(SIGINT, SIG_IGN);
204     onquit = signal(SIGQUIT, SIG_IGN);
205 }
206 
207 /*
208  * turn back on attention to signals
209  */
210 
211 LOCAL sigs_on()
212 {
213     (void) signal(SIGINT, onintr);
214     (void) signal(SIGQUIT, onquit);
215 }
216 
217 /*
218  * get PROCESS information from process's user area
219  */
220 
221 #if vax
222     LOCAL int rloc[] ={
223 	R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11,
224     };
225 #endif
226 #if tahoe
227     LOCAL int rloc[] ={
228 	R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12,
229     };
230 #endif
231 #if mc68000
232     LOCAL int rloc[] ={
233 	R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5,
234     };
235 #endif
236 
237 LOCAL getinfo(p, status)
238 register PROCESS *p;
239 register int status;
240 {
241     register int i;
242 
243     p->signo = (status&0177);
244     p->exitval = ((status >> 8)&0377);
245     if (p->signo == STOPPED) {
246 	p->status = p->signo;
247 	p->signo = p->exitval;
248 	p->exitval = 0;
249     } else {
250 	p->status = FINISHED;
251 	return;
252     }
253 #if !defined(vax) && !defined(tahoe)
254     if (ar0val < 0){
255 	ar0val = ptrace(UREAD, p->pid, U_AR0, 0);
256 	ar0val -= U_PAGE;
257     }
258 #endif
259     for (i = 0; i < NREG; i++) {
260 	p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0);
261 	p->oreg[i] = p->reg[i];
262     }
263 #if defined(vax) || defined(tahoe)
264     p->fp = p->ofp = ptrace(UREAD, p->pid, regloc(FP), 0);
265     p->sp = p->osp = ptrace(UREAD, p->pid, regloc(SP), 0);
266     p->pc = p->opc = ptrace(UREAD, p->pid, regloc(PC), 0);
267 #endif
268 #ifdef vax
269     p->ap = p->oap = ptrace(UREAD, p->pid, regloc(AP), 0);
270 #endif
271 #ifdef mc68000
272     p->fp = p->ofp = ptrace(UREAD, p->pid, regloc(AR6), 0);
273     p->ap = p->oap = p->fp;
274     p->sp = p->osp = ptrace(UREAD, p->pid, regloc(SP), 0);
275     p->pc = p->opc = ptrace(UREAD, p->pid, regloc(PC), 0);
276 #endif
277 }
278 
279 /*
280  * set process's user area information from given PROCESS structure
281  */
282 
283 LOCAL setinfo(p)
284 register PROCESS *p;
285 {
286     register int i;
287     register int r;
288 
289     if (istraced(p)) {
290 	p->signo = 0;
291     }
292     for (i = 0; i < NREG; i++) {
293 	if ((r = p->reg[i]) != p->oreg[i]) {
294 	    ptrace(UWRITE, p->pid, regloc(rloc[i]), r);
295 	}
296     }
297 #if vax || tahoe
298     if ((r = p->fp) != p->ofp) {
299 	ptrace(UWRITE, p->pid, regloc(FP), r);
300     }
301 #endif
302 #if vax
303     if ((r = p->ap) != p->oap) {
304 	ptrace(UWRITE, p->pid, regloc(AP), r);
305     }
306 #endif
307 #if mc68000
308     if ((r = p->fp) != p->ofp) {
309 	ptrace(UWRITE, p->pid, regloc(AR6), r);
310     }
311 #endif
312     if ((r = p->sp) != p->osp) {
313 	ptrace(UWRITE, p->pid, regloc(SP), r);
314     }
315     if ((r = p->pc) != p->opc) {
316 	ptrace(UWRITE, p->pid, regloc(PC), r);
317     }
318 }
319 
320 /*
321  * Structure for reading and writing by words, but dealing with bytes.
322  */
323 
324 typedef union {
325     WORD pword;
326     BYTE pbyte[sizeof(WORD)];
327 } PWORD;
328 
329 /*
330  * Read (write) from (to) the process' address space.
331  * We must deal with ptrace's inability to look anywhere other
332  * than at a word boundary.
333  */
334 
335 LOCAL WORD fetch();
336 LOCAL store();
337 
338 pio(p, op, seg, buff, addr, nbytes)
339 PROCESS *p;
340 PIO_OP op;
341 PIO_SEG seg;
342 char *buff;
343 ADDRESS addr;
344 int nbytes;
345 {
346     register int i, k;
347     register ADDRESS newaddr;
348     register char *cp;
349     char *bufend;
350     PWORD w;
351     ADDRESS wordaddr;
352     int byteoff;
353 
354     if (p->status != STOPPED) {
355 	error("program is not active");
356     }
357     cp = buff;
358     newaddr = addr;
359     wordaddr = (newaddr&WMASK);
360     if (wordaddr != newaddr) {
361 	w.pword = fetch(p, seg, wordaddr);
362 	for (i = newaddr - wordaddr; i<sizeof(WORD) && nbytes>0; i++) {
363 	    if (op == PREAD) {
364 		*cp++ = w.pbyte[i];
365 	    } else {
366 		w.pbyte[i] = *cp++;
367 	    }
368 	    nbytes--;
369 	}
370 	if (op == PWRITE) {
371 	    store(p, seg, wordaddr, w.pword);
372 	}
373 	newaddr = wordaddr + sizeof(WORD);
374     }
375     byteoff = (nbytes&(~WMASK));
376     nbytes -= byteoff;
377     bufend = cp + nbytes;
378     while (cp < bufend) {
379 	if (op == PREAD) {
380 	    w.pword = fetch(p, seg, newaddr);
381 	    for (k = 0; k < sizeof(WORD); k++) {
382 		*cp++ = w.pbyte[k];
383 	    }
384 	} else {
385 	    for (k = 0; k < sizeof(WORD); k++) {
386 		w.pbyte[k] = *cp++;
387 	    }
388 	    store(p, seg, newaddr, w.pword);
389 	}
390 	newaddr += sizeof(WORD);
391     }
392     if (byteoff > 0) {
393 	w.pword = fetch(p, seg, newaddr);
394 	for (i = 0; i < byteoff; i++) {
395 	    if (op == PREAD) {
396 		*cp++ = w.pbyte[i];
397 	    } else {
398 		w.pbyte[i] = *cp++;
399 	    }
400 	}
401 	if (op == PWRITE) {
402 	    store(p, seg, newaddr, w.pword);
403 	}
404     }
405 }
406 
407 /*
408  * Get a word from a process at the given address.
409  * The address is assumed to be on a word boundary.
410  *
411  * We use a simple cache scheme to avoid redundant references to
412  * the instruction space (which is assumed to be pure).  In the
413  * case of px, the "instruction" space lies between ENDOFF and
414  * ENDOFF + objsize.
415  *
416  * It is necessary to use a write-through scheme so that
417  * breakpoints right next to each other don't interfere.
418  */
419 
420 LOCAL WORD fetch(p, seg, addr)
421 PROCESS *p;
422 PIO_SEG seg;
423 register int addr;
424 {
425     register CACHEWORD *wp;
426     register WORD w;
427 
428     switch (seg) {
429 	case TEXTSEG:
430 	    panic("tried to fetch from px i-space");
431 	    /* NOTREACHED */
432 
433 	case DATASEG:
434 	    if (addr >= ENDOFF && addr < ENDOFF + objsize) {
435 		wp = &p->word[cachehash(addr)];
436 		if (addr == 0 || wp->addr != addr) {
437 		    w = ptrace(DREAD, p->pid, addr, 0);
438 		    wp->addr = addr;
439 		    wp->val = w;
440 		} else {
441 		    w = wp->val;
442 		}
443 	    } else {
444 		w = ptrace(DREAD, p->pid, addr, 0);
445 	    }
446 	    break;
447 
448 	default:
449 	    panic("fetch: bad seg %d", seg);
450 	    /* NOTREACHED */
451     }
452     return(w);
453 }
454 
455 /*
456  * Put a word into the process' address space at the given address.
457  * The address is assumed to be on a word boundary.
458  */
459 
460 LOCAL store(p, seg, addr, data)
461 PROCESS *p;
462 PIO_SEG seg;
463 int addr;
464 WORD data;
465 {
466     register CACHEWORD *wp;
467 
468     switch (seg) {
469 	case TEXTSEG:
470 	    wp = &p->word[cachehash(addr)];
471 	    wp->addr = addr;
472 	    wp->val = data;
473 	    ptrace(IWRITE, p->pid, addr, data);
474 	    break;
475 
476 	case DATASEG:
477 	    if (addr >= ENDOFF && addr < ENDOFF + objsize) {
478 		wp = &p->word[cachehash(addr)];
479 		wp->addr = addr;
480 		wp->val = data;
481 	    }
482 	    ptrace(DWRITE, p->pid, addr, data);
483 	    break;
484 
485 	default:
486 	    panic("store: bad seg %d", seg);
487 	    /*NOTREACHED*/
488     }
489 }
490 
491 /*
492  * Initialize the instruction cache for a process.
493  * This is particularly necessary after the program has been remade.
494  */
495 
496 initcache(process)
497 PROCESS *process;
498 {
499     register int i;
500 
501     for (i = 0; i < CSIZE; i++) {
502 	process->word[i].addr = 0;
503     }
504 }
505 
506 /*
507  * Swap file numbers so as to redirect standard input and output.
508  */
509 
510 LOCAL fswap(oldfd, newfd)
511 int oldfd;
512 int newfd;
513 {
514     if (oldfd != newfd) {
515 	close(oldfd);
516 	dup(newfd);
517 	close(newfd);
518     }
519 }
520 
521 #ifdef tahoe
522 BOOLEAN didret;
523 
524 void
525 chkret(p, status)
526 PROCESS *p;
527 int status;
528 {
529 	if (((status == (SIGILL << 8) | STOPPED) ||
530 	    (status == (SIGTRAP << 8) | STOPPED))) {
531 		didret = FALSE;
532 	} else {
533 		didret = TRUE;
534 	}
535 }
536 
537 void
538 doret(p)
539 PROCESS *p;
540 {
541 	register count = 0;
542 
543 	if (!didret) {
544 	    do {
545 		if (++count > 5) {
546 		    panic("px would not return to interpreter");
547 		}
548 		p->pc = RETLOC;
549 		pstep(p);
550 	    } while(INTFP && p->fp != INTFP);
551 	    didret = TRUE;
552 	}
553 }
554 #endif
555