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