Commit | Line | Data |
---|---|---|
629188b5 JR |
1 | /* Copyright (c) 1979 Regents of the University of California */ |
2 | #include <stdio.h> | |
3 | #include "as.h" | |
4 | #include "assyms.h" | |
5 | ||
6 | struct allocbox *allochead; | |
7 | struct allocbox *alloctail; | |
8 | struct symtab *nextsym; | |
9 | struct allocbox *newbox; | |
10 | char *namebuffer; | |
11 | int symsleft; | |
12 | ||
13 | symtabinit() | |
14 | { | |
15 | allochead = 0; | |
16 | alloctail = 0; | |
17 | nextsym = 0; | |
18 | symsleft = 0; | |
19 | } | |
20 | ||
21 | /* | |
22 | * Install all known instructions in the symbol table | |
23 | */ | |
24 | syminstall() | |
25 | { | |
26 | register struct instab *ip; | |
27 | register struct symtab **hp; | |
28 | register char *p1, *p2; | |
29 | ||
30 | for (ip=instab; ip->name[0]!=0; ip++) { | |
31 | p1 = ip->name; | |
32 | p2 = yytext; | |
33 | while (*p2++ = *p1++); | |
34 | hp = lookup(0); /* 0 => don't install this*/ | |
35 | if (*hp==NULL) { | |
36 | *hp = (struct symtab *)ip; | |
37 | if ( (ip->tag!=INSTn) | |
38 | && (ip->tag!=INST0) | |
39 | && (ip->tag!=0)) | |
40 | continue; /* was pseudo-op */ | |
41 | itab[ip->opcode & 0xFF] = ip; | |
42 | } | |
43 | } | |
44 | } /*end of syminstall*/ | |
45 | ||
46 | ||
47 | /* | |
48 | * Assign final values to symbols, | |
49 | * and overwrite the index field with its relative position in | |
50 | * the symbol table we give to the loader. | |
51 | */ | |
52 | extern struct hdr hdr; | |
53 | ||
54 | freezesymtab() | |
55 | { | |
56 | register struct symtab *sp; | |
57 | long bs; | |
58 | register int relpos = 0; | |
59 | #ifdef SORTEDOUTPUT | |
60 | register struct symtab **cosp; | |
61 | #else | |
62 | register struct symtab *ubsp; | |
63 | register struct allocbox *allocwalk; | |
64 | #endif | |
65 | ||
66 | #ifdef SORTEDOUTPUT | |
67 | SYMITERATE(cosp, sp) | |
68 | #else | |
69 | DECLITERATE(allocwalk, sp, ubsp) | |
70 | #endif | |
71 | { | |
72 | if (sp->tag >= IGNOREBOUND) | |
73 | continue; /*totally ignore jxxx entries */ | |
74 | /* | |
75 | * Ignore stabs, but give them a symbol table index | |
76 | */ | |
77 | if (sp->type & STABFLAG) | |
78 | goto assignindex; | |
79 | if ((sp->type&XTYPE)==XUNDEF) | |
80 | sp->type = XXTRN+XUNDEF; | |
81 | else if ((sp->type&XTYPE)==XDATA) | |
82 | sp->value += usedot[sp->index].xvalue; | |
83 | else if ((sp->type&XTYPE)==XTEXT) | |
84 | sp->value += usedot[sp->index].xvalue; | |
85 | else if ((sp->type&XTYPE)==XBSS) { | |
86 | bs = sp->value; | |
87 | sp->value = hdr.bsize + datbase; | |
88 | hdr.bsize += bs; | |
89 | } | |
90 | assignindex: | |
91 | if ( (sp->name[0] != 'L') | |
92 | || (sp->tag != LABELID) | |
93 | || savelabels | |
94 | ) /*then, we will write it later on*/ | |
95 | sp->index = relpos++; | |
96 | } | |
97 | } | |
98 | ||
99 | ||
100 | ||
101 | /* | |
102 | * For all of the stabs that had their final value undefined during pass 1 | |
103 | * and during pass 2 assign a final value. | |
104 | * We have already given stab entrys a initial approximation | |
105 | * when we constsructed the sorted symbol table. | |
106 | * Iteration order doesn't matter. | |
107 | */ | |
108 | stabfix() { | |
109 | register struct symtab *sp, **cosp; | |
110 | register struct symtab *p; | |
111 | ||
112 | SYMITERATE(cosp, sp){ | |
113 | if(sp->ptype && (sp->type & STABFLAG)) { | |
114 | p = sp->dest; | |
115 | sp->value = p->value; | |
116 | sp->index = p->index; | |
117 | sp->type = p->type; | |
118 | #ifdef DSTAB | |
119 | printf("STABFIX: %s (old %s) to %d offsets %d %d\n", | |
120 | sp->name, p->name, sp->value, sp, p); | |
121 | #endif | |
122 | } | |
123 | } | |
124 | } | |
125 | ||
126 | char *Calloc(number, size) | |
127 | int number, size; | |
128 | { | |
129 | register char *newstuff; | |
130 | newstuff = (char *)sbrk(number*size); | |
131 | if ((int)newstuff == -1){ | |
132 | yyerror("Ran out of Memory"); | |
133 | delexit(); | |
134 | } | |
135 | return(newstuff); | |
136 | } | |
137 | ||
138 | struct symtab * symalloc() | |
139 | { | |
140 | if (symsleft == 0){ | |
141 | register int *p; | |
142 | ||
143 | newbox = (struct allocbox *)Calloc(1,ALLOCQTY); | |
144 | symsleft = SYMDALLOP; | |
145 | nextsym = &newbox->symslots[0]; | |
146 | namebuffer = &newbox->symnames[0]; | |
147 | p = (int *)(&newbox->symnames[SYMDALLOP * NCPS]); | |
148 | while ( p > (int *)newbox){ | |
149 | *--p = 0; | |
150 | } | |
151 | if (alloctail == 0){ | |
152 | allochead = alloctail = newbox; | |
153 | } else { | |
154 | alloctail->nextalloc = newbox; | |
155 | alloctail = newbox; | |
156 | } | |
157 | } | |
158 | --symsleft; | |
159 | ++nsyms; | |
160 | nextsym->name = namebuffer; | |
161 | namebuffer += NCPS; | |
162 | return(nextsym++); | |
163 | } | |
164 | ||
165 | symcmp(pptr, qptr) | |
166 | struct symtab **pptr, **qptr; | |
167 | { | |
168 | register struct symtab *p = *pptr; | |
169 | register struct symtab *q = *qptr; | |
170 | if (p->index < q->index) | |
171 | return(-1); | |
172 | if (p->index > q->index) | |
173 | return(1); | |
174 | if (p->value < q->value) | |
175 | return(-1); | |
176 | if (p->value > q->value) | |
177 | return(1); | |
178 | /* | |
179 | * Force jxxx entries to virtually preceed labels defined | |
180 | * to follow the jxxxx instruction, so that bumping the | |
181 | * jxxx instruction correctly fixes up the following labels | |
182 | */ | |
183 | if (p->tag >= IGNOREBOUND) /*p points to a jxxx*/ | |
184 | return(-1); | |
185 | if (q->tag >= IGNOREBOUND) | |
186 | return(1); | |
187 | /* | |
188 | * both are now just plain labels; the relative order doesn't | |
189 | * matter. Both can't be jxxxes, as they would have different | |
190 | * values. | |
191 | */ | |
192 | return(0); | |
193 | } /*end of symcmp*/ | |
194 | ||
195 | /* | |
196 | * We construct the auxiliary table of pointers, symptrs and | |
197 | * symdelim | |
198 | * We also assign preliminary values to stab entries that did not yet | |
199 | * have an absolute value (because they initially referred to | |
200 | * forward references). We don't worry about .stabds, as they | |
201 | * already have an estimated final value | |
202 | */ | |
203 | ||
204 | sortsymtab() | |
205 | { | |
206 | register struct symtab *sp; | |
207 | register struct symtab **cowalk; | |
208 | register struct allocbox *allocwalk; | |
209 | struct symtab *ubsp; | |
210 | int segno; | |
211 | int slotno; | |
212 | int symsin; /*number put into symptrs*/ | |
213 | ||
214 | symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs); | |
215 | /* | |
216 | * Allocate one word at the beginning of the symptr array | |
217 | * so that backwards scans through the symptr array will | |
218 | * work correctly while scanning through the zeroth segment | |
219 | */ | |
220 | *symptrs++ = 0; | |
221 | cowalk = symptrs; | |
222 | symsin = 0; | |
223 | DECLITERATE(allocwalk, sp, ubsp) { | |
224 | if (sp->ptype && (sp->type &STABFLAG)){ | |
225 | sp->value = sp->dest->value; | |
226 | sp->index = sp->dest->index; | |
227 | } | |
228 | if (symsin >= nsyms) | |
229 | yyerror("INTERNAL ERROR: overfilled symbol table indirection table"); | |
230 | *cowalk++ = sp; | |
231 | symsin++; | |
232 | } | |
233 | if (symsin != nsyms) | |
234 | yyerror("INTERNAL ERROR: installed %d syms, should have installed %d", | |
235 | symsin, nsyms); | |
236 | symptrub = &symptrs[nsyms ]; | |
237 | qsort(symptrs, nsyms, sizeof *symptrs, symcmp); | |
238 | symdelim[0] = symptrs; | |
239 | for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1; | |
240 | segno < NLOC + NLOC; | |
241 | segno++, slotno++){ | |
242 | for (; sp && sp->index == segno; sp = *++cowalk); | |
243 | symdelim[slotno] = cowalk; /*forms the ub delimeter*/ | |
244 | } | |
245 | } /*end of sortsymtab*/ | |
246 | ||
247 | #ifdef DEBUG | |
248 | dumpsymtab() | |
249 | { | |
250 | register int segno; | |
251 | register struct symtab *sp, **cosp, *ub; | |
252 | char *tagstring(); | |
253 | ||
254 | printf("Symbol Table dump:\n"); | |
255 | for (segno = 0; segno < NLOC + NLOC; segno++){ | |
256 | printf("Segment number: %d\n", segno); | |
257 | SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){ | |
258 | printf("\tSeg: %d \"%8.8s\" value: %d index: %d tag %s\n", | |
259 | segno, sp->name, sp->value, sp->index, tagstring(sp->tag)); | |
260 | printf("\t\ttype: %d jxbump %d jxfear: %d\n", | |
261 | sp->type, sp->jxbump, sp->jxfear); | |
262 | } | |
263 | printf("\n\n"); | |
264 | } | |
265 | } | |
266 | ||
267 | static char tagbuff[4]; | |
268 | ||
269 | char *tagstring(tag) | |
270 | unsigned char tag; | |
271 | { | |
272 | switch(tag){ | |
273 | case JXACTIVE: return("active"); | |
274 | case JXNOTYET: return("notyet"); | |
275 | case JXALIGN: return("align"); | |
276 | case JXQUESTIONABLE: return("jxquestionable"); | |
277 | case JXINACTIVE: return("inactive"); | |
278 | case JXTUNNEL: return("tunnel"); | |
279 | case OBSOLETE: return("obsolete"); | |
280 | case IGNOREBOUND: return("ignorebound"); | |
281 | case STABFLOATING: return("stabfloating"); | |
282 | case STABFIXED: return("stabfixed"); | |
283 | case LABELID: return("labelid"); | |
284 | case OKTOBUMP: return("oktobump"); | |
285 | case ISET: return("iset"); | |
286 | case ILSYM: return("ilsym"); | |
287 | default: sprintf(tagbuff,"%d", tag); | |
288 | return(tagbuff); | |
289 | } | |
290 | } | |
291 | #endif | |
292 | ||
293 | #define HASHCLOGGED (NHASH * 3 ) / 4 | |
294 | ||
295 | struct symtab **lookup(instflg) | |
296 | int instflg; /* 0: don't install */ | |
297 | { | |
298 | register int ihash; | |
299 | register struct symtab **hp; | |
300 | register char *p1, *p2; | |
301 | register int i; | |
302 | ||
303 | #ifdef METRIC | |
304 | nhashed++; | |
305 | #endif | |
306 | ||
307 | /* | |
308 | * All strings passed in in yytext had better have | |
309 | * a trailing null. Strings are placed in yytext for | |
310 | * hashing by syminstall() and yylex() | |
311 | */ | |
312 | for (ihash = 0, p1 = yytext ; *p1; ihash <<= 2, ihash += *p1++); | |
313 | ihash += p1[-1] << 5; | |
314 | ihash %= NHASH; | |
315 | if (ihash < 0) ihash += NHASH; | |
316 | hp = &hshtab[ihash]; | |
317 | ihash = 1; /*now, it counts the number of times we rehash*/ | |
318 | while (*hp) { | |
319 | p1 = yytext; | |
320 | p2 = (*hp)->name; | |
321 | for (i = 0; (i<NCPS) && *p1; i++) | |
322 | if (*p1++ != *p2++) | |
323 | goto no; | |
324 | if (i >= NCPS) /*both symbols are maximal length*/ | |
325 | return(hp); | |
326 | if (*p2 == 0) /*assert *p1 == 0*/ | |
327 | return(hp); | |
328 | no: | |
329 | #ifdef METRIC | |
330 | nhcollisions++; | |
331 | #endif | |
332 | hp += ihash; | |
333 | ihash += 2; | |
334 | if (hp >= &hshtab[NHASH]) | |
335 | hp -= NHASH; | |
336 | } | |
337 | if(++hshused >= HASHCLOGGED) { | |
338 | yyerror("Symbol table overflow"); | |
339 | delexit(); | |
340 | } | |
341 | if (instflg) { | |
342 | #ifdef METRIC | |
343 | nentered++; | |
344 | #endif | |
345 | *hp = symalloc(); | |
346 | p1 = yytext; | |
347 | p2 = (*hp)->name; | |
348 | while (*p2++ = *p1++); | |
349 | } | |
350 | return(hp); | |
351 | } /*end of symlook*/ | |
352 | ||
353 | #ifdef vax | |
354 | #define writel(p,n,f) fwrite((long)p, sizeof (long), n, f) | |
355 | #else | |
356 | writel(p,n,f) | |
357 | long *p; | |
358 | FILE *f; | |
359 | { | |
360 | while (n--) { | |
361 | fwrite(&(*p).loword,2,1,f); | |
362 | fwrite(&(*p).hiword,2,1,f); | |
363 | p++; | |
364 | } | |
365 | } | |
366 | #endif | |
367 | ||
368 | int reflen[] = {0,0,1,1,2,2,4,4,8,8}; | |
369 | ||
370 | /* | |
371 | * Save the relocation information | |
372 | */ | |
373 | outrel(pval,reftype,reltype,xsym) | |
374 | long *pval; | |
375 | register int reftype,reltype; | |
376 | struct symtab *xsym; | |
377 | { | |
378 | ||
379 | /* | |
380 | * reftype: PCREL or not, plus length LEN1, LEN2, LEN4, LEN8 | |
381 | * reltype: csect ("segment") number (XTEXT, XDATA, ...) associated with 'val' | |
382 | * xsym: symbol table pointer | |
383 | */ | |
384 | long ts; | |
385 | char tc; | |
386 | long tl; | |
387 | short t; | |
388 | if (passno!=2) { | |
389 | dotp->xvalue += reflen[reftype]; | |
390 | return; | |
391 | } | |
392 | if (bitoff&07) | |
393 | yyerror("Padding error"); | |
394 | reltype &= ~XFORW; | |
395 | if (reltype == XUNDEF) | |
396 | yyerror("Undefined reference"); | |
397 | if (reltype != XABS || reftype & PCREL) { | |
398 | /* write the address portion of a relocation datum */ | |
399 | if (dotp >= &usedot[NLOC]) { | |
400 | hdr.drsize += sizeof(dotp->xvalue) + 3 + sizeof tc; | |
401 | tl = dotp->xvalue-datbase; | |
402 | writel(&tl,1,relfil); | |
403 | } else { | |
404 | hdr.trsize += sizeof(dotp->xvalue) + 3 + sizeof tc; | |
405 | writel(&dotp->xvalue,1,relfil); | |
406 | } | |
407 | /* write the properties portion of a relocation datum */ | |
408 | if (reltype == XXTRN+XUNDEF) { | |
409 | ts = (xsym->index); | |
410 | tc = (XXTRN<<3) | (reftype-LEN1); | |
411 | } else if ((reltype&XTYPE) == XUNDEFO) { | |
412 | ts = (xsym->index); | |
413 | tc = ((XXTRN+2)<<3) | (reftype-LEN1); | |
414 | } else { | |
415 | ts = (reltype); | |
416 | tc = (reftype-LEN1); | |
417 | } | |
418 | fwrite((char *)&ts, 3, 1, relfil); | |
419 | fwrite(&tc, sizeof(tc), 1, relfil); | |
420 | } | |
421 | /* write the raw ("unrelocated") value to the text file */ | |
422 | t = reflen[reftype]; | |
423 | dotp->xvalue += t; | |
424 | if (reftype & PCREL) | |
425 | *pval -= dotp->xvalue; | |
426 | #ifdef vax | |
427 | fwrite(pval,1,t,txtfil); | |
428 | #else | |
429 | if (t>2) { | |
430 | fwrite(&((*pval).loword),1,2,txtfil); | |
431 | fwrite(&((*pval).hiword),1,t-2,txtfil); | |
432 | } else fwrite(&((*pval).loword),1,t,txtfil); | |
433 | #endif | |
434 | } | |
435 | ||
436 | ||
437 | /* | |
438 | * Write out n symbols to file f, beginning at p | |
439 | * ignoring symbols that are obsolete, jxxx instructions, and | |
440 | * possibly, labels | |
441 | */ | |
442 | ||
443 | int sizesymtab() | |
444 | { | |
445 | struct symtab *sp; | |
446 | ||
447 | #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) | |
448 | ||
449 | return ( | |
450 | ( NCPS | |
451 | + sizeof (sp->ptype) | |
452 | + sizeof (sp->other) | |
453 | + sizeof (sp->desc) | |
454 | + sizeof (sp->value) | |
455 | ) | |
456 | * NOUTSYMS | |
457 | ); | |
458 | } | |
459 | ||
460 | symwrite(f) | |
461 | FILE *f; | |
462 | { | |
463 | int symsout; /*those actually written*/ | |
464 | int symsdesired = NOUTSYMS; | |
465 | register struct symtab *sp, *ub; | |
466 | #ifdef SORTEDOUTPUT | |
467 | int segno; | |
468 | register struct symtab **copointer; | |
469 | #else | |
470 | register struct allocbox *allocwalk; | |
471 | #endif | |
472 | ||
473 | #ifdef SORTEDOUTPUT | |
474 | for (segno = 0, symsout = 0; segno < NLOC + NLOC; segno++) | |
475 | SEGITERATE(segno, 0, 0, copointer, sp, ub, ++) | |
476 | #else | |
477 | symsout = 0; | |
478 | DECLITERATE(allocwalk, sp, ub) | |
479 | #endif | |
480 | { | |
481 | if (sp->tag >= IGNOREBOUND) | |
482 | continue; | |
483 | if ((sp->name[0] == 'L') && (sp->tag == LABELID) && !savelabels) | |
484 | continue; | |
485 | symsout++; | |
486 | fwrite(sp->name, NCPS, 1, f); | |
487 | sp->type &= ~XFORW; | |
488 | fwrite((sp->ptype) ? (char *)(&(sp->ptype)) : (char *)(&(sp->type)), | |
489 | sizeof(char), 1, f); | |
490 | /* | |
491 | * WATCH OUT. THIS DEPENDS THAT THE ALLOCATION OF | |
492 | * the four fields ptype, other, desc and value are | |
493 | * contiguous. This may have to be changed! | |
494 | * This is safe (as of 2-Nov-79). | |
495 | */ | |
496 | fwrite(&(sp->other), | |
497 | sizeof (sp->other) | |
498 | + sizeof (sp->desc) | |
499 | + sizeof (sp->value), 1, f | |
500 | ); | |
501 | #ifdef fooie | |
502 | #ifdef vax | |
503 | fwrite(&(sp->name[0]), sizeof(symtab[0].name), 1, f); | |
504 | fwrite(sp->ptype ? &(sp->ptype) : &(sp->type), | |
505 | sizeof(symtab[0].type), 1, f); | |
506 | fwrite(&(sp->other), sizeof(symtab[0].other), 1, f); | |
507 | fwrite(&(sp->desc), sizeof(symtab[0].desc), 1, f); | |
508 | fwrite(&(sp->value), sizeof(symtab[0].value), 1, f); | |
509 | #else | |
510 | writel(&(p->value), 1, f); | |
511 | #endif | |
512 | #endif | |
513 | } | |
514 | if (symsout != symsdesired) | |
515 | yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", | |
516 | symsout, symsdesired); | |
517 | } | |
518 | ||
519 | Flushfield(n) | |
520 | register int n; | |
521 | { | |
522 | while (n>0) { | |
523 | outb(bitfield); | |
524 | bitfield >>= 8; | |
525 | n -= 8; | |
526 | } | |
527 | bitoff=0; | |
528 | bitfield=0; | |
529 | } |