|
|
1.1 root 1: /*
2:
3: * sample program for demonstrating the debugging calls
4:
5: * Written by Alex Kiernan
6:
7: */
8:
9:
10:
11: #include <mintbind.h>
12:
13: #include <stddef.h>
14:
15:
16:
17: typedef struct _context {
18:
19: long regs[15]; /* registers d0-d7, a0-a6 */
20:
21: long usp; /* user stack pointer (a7) */
22:
23: short sr; /* status register */
24:
25: long pc; /* program counter */
26:
27: long ssp; /* supervisor stack pointer */
28:
29: long term_vec; /* GEMDOS terminate vector (0x102) */
30:
31: /*
32:
33: * AGK: if running on a TT and the user is playing with the FPU then we
34:
35: * must save and restore the context. We should also consider this for
36:
37: * I/O based co-processors, although this may be difficult due to
38:
39: * possibility of a context switch in the middle of an I/O handshaking
40:
41: * exchange.
42:
43: */
44:
45: unsigned char fstate[216]; /* FPU internal state */
46:
47: long fregs[3*8]; /* registers fp0-fp7 */
48:
49: long fctrl[3]; /* FPCR/FPSR/FPIAR */
50:
51: /*
52:
53: * AGK: for long (time-wise) co-processor instructions (FMUL etc.), the
54:
55: * FPU returns NULL, come-again with interrupts allowed primitives. It
56:
57: * is highly likely that a context switch will occur in one of these if
58:
59: * running a mathematically intensive application, hence we must handle
60:
61: * the mid-instruction interrupt stack. We do this by saving the extra
62:
63: * 3 long words and the stack format word here.
64:
65: */
66:
67: unsigned short sfmt; /* stack frame format identifier */
68:
69: short internal[42]; /* internal state -- see framesizes[] for size */
70:
71: char ptrace; /* trace exception is pending */
72:
73: } CONTEXT;
74:
75:
76:
77: #define PPROCADDR (('P'<< 8) | 1)
78:
79: #define PBASEADDR (('P'<< 8) | 2)
80:
81: #define PCTXTSIZE (('P'<< 8) | 3)
82:
83: #define PSETFLAGS (('P'<< 8) | 4)
84:
85: #define PGETFLAGS (('P'<< 8) | 5)
86:
87: #define PTRACESFLAGS (('P'<< 8) | 6)
88:
89: #define PTRACEGFLAGS (('P'<< 8) | 7)
90:
91: # define P_ENABLE (1 << 0) /* enable tracing */
92:
93: #ifdef NOTYETDEFINED
94:
95: # define P_DOS (1 << 1) /* trace DOS calls - unimplemented */
96:
97: # define P_BIOS (1 << 2) /* trace BIOS calls - unimplemented */
98:
99: # define P_XBIOS (1 << 3) /* trace XBIOS calls - unimplemented */
100:
101: #endif
102:
103:
104:
105: #define PTRACEGO (('P'<< 8) | 8) /* these 4 must be together */
106:
107: #define PTRACEFLOW (('P'<< 8) | 9)
108:
109: #define PTRACESTEP (('P'<< 8) | 10)
110:
111: #define PTRACE11 (('P'<< 8) | 11)
112:
113:
114:
115: /* lseek() origins */
116:
117: #define SEEK_SET 0 /* from beginning of file */
118:
119: #define SEEK_CUR 1 /* from current location */
120:
121: #define SEEK_END 2 /* from end of file */
122:
123:
124:
125: #define WNOHANG 1
126:
127: #define WUNTRACED 2
128:
129:
130:
131: /* these definitions are incompatible with <sys/wait.h> */
132:
133: #define WIFEXITED(x) ((int)((x) & 0xFF00) == 0)
134:
135: #define WEXITSTATUS(x) ((int)((x) & 0xFF))
136:
137:
138:
139: #define WIFSIGNALED(x) (((int)((x) & 0xFF00) > 0) && ((int)(((x) & 0xFF) == 0)))
140:
141: #define WTERMSIG(x) ((int)(((x) & 0xFF00) >> 8))
142:
143:
144:
145: #define WIFSTOPPED(x) (((int)((x) & 0xFF) == 0x7F) && ((int)(((x) >> 8) & 0xFF) != 0))
146:
147: #define WSTOPSIG(x) ((int)(((x) >> 8) & 0xFF))
148:
149:
150:
151: #define SIGTRAP 5 /* trace trap */
152:
153:
154:
155: void
156:
157: dumpCTXT(ctxt)
158:
159: CONTEXT *ctxt;
160:
161: {
162:
163: int i, j;
164:
165:
166:
167: for (i = 0; i < 16; i += 4) {
168:
169: for (j = 0; j < 4; j++) {
170:
171: /* oh dear... we output too many commas - c'est la vie */
172:
173: printf("%c%d=$%08lx, ", i < 8 ? 'D' : 'A',
174:
175: i + j - (i >= 8 ? 8 : 0),
176:
177: ctxt[0].regs[i + j]);
178:
179: }
180:
181: putchar('\n');
182:
183: }
184:
185: printf("SR=$%04x\n", ctxt[0].sr);
186:
187: printf("PC=$%08lx\n", ctxt[0].pc);
188:
189: printf("SSP=$%08lx\n", ctxt[0].ssp);
190:
191: printf("term_vec=$%08lx\n", ctxt[0].term_vec);
192:
193: printf("fstate[0]=%u\n", ctxt[0].fstate[0]);
194:
195: for (i = 0; i < 8; i++) {
196:
197: printf("FP%d=$%08lx%08lx%08lx\n",
198:
199: i,
200:
201: ctxt[0].fregs[i * 3 + 0],
202:
203: ctxt[0].fregs[i * 3 + 1],
204:
205: ctxt[0].fregs[i * 3 + 2]);
206:
207: }
208:
209: printf("frame format=%u\n", ctxt[0].sfmt >> 12);
210:
211: printf("vector offset=$%x\n", ctxt[0].sfmt & 0xfff);
212:
213: /* could print internal state here internal[0..41] */
214:
215: }
216:
217:
218:
219: int
220:
221: main(argc,argv)
222:
223: int argc;
224:
225: char *argv[];
226:
227: {
228:
229: int pid;
230:
231: unsigned long status;
232:
233: int fd;
234:
235: char fpid[13];
236:
237: CONTEXT ctxt;
238:
239: long pctxt;
240:
241: long sizeof_ctxt;
242:
243: unsigned short sig;
244:
245:
246:
247: if (isdigit(*argv[1])) {
248:
249: pid = atoi(argv[1]);
250:
251: sprintf(fpid, "U:\\PROC\\.%03d", pid);
252:
253: fd = Fopen(fpid, 0);
254:
255: sig = 1;
256:
257: Fcntl(fd, (long)&sig, PTRACESFLAGS); /* capture it */
258:
259: Pkill(pid, SIGTRAP); /* and stop it */
260:
261: }
262:
263: else {
264:
265: pid = Pexec(0x8000 | 100, argv[1], "\0", NULL);
266:
267: /* check pid */
268:
269: printf("pid = %d\n", pid);
270:
271: sprintf(fpid, "U:\\PROC\\.%03d", pid);
272:
273: fd = Fopen(fpid, 0);
274:
275: }
276:
277: /* check fd */
278:
279: Fcntl(fd, (long)&pctxt, PPROCADDR);
280:
281: Fcntl(fd, (long)&sizeof_ctxt, PCTXTSIZE);
282:
283: pctxt -= 2 * sizeof_ctxt;
284:
285:
286:
287: do {
288:
289: status = Pwait3(WUNTRACED, NULL);
290:
291: if (WIFSTOPPED(status)) {
292:
293: printf("pid = %d\, WSTOPSIG = %d\n", (int)(status >> 16), WSTOPSIG(status));
294:
295: Fseek((long)pctxt, fd, SEEK_SET);
296:
297: Fread(fd, sizeof(ctxt), &ctxt); /* note _not_ sizeof_ctxt */
298:
299: dumpCTXT(&ctxt);
300:
301: switch (Cconin() & 0xff) {
302:
303: case 's':
304:
305: case 'S':
306:
307: Fcntl(fd, (long)NULL, PTRACESTEP); /* single step */
308:
309: break;
310:
311:
312:
313: case 'g':
314:
315: case 'G':
316:
317: Fcntl(fd, (long)NULL, PTRACEGO); /* go */
318:
319: break;
320:
321:
322:
323: case 'f':
324:
325: case 'F':
326:
327: Fcntl(fd, (long)NULL, PTRACEFLOW); /* go to flow change */
328:
329: break;
330:
331:
332:
333: case 'x':
334:
335: case 'X':
336:
337: sig = WSTOPSIG(status);
338:
339: Fcntl(fd, (long)&sig, PTRACEGO); /* kill it */
340:
341: break;
342:
343: }
344:
345: }
346:
347: putchar('\n');
348:
349: } while (!WIFEXITED(status) && !WIFSIGNALED(status));
350:
351: if (WIFEXITED(status))
352:
353: printf("pid = %d, WEXITSTATUS = %d\n", (int)(status >> 16), WEXITSTATUS(status));
354:
355: else
356:
357: printf("pid = %d, WTERMSIG = %d\n", (int)(status >> 16), WTERMSIG(status));
358:
359: Fclose(fd); /* but the process is dead... (Jim!) */
360:
361: return 0;
362:
363: }
364:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.