|
|
1.1 root 1: static char sccsid[] = "@(#)pt.c 2.10";
2:
3: #include <errno.h>
4: #include <signal.h>
5:
6: #ifndef REGULUS
7: #include <sys/param.h>
8: #endif
9: #ifdef SUN
10: #define SYSTYPES 1 /* see basic.h */
11: #endif
12: #ifdef SYSIII
13: #define SYSTYPES 1 /* see basic.h */
14: #endif
15: #include "cdb.h"
16: #include "macdefs.h"
17:
18: #ifdef SYSIII
19: #include <termio.h>
20: #ifdef REGULUS
21: /* remove the two TCxxxxx and
22: * add #include <sys/ioctl.h> when preporocessor is fixed
23: */
24: #define TCGETA 1
25: #define TCSETAW 3
26: #define EINTR -1
27: #endif
28: struct termio histty, mytty;
29: #endif
30:
31: #ifdef BSD41
32: #include <sgtty.h>
33: struct sgttyb histty, mytty;
34: #endif
35:
36: export int vibp; /* last breakpoint hit, if any */
37:
38: export uint vsig;
39: uint vstat, vstatHi, vstatLo;
40: SAR vmpSigSa[NSIG]; /* signal action array */
41:
42: void Fixer();
43:
44: #define cArgsMax 30
45: char *argvChild[cArgsMax];
46: #define cbArgsMax 200
47: export char vsbArgsChild[cbArgsMax]; /* where we store args for child */
48:
49:
50: /* N E X T A R G */
51:
52: export char * NextArg(psbIn)
53: char **psbIn;
54: {
55: char *sbRet;
56:
57: /* skip white space */
58: while (**psbIn == ' ' OR **psbIn == '\t')
59: (*psbIn)++;
60: if (**psbIn == chNull)
61: return(sbNil); /* that's all, folks! */
62: sbRet = *psbIn; /* set current arg pointer */
63: while (**psbIn != chNull
64: AND **psbIn != ' '
65: AND **psbIn != '\t')
66: (*psbIn)++; /* skip all non-white space characters */
67: **psbIn = chNull; /* overwrite the tab, space, or 0 with a 0 */
68: (*psbIn)++;
69: return(sbRet);
70: } /* NextArg */
71:
72:
73: /* D O A R G S */
74:
75: export void DoArgs(sbProgram, sbArgs, argv, fReassign)
76: char *sbProgram, *sbArgs;
77: char **argv;
78: FLAGT fReassign;
79: {
80: int i;
81: char *sbFile, *sbArgCur;
82:
83: for (i=0; i< cArgsMax; i++)
84: argv[i] = sbNil;
85:
86: *argv++ = sbProgram; /* set the filename */
87:
88: /* eat the arguments */
89: while ((sbArgs != sbNil)
90: AND (*sbArgs != chNull)) {
91: sbArgCur = NextArg(&sbArgs);
92: if (sbArgCur == sbNil)
93: break;
94: /* check for indirection */
95: if (!fReassign
96: OR ((*sbArgCur != '<') AND (*sbArgCur != '>')) ) {
97: *argv++ = sbArgCur; /* we just pass it on */
98: }
99: else {
100: /* find that file name */
101: sbFile = sbArgCur + 1; /* initially we assume `<foo' vs `< foo' */
102: if (*sbFile == chNull) {
103: /* there was white space between < and sbFile */
104: sbFile = NextArg(&sbArgs);
105: if (sbFile == sbNil) {
106: printf("Illegal indirection\n");
107: exit(1);
108: } /* if */
109: } /* if */
110: if (*sbArgCur == '<') {
111: /* changing stdin */
112: close(0);
113: if (open(sbFile, O_RDONLY) < 0) {
114: perror(sbFile);
115: exit(1);
116: } /* if */
117: }
118: else if (*sbArgCur == '>') {
119: /* changing stdout */
120: close(1);
121: if (creat(sbFile, 0666) < 0) {
122: perror(sbFile);
123: exit(1);
124: } /* if */
125: } /* if */
126: } /* if */
127: } /* while */
128: *argv = sbNil;
129: } /* DoArgs */
130:
131:
132: /* P R I N T S I G */
133:
134: export void PrintSig(sig)
135: int sig;
136: {
137: switch (sig) {
138: case SIGHUP:
139: printf("Hangup");
140: break;
141: case SIGINT:
142: printf("interrupt");
143: break;
144: case SIGQUIT:
145: printf("quit");
146: break;
147: case SIGILL:
148: printf("illegal instruction");
149: break;
150: case SIGTRAP:
151: printf("breakpoint");
152: break;
153: case SIGIOT:
154: printf("IOT instruction");
155: break;
156: case SIGEMT:
157: printf("EMT instruction");
158: break;
159: case SIGFPE:
160: printf("floating point exception");
161: break;
162: case SIGKILL:
163: printf("kill");
164: break;
165: case SIGBUS:
166: printf("bus error");
167: break;
168: case SIGSEGV:
169: printf("segmentaion violation");
170: break;
171: case SIGSYS:
172: printf("bad arg to sys call");
173: break;
174: case SIGPIPE:
175: printf("write on pipe with no reader");
176: break;
177: case SIGALRM:
178: printf("alarm clock");
179: break;
180: case SIGTERM:
181: printf("software termination");
182: break;
183: #ifdef SYSIII
184: case SIGUSR1:
185: printf("user signal 1");
186: break;
187: case SIGUSR2:
188: printf("user signal 2");
189: break;
190: case SIGCLD:
191: printf("death of child");
192: break;
193: case SIGPWR:
194: printf("power fail");
195: break;
196: #endif
197: #ifdef BSD41
198: #ifdef BSD42
199: case SIGURG:
200: printf("urgent condition on IO channel");
201: break;
202: case SIGIO:
203: printf("input/output possible signal");
204: break;
205: case SIGVTALRM:
206: printf("virtual time alarm");
207: break;
208: case SIGPROF:
209: printf("profiling time alarm");
210: break;
211: #endif
212: case SIGSTOP:
213: printf("sendable stop signal not from tty");
214: break;
215: case SIGTSTP:
216: printf("stop signal from tty");
217: break;
218: case SIGCONT:
219: printf("attempt to continue a stopped process");
220: break;
221: case SIGCHLD:
222: printf("child stop or exit");
223: break;
224: case SIGTTIN:
225: printf("to readers pgrp upon background tty read");
226: break;
227: case SIGTTOU:
228: printf("to writers pgrp upon background tty write");
229: break;
230: case SIGXCPU:
231: printf("exceeded CPU time limit");
232: break;
233: case SIGXFSZ:
234: printf("exceeded file size limit");
235: break;
236: #endif
237: default:
238: printf("signal %d", sig);
239: break;
240: } /* switch */
241: } /* PrintSig */
242:
243:
244: /* I B P F W A I T */
245:
246: export int IbpFWait(fDoBrk)
247: FLAGT fDoBrk;
248: {
249: int ibp, waitReturn;
250: pSAR sa;
251:
252: keepGoing: /* we come here if the signal is not interesting */
253:
254: signal(SIGINT, SIG_IGN); /* ignore INT - let child deal with it */
255:
256: while ( ((waitReturn=wait(&vstat)) != vpid) AND (waitReturn != -1) )
257: ;
258:
259: #ifdef SYSIII
260: ioctl(0, TCGETA, &histty); /* save his state, restore my state */
261: ioctl(0, TCSETAW, &mytty);
262: #endif
263: #ifdef BSD41
264: gtty(0, &histty); /* save his state, restore my state */
265: stty(0, &mytty);
266: #endif
267: signal(SIGINT, Fixer); /* reconnect to the Fixer routine */
268:
269: GetState();
270:
271: vsig = vstatHi = vstat >> 8;
272: vstatLo = vstat & 0377;
273: vibp = ibp = ibpNil; /* index of the breakpoint we are at (if any) */
274: if (waitReturn == -1) {
275: if (errno == EINTR) {
276: printf("PANIC! received signal: %d????\n", vsig);
277: /* what do we do here?? */
278: exit(1);
279: }
280: else { /* some sort of error occurred */
281: perror("cdb");
282: exit(1);
283: } /* if */
284: }
285: else if (vstatLo == 0) { /* child terminated */
286: if (vstatHi != 0)
287: printf("Process exited with %d\n", vstatHi);
288: else printf("Process terminated normally\n");
289: KillChild(); /* go bury the corpse */
290: ibp = 0; /* small hack - causes single step to stop in cmd.c */
291: }
292: else if ((vstatLo&0177) == 0177) { /* child stopped */
293: sa = vmpSigSa + vsig;
294: if (sa->fNoStop) {
295: #ifdef SYSIII
296: ioctl(0, TCSETAW, &histty);
297: #endif
298: #ifdef BSD41
299: stty(0, &histty);
300: #endif
301: if (!(sa->fNoReport)) {
302: PrintSig(vsig);
303: printf(" at %s\n", SbFAdr(lengthen(vpc), true));
304: PrintPos(vpc, fmtProc+fmtLn+fmtPrint);
305: } /* if */
306: vsig = (sa->fEatSig) ? 0 : vsig;
307: ptrace(ptResume, vpid, 1, vsig); /* continue */
308: goto keepGoing;
309: } /* if */
310: /* NOTE: BrkOut MIGHT back up pc, depends on machine and instruction */
311: vibp = ibp = (fDoBrk) ? BrkOut(&vpc) : ibpNil;
312: if (vpc == vadrBreak) {
313: /* we have hit the BP used for proc calls from command line */
314: return(ibp);
315: } /* if */
316: if ( (ibp >= 0)
317: AND (vrgBp[ibp].sbBp[0] != chNull) ) {
318: PushCmd(vsbCmd);
319: vsbCmd = vrgBp[ibp].sbBp;
320: } /* if */
321: if ( (vsig != SIGTRAP) /* we ALWAYS report non-break signals */
322: OR ((ibp >= 0) /* there is something to hear */
323: AND (*vsbCmd != 'Q')) ) { /* and BP's want's it heard */
324: printf("\n"); /* in case we were left in the middle of a line */
325: PrintSig(vsig);
326: printf(" at %s\n", SbFAdr(lengthen(vpc), true));
327: PrintPos(vpc, fmtProc+fmtLn+fmtPrint);
328: }
329: else if ((vsbCmd != sbNil) AND (*vsbCmd == 'Q')) {
330: PrintPos(vpc, fmtNil);
331: } /* if */
332: vsig = (sa->fEatSig) ? 0 : vsig;
333: }
334: else if ((vstat & 0177) != 0177) { /* terminated on signal */
335: if (vstat & 0177)
336: PrintSig(vstat&0177);
337: if (vstat & 0200) {
338: printf(" (core dumped)");
339: close(vfnCore);
340: InitCorefile("core");
341: } /* if */
342: printf(" at %s\n", SbFAdr(lengthen(vpc), true));
343: PrintPos(vpc, fmtProc+fmtLn+fmtPrint);
344: vpid = pidNil;
345: } /* if */
346: return(ibp);
347: } /* IbpFWait */
348:
349:
350: /* I B P F R U N */
351:
352: export int IbpFRun(pt)
353: int pt;
354: {
355: int ibp;
356: ADRT pcOld;
357:
358: if (vpid == pidNil)
359: UError("No process");
360:
361: if ((vfRunAssert)
362: AND (vas == asActive)
363: AND (viadMac > 0)
364: AND (pt != ptSingle)) {
365: /* do the assertions */
366: if (FDoAssert(pt)) /* this will change vas and single step the child */
367: return(ibpNil); /* an assertion came up true */
368: if (vpid == pidNil)
369: return(ibpNil); /* the child died during assertions */
370: if (vibp != ibpNil)
371: return(vibp);
372: } /* if */
373:
374: /* hit the GO button */
375:
376: do { /* loop allows for bp's that say 'continue' */
377: /* if we are at a breakpoint, single step over it, then install it */
378: if (IbpFBrkIn(vpc) != ibpNil) {
379: PutState();
380: pcOld = vpc;
381: while (pcOld == vpc) {
382: ptrace(ptSingle, vpid, 1, vsig);
383: ibp = IbpFWait(false);
384: } /* while */
385: if (pt == ptSingle)
386: return(ibp); /* we have already single stepped it for them */
387: /* full steam ahead */
388: IbpFBrkIn(adrNil); /* put in bp's */
389: } /* if */
390:
391: PutState();
392: #ifdef SYSIII
393: ioctl(0, TCSETAW, &histty);
394: #endif
395: #ifdef BSD41
396: stty(0, &histty);
397: #endif
398: errno = 0;
399: ptrace(pt, vpid, 1, vsig); /* start child with signal `sig' */
400: ibp = IbpFWait(true);
401: }
402: while (ibp == ibpContinue);
403: return(ibp);
404: } /* IbpFRun */
405:
406:
407: /* I B P F N E W C H I L D */
408:
409: export int IbpFNewChild(sbArgs)
410: char *sbArgs;
411: {
412: int sig, i, ibp;
413: FLAGT fMaster;
414:
415: KillChild(); /* in case there is already one out there */
416:
417: #ifdef SYSIII
418: ioctl(0, TCGETA, &histty); /* to start with, he is the same as me */
419: ioctl(0, TCGETA, &mytty); /* save my stuff */
420: #endif
421: #ifdef BSD41
422: gtty(0, &histty); /* to start with, he is the same as me */
423: gtty(0, &mytty); /* save my stuff */
424: #endif
425:
426: if (sbArgs == sbNil) {
427: *vsbArgsChild = chNull; /* this comes from the R command */
428: }
429: else {
430: fMaster = (sbArgs == vsbCmd); /* this is the normal command line */
431: while (*sbArgs == ' ' OR *sbArgs == '\011')
432: sbArgs++; /* eat leading white space */
433: if (*sbArgs != chNull) {
434: strcpy(vsbArgsChild, sbArgs);
435: for (i=strlen(sbArgs); i<cbArgsMax; i++)
436: vsbArgsChild[i] = chNull;
437: /* fixes obscure bug, don't ask why...... */
438: if (fMaster) {
439: /* eat it - this way we don't
440: * try to execute the arguments to the child
441: * as debugger commands
442: */
443: vsbCmd = sbNil;
444: } /* if */
445: } /* if */
446: } /* if */
447:
448: close(vfnSym); /* in case it is PURE or SPLIT I&D */
449: if ((vpid = fork()) == 0) {
450: for (sig=1; sig<NSIG; sig++)
451: signal(sig, SIG_DFL); /* start out with default response */
452: DoArgs(vsbSymfile, vsbArgsChild, argvChild, true);
453: ptrace(ptChild, 0, 0, 0); /* Hi, Mom! */
454: #ifdef REGULUS
455: #define flags 04+010+020 /* overlay + set trace + environment present */
456: maketask(vsbSymfile, flags, 0, argvChild, venvpParent);
457: #else
458: execvp(vsbSymfile, argvChild);
459: #endif
460: /* if we get here, exec failed */
461: perror("could not startup");
462: exit(1);
463: } /* if */
464:
465: /* should only get here if parent */
466: printf("running '%s %s'\n", vsbSymfile, vsbArgsChild);
467: IbpFWait(false);
468: /* it is now safe to open symfile again */
469: /* printf("Opening file %s\n", vsbSymfile); */
470: vfnSym = open(vsbSymfile, O_RDONLY);
471: if (vfnSym < 0) {
472: perror(vsbSymfile);
473: exit(1);
474: } /* if */
475: IbpFAdr(vadrStart, 0, sbNil); /* at first instruction */
476: vfRunAssert = false; /* we don't want assertions during initialization */
477: ibp = IbpFRun(ptResume);
478: vfRunAssert = true;
479: return(ibp);
480: } /* IbpFNewChild */
481:
482:
483: /* K I L L C H I L D */
484:
485: export void KillChild()
486: {
487: if (vpid != pidNil) {
488: ptrace(ptTerm, vpid, 0, 0);
489: }
490: vpid = pidNil;
491: vpc = adrNil;
492: vsig = 0;
493: vfp = 0;
494: if(vfnCore != fnNil) {
495: GetState(); /* refresh from the core file */
496: vpc -= 2; /* so we have true address of error */
497: } /* if */
498: } /* KillChild */
499:
500:
501: /* G O T O L N */
502:
503: export void GotoLn(ln)
504: int ln;
505: {
506: ADRT adr;
507:
508: adr = AdrFIfdLn(vifd, ln);
509: if (IpdFAdr(adr) != IpdFAdr(vpc))
510: UError("You can't goto a line outside of the current procedure");
511:
512: /* if I can figure it out, it would be nice to be able to unwind the
513: * stack. We can get the pc, fp, and ap, but the sp seems to be unknown,
514: * plus the old register values. We might be able to 'goto' each
515: * procedure end, return up the stack, and keep doing that until we
516: * get there, but this is involved. Maybe if someone asks REAL nicely....
517: */
518: PutReg(upc, adr);
519: } /* GotoAdr */
520:
521:
522: /* I N I T S A */
523:
524: export void InitSa()
525: {
526: /* the 'Q' option shuts up the printout of the signal settings */
527: SaMaintain(SIGALRM, "srQ"); /* we don't stop, report or eat */
528: SaMaintain(SIGKILL, "srQ");
529: SaMaintain(SIGINT, "eQ"); /* we stop, report and eat */
530: SaMaintain(SIGTRAP, "eQ"); /* we stop, report and eat */
531: #ifdef BSD41
532: SaMaintain(SIGCONT, "srQ");
533: SaMaintain(SIGCHLD, "srQ");
534: #endif
535: } /* InitSa */
536:
537:
538: /* S A M A I N T A I N */
539:
540: export void SaMaintain(sig, sbOptions)
541: int sig;
542: char *sbOptions;
543: {
544: pSAR sa;
545:
546: sa = vmpSigSa + sig;
547: /* we toggle options based on the flags:
548: * r = report, s = stop, e = eat signal
549: */
550: if (strchr(sbOptions, 'r'))
551: sa->fNoReport = ~sa->fNoReport;
552: if (strchr(sbOptions, 's'))
553: sa->fNoStop = ~sa->fNoStop;
554: if (strchr(sbOptions, 'e'))
555: sa->fEatSig = ~sa->fEatSig;
556:
557: if (strchr(sbOptions, 'Q') == sbNil) {
558: printf(" Stop Eat Report Name\n");
559: printf("%2d %c %c %c ", sig,
560: (sa->fNoStop) ? 'F':'T',
561: (sa->fEatSig) ? 'T':'F',
562: (sa->fNoReport) ? 'F':'T');
563: PrintSig(sig);
564: printf("\n");
565: } /* if */
566: } /* SaMaintain */
567:
568:
569: /* L I S T S A */
570:
571: export void ListSa()
572: {
573: int sig;
574: pSAR sa;
575:
576: printf(" Stop Eat Report Name\n");
577: for (sig=1; sig < NSIG; sig++) {
578: sa = vmpSigSa + sig;
579: printf("%2d %c %c %c ", sig,
580: (sa->fNoStop) ? 'F':'T',
581: (sa->fEatSig) ? 'T':'F',
582: (sa->fNoReport) ? 'F':'T');
583: PrintSig(sig);
584: printf("\n");
585: } /* for */
586: } /* ListSa */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.