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