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