1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)resume.c 1.8 02/08/83";
4 
5 /*
6  * resume execution, first setting appropriate registers
7  */
8 
9 #include "defs.h"
10 #include <signal.h>
11 #include "process.h"
12 #include "machine.h"
13 #include "main.h"
14 #include "process.rep"
15 #include "runtime/frame.rep"
16 
17 #   if (isvaxpx)
18 #       include "machine/pxerrors.h"
19 #       include "pxinfo.h"
20 #   endif
21 
22 #ifdef vax
23 LOCAL ADDRESS fetchpc();
24 #endif
25 
26 LOCAL ADDRESS *pcaddr;
27 
28 /*
29  * Resume execution, set (get) pcode location counter before (after) resuming.
30  */
31 
32 resume()
33 {
34     register PROCESS *p;
35     int oldsigno;
36 
37     p = process;
38     do {
39 	if (option('e')) {
40 	    printf("execution resumes at pc 0x%x, lc %d\n", process->pc, pc);
41 	    fflush(stdout);
42 	}
43 	pcont(p);
44 #       if (isvaxpx)
45 #           ifdef sun
46 		if (pcaddr == 0) {
47 		    dread(&pcaddr, PCADDRP, sizeof(pcaddr));
48 		}
49 		dread(&pc, pcaddr, sizeof(pc));
50 #           else ifdef vax
51 		if (p->status == STOPPED) {
52 		    if (isbperr()) {
53 			pc = p->reg[11];
54 		    } else {
55 			dread(&pcframe, PCADDRP, sizeof(pcframe));
56 			pcframe++;
57 			pc = fetchpc(pcframe);
58 		    }
59 		    pc -= (sizeof(char) + ENDOFF);
60 		}
61 #           endif
62 #       else /* compiled code */
63 	    pc = process->pc;
64 #       endif
65 	if (option('e')) {
66 	    printf("execution stops at pc 0x%x, lc %d on sig %d\n",
67 		process->pc, pc, p->signo);
68 	    fflush(stdout);
69 	}
70 	if (p->status == STOPPED) {
71 	    errnum = 0;
72 	}
73     } while (p->signo == SIGCONT);
74 #   if (isvaxpx)
75 	if (option('r') && p->signo != 0) {
76 	    choose();
77 	}
78 
79     /*
80      * If px implements a breakpoint by executing a halt instruction
81      * (which is true on the VAX), the real pc must be incremented to
82      * skip over it.  On other machines (such as SUNs), px sends itself
83      * a signal and no incrementing is needed.
84      */
85 #       ifdef vax
86 	    if (isbperr()) {
87 		p->pc++;
88 	    }
89 #       endif
90 #   endif
91 }
92 
93 # if (isvaxpx)
94 # ifdef vax
95 
96 /*
97  * Find the location in the Pascal object where execution was suspended.
98  *
99  * We basically walk back through the frames looking for saved
100  * register 11's.  Each time we find one, we remember it.  When we reach
101  * the frame associated with the interpreter procedure, the most recently
102  * saved register 11 is the one we want.
103  */
104 
105 typedef struct {
106     int fr_handler;
107     unsigned int fr_psw : 16;   /* saved psw */
108     unsigned int fr_mask : 12;  /* register save mask */
109     unsigned int fr_unused : 1;
110     unsigned int fr_s : 1;      /* call was a calls, not callg */
111     unsigned int fr_spa : 2;    /* stack pointer alignment */
112     unsigned int fr_savap;      /* saved arg pointer */
113     unsigned int fr_savfp;      /* saved frame pointer */
114     int fr_savpc;           /* saved program counter */
115 } Vaxframe;
116 
117 #define regsaved(frame, n) ((frame.fr_mask&(1 << n)) != 0)
118 
119 LOCAL ADDRESS fetchpc(framep)
120 ADDRESS *framep;
121 {
122     register PROCESS *p;
123     Vaxframe vframe;
124     ADDRESS *savfp;
125     ADDRESS r;
126 
127     p = process;
128     r = p->reg[11];
129     if (p->fp == (ADDRESS) framep) {
130 	return r;
131     }
132     savfp = (ADDRESS *) p->fp;
133     dread(&vframe, savfp, sizeof(vframe));
134     while (vframe.fr_savfp != (int) framep && vframe.fr_savfp != 0) {
135 	if (regsaved(vframe, 11)) {
136 	    dread(&r, savfp + 5, sizeof(r));
137 	    r -= sizeof(char);
138 	}
139 	savfp = (ADDRESS *) vframe.fr_savfp;
140 	dread(&vframe, savfp, sizeof(vframe));
141     }
142     if (vframe.fr_savfp == 0) {
143 	panic("resume: can't find interpreter frame 0x%x", framep);
144     }
145     if (regsaved(vframe, 11)) {
146 	dread(&r, savfp + 5, sizeof(r));
147 	r -= sizeof(char);
148     }
149     return(r);
150 }
151 
152 # endif
153 
154 /*
155  * Under the -r option, we offer the opportunity to just get
156  * the px traceback and not actually enter the debugger.
157  *
158  * If the standard input is not a tty but standard error is,
159  * change standard input to be /dev/tty.
160  */
161 
162 LOCAL choose()
163 {
164     register int c;
165 
166     if (!isterm(stdin)) {
167 	if (!isterm(stderr) || freopen("/dev/tty", "r", stdin) == NIL) {
168 	    unsetsigtraces(process);
169 	    pcont(process);
170 	    quit(process->exitval);
171 	    /* NOTREACHED */
172 	}
173     }
174     fprintf(stderr, "\nProgram error");
175     if (errnum != 0) {
176 	fprintf(stderr, " -- %s", pxerrmsg[errnum]);
177     }
178     fprintf(stderr, "\nDo you wish to enter the debugger? ");
179     c = getchar();
180     if (c == 'n') {
181 	unsetsigtraces(process);
182 	pcont(process);
183 	quit(process->exitval);
184     }
185     while (c != '\n' && c != EOF) {
186 	c = getchar();
187     }
188     fprintf(stderr, "\nEntering debugger ...");
189     init();
190     option('r') = FALSE;
191     fprintf(stderr, " type 'help' for help.\n");
192 }
193 
194 # endif
195