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