122512Sdist /* 222512Sdist * Copyright (c) 1980 Regents of the University of California. 322512Sdist * All rights reserved. The Berkeley software License Agreement 422512Sdist * specifies the terms and conditions for redistribution. 522512Sdist */ 65508Slinton 722512Sdist #ifndef lint 8*30848Smckusick static char sccsid[] = "@(#)resume.c 5.2 (Berkeley) 04/07/87"; 922512Sdist #endif not lint 10*30848Smckusick 115508Slinton /* 1211061Slinton * Resume execution, first setting appropriate registers. 135508Slinton */ 145508Slinton 155508Slinton #include "defs.h" 165508Slinton #include <signal.h> 175508Slinton #include "process.h" 185508Slinton #include "machine.h" 195508Slinton #include "main.h" 205508Slinton #include "process.rep" 215508Slinton #include "runtime/frame.rep" 225508Slinton 2311061Slinton #include "machine/pxerrors.h" 2411061Slinton #include "pxinfo.h" 255508Slinton 26*30848Smckusick #if defined(vax) || defined(tahoe) 2711061Slinton LOCAL ADDRESS fetchpc(); 2810766Slinton #endif 29*30848Smckusick #ifdef vax 30*30848Smckusick #define PCREG 11 /* where px holds virtual pc (see interp.sed) */ 31*30848Smckusick #endif 32*30848Smckusick #ifdef tahoe 33*30848Smckusick #define PCREG 12 /* where px holds virtual pc (see interp.sed) */ 34*30848Smckusick #endif 355508Slinton 36*30848Smckusick #ifdef sun 3710766Slinton LOCAL ADDRESS *pcaddr; 38*30848Smckusick #endif 3910766Slinton 405508Slinton /* 4110766Slinton * Resume execution, set (get) pcode location counter before (after) resuming. 425508Slinton */ 435508Slinton 445508Slinton resume() 455508Slinton { 465714Slinton register PROCESS *p; 475508Slinton 485714Slinton p = process; 495714Slinton do { 505714Slinton if (option('e')) { 515714Slinton printf("execution resumes at pc 0x%x, lc %d\n", process->pc, pc); 525714Slinton fflush(stdout); 535714Slinton } 545714Slinton pcont(p); 5511061Slinton # ifdef sun 5611061Slinton if (pcaddr == 0) { 5711061Slinton dread(&pcaddr, PCADDRP, sizeof(pcaddr)); 5811061Slinton } 5911061Slinton dread(&pc, pcaddr, sizeof(pc)); 60*30848Smckusick # else vax || tahoe 6111061Slinton if (p->status == STOPPED) { 6211061Slinton if (isbperr()) { 63*30848Smckusick pc = p->reg[PCREG]; 6411061Slinton } else { 6511061Slinton dread(&pcframe, PCADDRP, sizeof(pcframe)); 66*30848Smckusick #ifdef tahoe 67*30848Smckusick pcframe += 14; 68*30848Smckusick #else 6911061Slinton pcframe++; 70*30848Smckusick #endif 7111061Slinton pc = fetchpc(pcframe); 725508Slinton } 7311061Slinton pc -= (sizeof(char) + ENDOFF); 7411061Slinton } 755714Slinton # endif 765714Slinton if (option('e')) { 775714Slinton printf("execution stops at pc 0x%x, lc %d on sig %d\n", 785714Slinton process->pc, pc, p->signo); 795714Slinton fflush(stdout); 805714Slinton } 815714Slinton } while (p->signo == SIGCONT); 8211061Slinton if (option('r') && p->signo != 0) { 8311061Slinton choose(); 8411061Slinton } 8510766Slinton 8610766Slinton /* 8710766Slinton * If px implements a breakpoint by executing a halt instruction 8811061Slinton * the real pc must be incremented to skip over it. 8911061Slinton * 9011061Slinton * Currently, px sends itself a signal so no incrementing is needed. 9111061Slinton * 9211061Slinton if (isbperr()) { 9311061Slinton p->pc++; 9411061Slinton } 9510766Slinton */ 965508Slinton } 975508Slinton 98*30848Smckusick #if defined(vax) || defined(tahoe) 995508Slinton 1005508Slinton /* 1015508Slinton * Find the location in the Pascal object where execution was suspended. 1025875Slinton * 1035875Slinton * We basically walk back through the frames looking for saved 104*30848Smckusick * register PCREG's. Each time we find one, we remember it. When we reach 1055875Slinton * the frame associated with the interpreter procedure, the most recently 106*30848Smckusick * saved register PCREG is the one we want. 1075508Slinton */ 1085508Slinton 1095508Slinton typedef struct { 110*30848Smckusick #ifdef vax 1115714Slinton int fr_handler; 1125714Slinton unsigned int fr_psw : 16; /* saved psw */ 1135714Slinton unsigned int fr_mask : 12; /* register save mask */ 1145714Slinton unsigned int fr_unused : 1; 1155714Slinton unsigned int fr_s : 1; /* call was a calls, not callg */ 1165714Slinton unsigned int fr_spa : 2; /* stack pointer alignment */ 1175714Slinton unsigned int fr_savap; /* saved arg pointer */ 1185714Slinton unsigned int fr_savfp; /* saved frame pointer */ 1195714Slinton int fr_savpc; /* saved program counter */ 120*30848Smckusick #endif 121*30848Smckusick #ifdef tahoe 122*30848Smckusick int fr_savpc; /* saved program counter */ 123*30848Smckusick unsigned short fr_mask; /* register save mask */ 124*30848Smckusick unsigned short fr_removed; /* (nargs+1)*4 */ 125*30848Smckusick unsigned int fr_savfp; /* saved frame pointer */ 126*30848Smckusick #endif 127*30848Smckusick } Stkframe; 1285508Slinton 1295875Slinton #define regsaved(frame, n) ((frame.fr_mask&(1 << n)) != 0) 1305875Slinton 1315508Slinton LOCAL ADDRESS fetchpc(framep) 1325508Slinton ADDRESS *framep; 1335508Slinton { 1345714Slinton register PROCESS *p; 135*30848Smckusick Stkframe sframe; 136*30848Smckusick #ifdef tahoe 137*30848Smckusick #define PCREGLOC (-1) 138*30848Smckusick #else 139*30848Smckusick #define PCREGLOC (sizeof sframe/sizeof(ADDRESS)) 140*30848Smckusick #endif 1415714Slinton ADDRESS *savfp; 1425714Slinton ADDRESS r; 1435508Slinton 1445714Slinton p = process; 145*30848Smckusick r = p->reg[PCREG]; 1465714Slinton if (p->fp == (ADDRESS) framep) { 1475875Slinton return r; 1485714Slinton } 1495714Slinton savfp = (ADDRESS *) p->fp; 150*30848Smckusick #ifdef tahoe 151*30848Smckusick savfp -= 2; 152*30848Smckusick #endif 153*30848Smckusick dread(&sframe, savfp, sizeof(sframe)); 154*30848Smckusick while (sframe.fr_savfp != (int) framep && sframe.fr_savfp != 0) { 155*30848Smckusick if (regsaved(sframe, PCREG)) { 156*30848Smckusick dread(&r, savfp + PCREGLOC, sizeof(r)); 1575875Slinton r -= sizeof(char); 1585875Slinton } 159*30848Smckusick savfp = (ADDRESS *) sframe.fr_savfp; 160*30848Smckusick #ifdef tahoe 161*30848Smckusick savfp -= 2; 162*30848Smckusick #endif 163*30848Smckusick dread(&sframe, savfp, sizeof(sframe)); 1645714Slinton } 165*30848Smckusick if (sframe.fr_savfp == 0) { 1665714Slinton panic("resume: can't find interpreter frame 0x%x", framep); 1675714Slinton } 168*30848Smckusick if (regsaved(sframe, PCREG)) { 169*30848Smckusick dread(&r, savfp + PCREGLOC, sizeof(r)); 1705714Slinton r -= sizeof(char); 1715714Slinton } 1725714Slinton return(r); 1735508Slinton } 1745508Slinton 17511061Slinton #endif 17610766Slinton 1775508Slinton /* 1785508Slinton * Under the -r option, we offer the opportunity to just get 1795508Slinton * the px traceback and not actually enter the debugger. 1806074Slinton * 1816074Slinton * If the standard input is not a tty but standard error is, 1826074Slinton * change standard input to be /dev/tty. 1835508Slinton */ 1845508Slinton 1855508Slinton LOCAL choose() 1865508Slinton { 1875714Slinton register int c; 1885508Slinton 1896873Slinton if (!isterm(stdin)) { 1906873Slinton if (!isterm(stderr) || freopen("/dev/tty", "r", stdin) == NIL) { 1916074Slinton unsetsigtraces(process); 1926074Slinton pcont(process); 1936074Slinton quit(process->exitval); 1946074Slinton /* NOTREACHED */ 1956074Slinton } 1966074Slinton } 1975714Slinton fprintf(stderr, "\nProgram error"); 1985714Slinton fprintf(stderr, "\nDo you wish to enter the debugger? "); 1995714Slinton c = getchar(); 2005714Slinton if (c == 'n') { 2015714Slinton unsetsigtraces(process); 2025714Slinton pcont(process); 2035714Slinton quit(process->exitval); 2045714Slinton } 2056074Slinton while (c != '\n' && c != EOF) { 2065508Slinton c = getchar(); 2075714Slinton } 2085714Slinton fprintf(stderr, "\nEntering debugger ..."); 2095714Slinton init(); 2105714Slinton option('r') = FALSE; 2115714Slinton fprintf(stderr, " type 'help' for help.\n"); 2125508Slinton } 213