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