|
|
1.1 root 1: #include "global.h"
2: #include <stdio.h>
3: #include <a.out.h>
4: #include "chkrtab.h"
5:
6: /* rfasl - really fast loader j.k.foderaro
7: * this loader is tuned for the lisp fast loading application
8: * any changes in the system loading procedure will require changes
9: * to this file
10: * Nov 4, 1979 - this now becomes fasl to the lisp world
11: */
12:
13:
14:
15: /* global variables to keep track of allocation */
16:
17: int curps ;
18:
19: /* external functions called or referenced */
20:
21: int _qf0(), _qf1(), _qf2(), _qf3(), _qf4(), _qfuncl(), svkludg();
22: lispval Lread(), Lcons(), Lminus(), Ladd1(), Lsub1(), Lplist(), Lputprop();
23: lispval Lprint(), Lpatom(), Lconcat(), Lget(), Lmapc(), Lmapcan();
24: lispval Llist(), Ladd(), Lgreaterp(), Lequal(), Ltimes(), Lsub();
25: lispval Lncons();
26: lispval Idothrow(),error();
27: extern lispval *tynames[];
28: extern int errp;
29: extern char _erthrow[];
30: extern char setsav[];
31:
32: extern int initflag; /* when TRUE, inhibits gc */
33: /* prelud to linker table in data segment
34: * these locations always begin the data segment, if there is any change
35: * to the compiler, this must be fixed up.
36: *
37: */
38:
39:
40: #define PRESIZ (8*4)
41:
42: struct prelud
43: {
44: int dummy[PRESIZ/4];
45: } prel = {
46: (int) &bnp,
47: (int) _qfuncl,
48: (int) _qf4,
49: (int) _qf3,
50: (int) _qf2,
51: (int) _qf1,
52: (int) _qf0,
53: (int) 0 };
54: /* mini symbol table, contains the only external symbols compiled code
55: is allowed to reference
56: */
57:
58: #define SYMMAX 35
59: struct ssym { char *fnam; /* pointer to string containing name */
60: int floc; /* address of symbol */
61: int ord; /* ordinal number within cur sym tab */
62:
63: } symbtb[SYMMAX]
64: = {
65: "_Lminus", (int) Lminus, -1,
66: "_Ladd1", (int) Ladd1, -1,
67: "_Lsub1", (int) Lsub1, -1,
68: "_Lplist", (int) Lplist, -1,
69: "_Lcons", (int) Lcons, -1,
70: "_Lputpro", (int) Lputprop, -1,
71: "_Lprint", (int) Lprint, -1,
72: "_Lpatom", (int) Lpatom, -1,
73: "_Lread", (int) Lread, -1,
74: "_Lconcat", (int) Lconcat, -1,
75: "_Lget", (int) Lget, -1,
76: "_Lmapc", (int) Lmapc, -1,
77: "_Lmapcan", (int) Lmapcan, -1,
78: "_Llist", (int) Llist, -1,
79: "_Ladd", (int) Ladd, -1,
80: "_Lgreate",(int) Lgreaterp,-1,
81: "_Lequal", (int) Lequal, -1,
82: "_Ltimes", (int) Ltimes, -1,
83: "_Lsub", (int) Lsub, -1,
84: "_Lncons", (int) Lncons, -1,
85: "_typetab", (int) typetab, -1,
86: "_tynames", (int) tynames, -1,
87: "_errp", (int) &errp, -1,
88: "_Idothro", (int) Idothrow, -1,
89: "__erthro", (int) _erthrow, -1,
90: "_error", (int) error, -1,
91: "_bnp", (int) &bnp, -1,
92: "__qfuncl", (int) _qfuncl, -1,
93: "__qf4", (int) _qf4, -1,
94: "__qf3", (int) _qf3, -1,
95: "__qf2", (int) _qf2, -1,
96: "__qf1", (int) _qf1, -1,
97: "__qf0", (int) _qf0, -1,
98: "_setsav", (int) setsav, -1,
99: "_svkludg", (int) svkludg, -1
100: };
101:
102: struct nlist syml; /* to read a.out symb tab */
103: extern lispval *bind_lists; /* gc binding lists */
104:
105: /* bindage structure:
106: * the bindage structure describes the linkages of functions and name,
107: * and tells which functions should be evaluated. It is mainly used
108: * for the non-fasl'ing of files, we only use one of the fields in fasl
109: */
110: struct bindage
111: {
112: lispval (*b_entry)(); /* function entry point */
113: int b_atmlnk; /* pointer to string */
114: int b_type; /* type code, as described below */
115: };
116:
117: /* the possible values of b_type
118: * -1 - this is the end of the bindage entries
119: * 0 - this is a lambda function
120: * 1 - this is a nlambda function
121: * 2 - this is a macro function
122: * 99 - evaluate the string
123: *
124: */
125:
126: /* maximum number of functions */
127: #define MAXFNS 500
128:
129: lispval Lfasl()
130: {
131: register int orgtx,orgdt,orgps;
132: register struct argent *svnp, *lbot, *np;
133: struct exec exblk; /* stores a.out header */
134: FILE *filp, *p, *map; /* file pointer */
135: int domap;
136: lispval handy;
137: struct relocation_info reloc;
138: struct prelud *ppre;
139: lispval disp;
140: int i,j,times, *iptr, oldinitflag;
141: int funloc[MAXFNS]; /* addresses of functions rel to txt org */
142: int funcnt = 0;
143:
144: /* unrelocated start and end of litteral table */
145: int litstrt = 0 , litend = 0;
146:
147: int segdif;
148: struct bindage *bindorg, *curbind;
149: int linkerloc, bindloc = 0 , typer,linkstrt,linkend;
150: lispval rdform, *linktab;
151: int segsiz;
152: int debug = 0;
153: lispval currtab,curibase;
154: char ch;
155:
156:
157: chkarg(2);
158: if (TYPE(lbot->val) != ATOM) error("non atom arg",FALSE);
159:
160: if ( (filp = fopen((lbot->val)->pname,"r")) == NULL)
161: errorh(Vermisc,"Can't open file",nil,FALSE,9797,lbot->val);
162:
163: domap = FALSE;
164: if ((handy = (lbot+1)->val) != nil )
165: {
166: if((TYPE(handy) != ATOM ) ||
167: (map = fopen(handy->pname,"w")) == NULL)
168: error("rfasl: can't open map file",FALSE);
169: else
170: { domap = TRUE;
171: fprintf(map,"Map of file %s\n",lbot->val->pname);
172: }
173: }
174:
175: printf("[fasl %s]",lbot->val->pname);
176: fflush(stdout);
177: svnp = np;
178:
179: lbot = np; /* set up base for later calls */
180:
181:
182: /* clear the ords in the symbol table */
183: for(i=0 ; i < SYMMAX ; i++) symbtb[i].ord = -1;
184:
185: if( fread(&exblk,sizeof(struct exec),1,filp) != 1)
186: error("Read failed",FALSE);
187:
188:
189: /* read in symbol table and set the ordinal values */
190:
191: fseek(filp,
192: (long)(32+exblk.a_text+exblk.a_data+exblk.a_trsize+exblk.a_drsize)
193: ,0);
194:
195: times = exblk.a_syms/sizeof(struct nlist);
196: if(debug) printf(" %d symbols in symbol table\n",times);
197:
198: for(i=0; i < times ; i++)
199: {
200: if( fread(&syml,sizeof(struct nlist),1,filp) != 1)
201:
202:
203: error("Symb tab read error",FALSE);
204:
205: if (syml.n_type == N_EXT)
206: {
207: for(j=0; j< SYMMAX; j++)
208: {
209: if((symbtb[j].ord < 0)
210: && strcmpn(symbtb[j].fnam,syml.n_name,8)==0)
211: { symbtb[j].ord = i;
212: if(debug)printf("symbol %s ord is %d\n",syml.n_name,i);
213: break;
214: };
215:
216: };
217:
218: if( j>=SYMMAX ) printf("Unknown symbol %s\n",syml.n_name);
219: }
220: else if (((ch = syml.n_name[0]) == 's')
221: || (ch == 'L')
222: || (ch == '.') ) ; /* skip this */
223: else if (syml.n_name[0] == 'F')
224: funloc[funcnt++] = syml.n_value; /* seeing function */
225: else if (!bindloc && (strcmp(syml.n_name, "BINDER") == 0))
226: bindloc = syml.n_value;
227: else if (strcmp(syml.n_name, "litstrt") == 0)
228: litstrt = syml.n_value;
229: else if (strcmp(syml.n_name, "litend") == 0)
230: litend = syml.n_value;
231: }
232:
233: /* check to make sure we are working with the right format */
234: if((litstrt == 0) || (litend == 0))
235: errorh(Vermisc,"File not in new fasl format",nil,FALSE,0,lbot->val);
236:
237: /*----------------*/
238:
239: /* read in text segment */
240:
241:
242: fseek(filp,(long)32,0);
243: segsiz = exblk.a_text + exblk.a_data;
244: if(fread(curps = (int) csegment(int_name,segsiz/sizeof(int))
245: ,1,exblk.a_text,filp) != exblk.a_text)
246: error("Read error in text and data read",FALSE);
247:
248: orgtx = curps;
249: orgdt = curps + exblk.a_text;
250:
251: linkstrt = orgdt + PRESIZ; /* start of linker table */
252: linkend = orgdt + exblk.a_data - 4; /* end of linker table */
253:
254: /* the object file is a 410 file and thus has seperate text and
255: data segments. The data is assumed to be loaded at the start
256: of the next PAGSIZ byte boundary, we must calculate the difference
257: between where the data segment begins and where the loader
258: thinks it begins. Caclulate by rounding up the text size and
259: seeing how much is skipped
260: */
261: segdif = ((exblk.a_text + PAGRND) & ~PAGRND) - exblk.a_text;
262: if(debug) printf("funcs %d, orgtx %x, orgdt %x, linkstrt %x, linkend %x segdif %x",
263: funcnt,orgtx,orgdt,linkstrt,linkend,segdif);
264:
265: /* set the linker table to all -1's so we can put in the gc table */
266: for( iptr = (int *)linkstrt ; iptr <= (int *)linkend ; iptr++)
267: *iptr = -1;
268:
269: /* copy in the prelud */
270: ppre = (struct prelud *) orgdt; /* use structure to copy */
271: *ppre = prel; /* copy over prelud */
272:
273: /* link our table into the gc tables */
274: *( ((int *)linkstrt) -1) = (int)bind_lists; /* point to current */
275: bind_lists = (lispval *) linkstrt;
276:
277: /* new relocate the necessary symbols in the text segment */
278:
279: orgps = orgtx;
280: fseek(filp,(long)(32+exblk.a_text+exblk.a_data),0);
281: times = (exblk.a_trsize)/sizeof(struct relocation_info);
282:
283: /* the only symbols we will relocate are references to lisp
284: 1) functions like _Lcons
285: 2) the symbol linker in the data segment
286:
287: type (1) can be recognized by extern and pcrel, while
288: type (2) can be recognized by !extern and pcrel and data segment
289: */
290:
291: for( i=1; i<=times ; i++)
292: {
293: if( fread(&reloc,sizeof(struct relocation_info),1,filp) != 1)
294: error("Bad text reloc read",FALSE);
295: if(reloc.r_extern && reloc.r_pcrel)
296: {
297: for(j=0; j < SYMMAX; j++)
298: {
299:
300: if(symbtb[j].ord == reloc.r_symbolnum) /* look for this sym */
301: {
302: if(debug) printf("Relocating %d (ord %d) at %x\n",
303: j, symbtb[j].ord, reloc.r_address);
304: *(int *)(orgps+reloc.r_address)
305: += symbtb[j].floc - orgtx;
306:
307: break;
308:
309: }
310: };
311: if( j >= SYMMAX) if(debug) printf("Couldnt find ord # %d\n",
312: reloc.r_symbolnum);
313: }
314: else if(!reloc.r_extern && reloc.r_pcrel &&
315: (reloc.r_symbolnum == N_DATA))
316: { if(debug) printf("relocing at addr %x \n",reloc.r_address);
317: *(int *)(orgps + reloc.r_address) -= segdif;
318: }
319:
320: }
321:
322: putchar('\n');
323: fflush(stdout);
324:
325: /* set up a fake port so we can read from core */
326: /* first find a free port */
327:
328: p = stdin;
329: for( ; p->_flag & (_IOREAD|_IOWRT) ; p++)
330: if( p >= _iob + _NFILE)
331: error(" No free file descriptor for fasl ",FALSE);
332:
333: p->_flag = _IOREAD | _IOSTRG;
334: p->_base = p->_ptr = (char *) (orgtx + litstrt); /* start at beginning of lit */
335: p->_cnt = litend - litstrt;
336:
337: if(debug)printf("litstrt %d, charstrt %d\n",litstrt, p->_base);
338: /* the first forms we wish to read are those literals in the
339: * literal table, that is those forms referenced by an offset
340: * from r8 in compiled code
341: */
342:
343: /* to read in the forms correctly, we must set up the read table
344: */
345: currtab = Vreadtable->clb;
346: Vreadtable->clb = strtab; /* standard read table */
347: curibase = ibase->clb;
348: ibase->clb = inewint(10); /* read in decimal */
349:
350: linktab = (lispval *)linkstrt;
351:
352: oldinitflag = initflag; /* remember current val */
353: initflag = TRUE; /* turn OFF gc */
354:
355: while (linktab < (lispval *)linkend)
356: {
357: np = svnp;
358: protect(P(p));
359: handy = Lread();
360: getc(p); /* eat trailing blank */
361: if(debug)
362: { printf("one form read: ");
363: printr(handy,stdout); fflush(stdout);
364: }
365: *linktab++ = handy;
366: }
367:
368: /* now process the binder table, which contains pointers to
369: functions to link in and forms to evaluate.
370: */
371: bindorg = (struct bindage *) (orgtx + bindloc);
372: funcnt = 0;
373: if(debug) printf("binding loc %d, orgin : %d\n",bindloc,bindorg);
374:
375: for( curbind = bindorg; curbind->b_type != -1 ; curbind++)
376: {
377: np = svnp;
378: protect(P(p));
379: rdform = Lread();
380: getc(p); /* eat trailing null */
381: protect(rdform);
382: if(curbind->b_type <= 2) /* if function type */
383: {
384: handy = newfunct();
385: rdform->fnbnd = handy;
386: handy->entry = (lispval (*)())(orgtx + funloc[funcnt++]);
387: handy->discipline =
388: (curbind->b_type == 0 ? lambda :
389: curbind->b_type == 1 ? nlambda :
390: macro);
391: if(domap) fprintf(map,"%s\n%x\n",rdform->pname,handy->entry);
392: }
393: else {
394: Vreadtable->clb = currtab;
395: ibase->clb = curibase;
396:
397: eval(rdform); /* otherwise eval it */
398:
399: curibase = ibase->clb;
400: ibase->clb = inewint(10);
401: Vreadtable->clb = strtab;
402: }
403: };
404:
405: p->_flag = 0; /* give up file descriptor */
406: initflag = oldinitflag; /* restore state of gc */
407: Vreadtable->clb = currtab;
408: chkrtab(currtab);
409: ibase->clb = curibase;
410:
411: fclose(filp);
412: if(domap) fclose(map);
413: return(tatom);
414: }
415:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.