|
|
1.1 root 1: /*
2: * db/db8.c
3: * A debugger.
4: * Child process.
5: * All the machine-independent ptrace() code is here.
6: */
7:
8: #include <errno.h>
9: #include <signal.h>
10: #include <sys/param.h>
11: #include <sys/ptrace.h>
12: #include "db.h"
13:
14: /*
15: * Read 'n' characters starting at address 'a' into the buffer 'bp'
16: * from segment 'f' in the child process.
17: * Return 1 on success, 0 on failure.
18: */
19: int
20: getp(f, a, bp, n) int f; ADDR_T a; register char *bp; register int n;
21: {
22: int d, n1, pcmd;
23:
24: /* Set pcmd to the appropriate ptrace() read command. */
25: switch(f) {
26: case ISEG: pcmd = PTRACE_RD_TXT; break;
27: case DSEG: pcmd = PTRACE_RD_DAT; break;
28: case USEG: pcmd = PTRACE_RD_USR; break;
29: }
30:
31: /* Read in PTSIZE-sized chunks. */
32: for (errno = 0; n != 0; n -= n1, a += n1, bp += n1) {
33: n1 = (n > PTSIZE) ? PTSIZE : n;
34: d = ptrace(pcmd, pid, (int)a, 0);
35: if (errno)
36: return 0;
37: memcpy(bp, &d, n1);
38: }
39: return 1;
40: }
41:
42: /*
43: * Infanticide.
44: */
45: void
46: killc()
47: {
48: reg_flag = R_INVALID;
49: if (execflag) {
50: ptrace(PTRACE_TERM, pid, 0, 0);
51: waitc();
52: execflag = 0;
53: }
54: #if 0
55: trapstr = NULL;
56: #endif
57: }
58:
59: /*
60: * Write 'n' characters from the buffer 'bp'
61: * to segment 'f' in the child process starting at address 'a'.
62: * Return 1 on success, 0 on failure.
63: */
64: int
65: putp(f, a, bp, n) int f; ADDR_T a; register char *bp; register int n;
66: {
67: int d, n1, pcmd, prcmd;
68:
69: /* Set pcmd to the appropriate ptrace() write command. */
70: switch(f) {
71: case ISEG: pcmd = PTRACE_WR_TXT; break;
72: case DSEG: pcmd = PTRACE_WR_DAT; break;
73: case USEG: pcmd = PTRACE_WR_USR; break;
74: }
75: for (errno = 0; n != 0; n -= n1, a += n1, bp += n1) {
76: if (n < PTSIZE) {
77: /* Read first so write can leave extra bytes unchanged. */
78: n1 = n;
79: switch(f) {
80: case ISEG: prcmd = PTRACE_RD_TXT; break;
81: case DSEG: prcmd = PTRACE_RD_DAT; break;
82: case USEG: prcmd = PTRACE_RD_USR; break;
83: }
84: d = ptrace(prcmd, pid, (int)a, 0);
85: } else
86: n1 = PTSIZE;
87: memcpy(&d, bp, n1);
88: ptrace(pcmd, pid, (int)a, d);
89: if (errno) {
90: perror("putp()");
91: return 0;
92: }
93: }
94: return 1;
95: }
96:
97: /*
98: * Run the child and wait for it to stop.
99: * Return 0 on error.
100: */
101: int
102: runc()
103: {
104: register int pcmd;
105:
106: switch (step_mode) {
107: case SNULL:
108: case SWAIT:
109: pcmd = PTRACE_RESUME;
110: break;
111: case SCALL:
112: case SCONT:
113: case SSTEP:
114: pcmd = PTRACE_SSTEP;
115: break;
116: default:
117: panic("invalid step_mode=%d", step_mode);
118: }
119: errno = 0;
120: reg_flag = R_INVALID;
121: ptrace(pcmd, pid, 1, 0);
122: if (errno) {
123: perror("ptrace");
124: return 0;
125: }
126: if (waitc() == 0)
127: return 0;
128: get_regs(R_SOME);
129: return 1;
130: }
131:
132: /*
133: * Start execution of the child.
134: * 'argv' is the argument list,
135: * 'ifn' is the name of the input file,
136: * 'ofn' is the name of the output file, and
137: * 'aflag' tells us whether the output file is opened for append or write.
138: */
139: int
140: startc(argv, ifn, ofn, aflag) char **argv; char *ifn; char *ofn; int aflag;
141: {
142: register int n;
143:
144: reg_flag = R_INVALID;
145: if ((pid = fork()) < 0)
146: return printr("Cannot fork");
147: if (pid == 0) {
148: /* Child process. */
149: if (ifn != NULL) {
150: if ((n=open(ifn, 0)) < 0)
151: panic("Cannot open \"%s\"", ifn);
152: dup2(n, 0);
153: close(n);
154: }
155: if (ofn != NULL) {
156: n = -1;
157: if (aflag) {
158: if ((n = open(ofn, 1)) >= 0)
159: lseek(n, 0L, SEEK_END);
160: }
161: if (n < 0) {
162: if ((n=creat(ofn, 0644)) < 0)
163: panic("%s: cannot create", ofn);
164: }
165: dup2(n, 1);
166: close(n);
167: }
168: ptrace(PTRACE_SETUP, 0, 0, 0); /* I hear you, Dad... */
169: execv(lfn, argv);
170: exit(1);
171: }
172: /* Parent process. */
173: if (waitc() == 0)
174: return 0;
175:
176: /*
177: * Now the child is running, so map the child process rather
178: * than the disk file.
179: * FIX_ME The map addresses for DSEG and ISEG here are bogus.
180: */
181: map_init();
182: map_set(DSEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_CHILD);
183: map_set(ISEG, MIN_ADDR, MAX_ADDR, (off_t)0, MAP_CHILD);
184: map_set(USEG, MIN_ADDR, (ADDR_T)UPASIZE, (off_t)0, MAP_CHILD);
185: execflag = 1;
186: get_regs(R_SOME);
187: return 1;
188: }
189:
190: /*
191: * Wait for the child to stop.
192: */
193: int
194: waitc()
195: {
196: register int p;
197: int s;
198:
199: while ((p = wait(&s)) != pid) {
200: if (p >= 0) {
201: printr("Adopted a child %d", p);
202: continue;
203: }
204: if (intflag == 0) {
205: execflag = 0;
206: return printr("Nonexistent child");
207: }
208: intflag = 0;
209: }
210: if ((s & 0xff) != 0x7f) {
211: execflag = 0;
212: return printr("Child process terminated (0x%X)", (s >> 8) & 0xFF );
213: }
214: return 1;
215: }
216:
217: #if DBPTRACE
218: #undef ptrace
219: int
220: dbptrace(cmd, pid, loc, val) int cmd, pid, loc, val;
221: {
222: register int n;
223:
224: printf("ptrace(%d, %d, 0x%X, 0x%X) = ", cmd, pid, loc, val);
225: n = ptrace(cmd, pid, loc, val);
226: printf("0x%X\n", n);
227: return n;
228: }
229: #endif
230:
231: /* end of db/db8.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.