1*6791Srrh #
2*6791Srrh
3*6791Srrh static char sccsid[] = " runcompat.c 1.1 82/05/12 ";
4*6791Srrh
5*6791Srrh /*
6*6791Srrh * Compatability mode support under UNIX-32V
7*6791Srrh * written by Art Wetzel during August 1979
8*6791Srrh * at the Interdisciplinary Dept of Information Science
9*6791Srrh * Room 711, LIS Bldg
10*6791Srrh * University of Pittsburgh
11*6791Srrh * Pittsburgh, Pa 15260
12*6791Srrh *
13*6791Srrh * No claims are made on the completeness of the support of any
14*6791Srrh * of the systems simulated under this package
15*6791Srrh */
16*6791Srrh #include <stdio.h>
17*6791Srrh #include <signal.h>
18*6791Srrh #include <sys/types.h>
19*6791Srrh #include <sys/stat.h>
20*6791Srrh #include <errno.h>
21*6791Srrh #include "defs.h"
22*6791Srrh #ifdef UNIX
23*6791Srrh #include "unixhdr.h"
24*6791Srrh #endif
25*6791Srrh #ifdef RT11
26*6791Srrh #include "rt11.h"
27*6791Srrh #endif
28*6791Srrh struct stat stat32v;
29*6791Srrh unsigned short regs[8];
30*6791Srrh unsigned long psl;
31*6791Srrh unsigned short *pc;
32*6791Srrh int incompat;
33*6791Srrh char *progname;
34*6791Srrh char *nameend;
main(argc,argv,envp)35*6791Srrh main(argc, argv, envp) int argc; char **argv, **envp; {
36*6791Srrh if(argc < 2){
37*6791Srrh printf(stderr,"Usage: %s [-rootdir] file args...\n",argv[0]);
38*6791Srrh exit(1);
39*6791Srrh }
40*6791Srrh /* remember where the program name etc should go for using ps */
41*6791Srrh progname = argv[0];
42*6791Srrh nameend = envp[0]-1;
43*6791Srrh argv++;
44*6791Srrh /* set up alternate root directory if flagged for */
45*6791Srrh if(*argv[0] == '-') {
46*6791Srrh if(chroot(argv[0]+1)) {
47*6791Srrh fprintf(stderr,"Can't change root to %s\n",argv[0]+1);
48*6791Srrh exit(-1);
49*6791Srrh }
50*6791Srrh argv++;
51*6791Srrh }
52*6791Srrh /* check out file stats of file to run */
53*6791Srrh if(stat(argv[0], &stat32v)) {
54*6791Srrh fprintf(stderr,"%s does not exist\n",argv[0]);
55*6791Srrh exit(1);
56*6791Srrh }
57*6791Srrh /* a version of SETUID and SETGID file executions */
58*6791Srrh /* the binary of this program should be SETUID root for this to work */
59*6791Srrh /* requires nonstandard seteuid and setegid sys calls */
60*6791Srrh if(!(stat32v.st_mode & S_ISGID) || setegid(stat32v.st_gid))
61*6791Srrh /* if not SETGID file or error, drop back to real group */
62*6791Srrh setgid(getgid());
63*6791Srrh if(!(stat32v.st_mode & S_ISUID) || seteuid(stat32v.st_uid))
64*6791Srrh /* if not SETUID file or error, drop back to real uid */
65*6791Srrh setuid(getuid());
66*6791Srrh #ifdef V6UNIX
67*6791Srrh /* no umasks in version 6 */
68*6791Srrh umask(0);
69*6791Srrh #endif
70*6791Srrh /* go try to execute , passing along args and environment */
71*6791Srrh execute(argv[0], argv, envp);
72*6791Srrh /* only get here if execute fails */
73*6791Srrh fprintf(stderr,"Execution failure on %s\n",argv[0]);
74*6791Srrh exit(1);
75*6791Srrh }
execute(file,argv,envp)76*6791Srrh execute(file, argv, envp) char *file, **argv, **envp; {
77*6791Srrh int fd, n, tloadpt, dloadpt, tloadsize, dloadsize, stacksize;
78*6791Srrh register short *p;
79*6791Srrh extern illtrap();
80*6791Srrh /* file to run should be readable */
81*6791Srrh if((fd = open(file, 0)) == -1) {
82*6791Srrh fprintf(stderr,"Can't open %s for read access\n",file);
83*6791Srrh return(-1);
84*6791Srrh }
85*6791Srrh #ifdef UNIX
86*6791Srrh if((n = read(fd, &header, sizeof header)) != sizeof header)
87*6791Srrh return(ENOEXEC);
88*6791Srrh /* check to see if really unix file */
89*6791Srrh if(header.magic != MAGIC1 && header.magic != MAGIC2 &&
90*6791Srrh header.magic != MAGIC3 && header.magic != MAGIC4) {
91*6791Srrh return(ENOEXEC);
92*6791Srrh }
93*6791Srrh /* if a UNIX-32V file run it */
94*6791Srrh if(header.textsize == 0) {
95*6791Srrh close(fd);
96*6791Srrh return(execv(file, argv, envp));
97*6791Srrh }
98*6791Srrh /* checks out OK as PDP-11 UNIX file */
99*6791Srrh if(header.magic == MAGIC3) {
100*6791Srrh fprintf(stderr,"%s compiled for separate I/D space\n",argv[0]);
101*6791Srrh return(-1);
102*6791Srrh }
103*6791Srrh /* unix text loads at 0 */
104*6791Srrh tloadpt = 0;
105*6791Srrh /* set starting pc value */
106*6791Srrh pc = (unsigned short *)header.entry;
107*6791Srrh /* figure out where to load initialized data */
108*6791Srrh dloadpt = tloadsize = header.textsize;
109*6791Srrh /* check if alignment of data segment to 8k byte boundary */
110*6791Srrh if(header.magic == MAGIC2)
111*6791Srrh dloadpt = (dloadpt+8191) & (~8191);
112*6791Srrh /* how much data */
113*6791Srrh dloadsize = header.datasize;
114*6791Srrh stacksize = header.bsssize;
115*6791Srrh #endif
116*6791Srrh #ifdef RT11
117*6791Srrh if((n = read(fd, shortspace, RTHDRSIZ)) != RTHDRSIZ) {
118*6791Srrh fprintf(stderr,"Error reading 1st block\n");
119*6791Srrh return(-1);
120*6791Srrh }
121*6791Srrh /* rt11 files are 0 aligned including the header */
122*6791Srrh tloadpt = RTHDRSIZ;
123*6791Srrh /* set starting pc value */
124*6791Srrh pc = (unsigned short *)shortspace[RTPC];
125*6791Srrh /* initialize stack location */
126*6791Srrh regs[6] = shortspace[RTSP];
127*6791Srrh /* figure how much to load */
128*6791Srrh dloadpt = tloadsize = shortspace[RTHGH]-RTHDRSIZ;
129*6791Srrh /* no separate data as in unix */
130*6791Srrh dloadsize = 0;
131*6791Srrh stacksize = 0;
132*6791Srrh #endif
133*6791Srrh /* see if it all fits into available memory space */
134*6791Srrh if((dloadpt+dloadsize+stacksize) > (int)memsiz) {
135*6791Srrh fprintf(stderr,"File too big to run\n");
136*6791Srrh return(-1);
137*6791Srrh }
138*6791Srrh /* read text segment */
139*6791Srrh if((n = read(fd, tloadpt, tloadsize)) < tloadsize) {
140*6791Srrh fprintf(stderr,"Text read failure\n");
141*6791Srrh return(-1);
142*6791Srrh }
143*6791Srrh /* read data segment */
144*6791Srrh if((n = read(fd, dloadpt, dloadsize)) < dloadsize) {
145*6791Srrh fprintf(stderr,"Data read failure\n");
146*6791Srrh return(-1);
147*6791Srrh }
148*6791Srrh /* clear out the rest of memory */
149*6791Srrh p = (short *)(dloadpt + dloadsize);
150*6791Srrh while(p < (short *)memsiz) *p++ = 0;
151*6791Srrh /* close file before starting it */
152*6791Srrh close(fd);
153*6791Srrh /* set up illegal instruction trapping */
154*6791Srrh signal(SIGILL, illtrap);
155*6791Srrh /* lets give it a try */
156*6791Srrh start(argv, envp);
157*6791Srrh }
illtrap()158*6791Srrh illtrap(){
159*6791Srrh unsigned short *pcptr;
160*6791Srrh int instr;
161*6791Srrh register int i;
162*6791Srrh extern getregs();
163*6791Srrh /* record the fact that we are not in compatability mode now */
164*6791Srrh incompat = 0;
165*6791Srrh /* get the register values before they get clobbered */
166*6791Srrh getregs();
167*6791Srrh /* figure out what the pc was */
168*6791Srrh pcptr = (unsigned short *)((char *)&pcptr + 20);
169*6791Srrh pc = (unsigned short *) *pcptr;
170*6791Srrh /* get the instruction */
171*6791Srrh instr = *pc;
172*6791Srrh /* incriment the pc over this instruction */
173*6791Srrh pc++;
174*6791Srrh /* set register 7 as pc synonym */
175*6791Srrh regs[7] = (unsigned short)(int)pc;
176*6791Srrh /* set up psl with condition codes */
177*6791Srrh /* a UNIX-32V monitor patch is required to not clear condition codes */
178*6791Srrh psl = 0x83c00000 | (*(pcptr - 6) & 017);
179*6791Srrh /* pick out the appropriate action for this illegal instruction */
180*6791Srrh switch(instr>>8){
181*6791Srrh case TRAPS:
182*6791Srrh dotrap(instr & 0377);
183*6791Srrh break;
184*6791Srrh case EMTS:
185*6791Srrh if(sigvals[SIGEMT] && ((sigvals[SIGEMT]%2) != 1)) {
186*6791Srrh dosig(SIGEMT, pc);
187*6791Srrh break;
188*6791Srrh }
189*6791Srrh doemt(instr & 0377);
190*6791Srrh break;
191*6791Srrh default:
192*6791Srrh if(instr >= 075000 && instr < 075040) {
193*6791Srrh /* fis instructions */
194*6791Srrh if(dofloat(instr) == 0)
195*6791Srrh break;
196*6791Srrh }
197*6791Srrh if(instr >= 0170000) {
198*6791Srrh /* floating point unit instructions */
199*6791Srrh if(dofloat(instr) == 0)
200*6791Srrh break;
201*6791Srrh }
202*6791Srrh /* genuine illegal instruction */
203*6791Srrh /* if signal trap set go to user's trap location */
204*6791Srrh if(sigvals[SIGILL] && ((sigvals[SIGILL]%2) != 1)) {
205*6791Srrh dosig(SIGILL, pc);
206*6791Srrh break;
207*6791Srrh }
208*6791Srrh /* ignore uncaught setd instructions */
209*6791Srrh if(instr == SETD)
210*6791Srrh break;
211*6791Srrh /* otherwise put out a message and quit */
212*6791Srrh printf("illegal instruction, psl 0x%08x, pc 0%04o\n",psl,pc-1);
213*6791Srrh for(i=0; i<7; i++) printf("0x%04x ",regs[i]);
214*6791Srrh printf("0x%04x -> 0%o\n",pc-1,instr);
215*6791Srrh /* set up to dump on illegal instruction */
216*6791Srrh signal(SIGILL,SIG_DFL);
217*6791Srrh /* set pc back to bad instruction */
218*6791Srrh pc--;
219*6791Srrh /* go do it again for dump */
220*6791Srrh compat();
221*6791Srrh }
222*6791Srrh /* go back to compatability mode */
223*6791Srrh incompat++;
224*6791Srrh compat();
225*6791Srrh }
226