1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)ptrace.c 1.2 01/23/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  * Swap file numbers so as to redirect standard input and output.
466  */
467 
468 LOCAL fswap(oldfd, newfd)
469 int oldfd;
470 int newfd;
471 {
472 	if (oldfd != newfd) {
473 		close(oldfd);
474 		dup(newfd);
475 		close(newfd);
476 	}
477 }
478