|
|
1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.