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