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