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 */
pstart(p,cmd,argv,infile,outfile)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
pcont(p)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
pstep(p)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
psigtrace(p,sig,sw)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
unsetsigtraces(p)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
sigs_off()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
sigs_on()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
getinfo(p,status)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
setinfo(p)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
pio(p,op,seg,buff,addr,nbytes)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
fetch(p,seg,addr)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
store(p,seg,addr,data)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
initcache(process)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
fswap(oldfd,newfd)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
chkret(p,status)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
doret(p)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