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