|
|
1.1 root 1: /*
2: * Copyright (c) 1982 Regents of the University of California
3: */
4: #ifndef lint
5: static char sccsid[] = "@(#)assyms.c 4.14 8/11/83";
6: #endif not lint
7:
8: #include <stdio.h>
9: #include <ctype.h>
10: #include "as.h"
11: #include "asscan.h"
12: #include "assyms.h"
13:
14: /*
15: * Managers for chunks of symbols allocated from calloc()
16: * We maintain a linked list of such chunks.
17: *
18: */
19: struct allocbox *allochead; /*head of chunk list*/
20: struct allocbox *alloctail; /*tail*/
21: struct allocbox *newbox; /*for creating a new chunk*/
22: struct symtab *nextsym; /*next symbol free*/
23: int symsleft; /*slots left in current chunk*/
24:
25: struct symtab **symptrs;
26: struct symtab **symdelim[NLOC + NLOC +1];
27: struct symtab **symptrub;
28: /*
29: * Managers for the dynamically extendable hash table
30: */
31: struct hashdallop *htab;
32:
33: Iptr *itab[NINST]; /*maps opcodes to instructions*/
34: /*
35: * Counts what went into the symbol table, so that the
36: * size of the symbol table can be computed.
37: */
38: int nsyms; /* total number in the symbol table */
39: int njxxx; /* number of jxxx entrys */
40: int nforgotten; /* number of symbols erroneously entered */
41: int nlabels; /* number of label entries */
42:
43: /*
44: * Managers of the symbol literal storage.
45: */
46: struct strpool *strplhead = 0;
47:
48: symtabinit()
49: {
50: allochead = 0;
51: alloctail = 0;
52: nextsym = 0;
53: symsleft = 0;
54: strpoolalloc(); /* get the first strpool storage area */
55: htab = 0;
56: htaballoc(); /* get the first part of the hash table */
57: }
58:
59: /*
60: * Install all known instructions in the symbol table
61: */
62: syminstall()
63: {
64: register Iptr ip;
65: register struct symtab **hp;
66: register char *p1, *p2;
67: register int i;
68:
69: for (i = 0; i < NINST; i++)
70: itab[i] = (Iptr*)BADPOINT;
71:
72: for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) {
73: p1 = FETCHNAME(ip);
74: p2 = yytext;
75: while (*p2++ = *p1++);
76: hp = lookup(0); /* 0 => don't install this*/
77: if (*hp==NULL) {
78: *hp = (struct symtab *)ip;
79: if ( (ip->s_tag!=INSTn)
80: && (ip->s_tag!=INST0)
81: && (ip->s_tag!=0))
82: continue; /* was pseudo-op */
83: if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){
84: itab[ip->i_eopcode] =
85: (Iptr*)ClearCalloc(256, sizeof(Iptr));
86: for (i = 0; i < 256; i++)
87: itab[ip->i_eopcode][i] =
88: (Iptr)BADPOINT;
89: }
90: itab[ip->i_eopcode][ip->i_popcode] = ip;
91: }
92: }
93: } /*end of syminstall*/
94:
95: #define ISLABEL(sp) \
96: ( (!savelabels) \
97: && (sp->s_tag == LABELID) \
98: && (STRPLACE(sp) & STR_CORE) \
99: && (FETCHNAME(sp)[0] == 'L'))
100: /*
101: * Assign final values to symbols,
102: * and overwrite the index field with its relative position in
103: * the symbol table we give to the loader.
104: */
105: extern struct exec hdr;
106:
107: freezesymtab()
108: {
109: register struct symtab *sp;
110: long bs;
111: register int relpos = 0;
112: register struct symtab *ubsp;
113: register struct allocbox *allocwalk;
114:
115: DECLITERATE(allocwalk, sp, ubsp)
116: {
117: if (sp->s_tag >= IGNOREBOUND)
118: continue; /*totally ignore jxxx entries */
119: /*
120: * Ignore stabs, but give them a symbol table index
121: */
122: if (sp->s_type & STABFLAG)
123: goto assignindex;
124: if ((sp->s_type&XTYPE)==XUNDEF)
125: sp->s_type = XXTRN+XUNDEF;
126: else if ((sp->s_type&XTYPE)==XDATA)
127: sp->s_value += usedot[sp->s_index].e_xvalue;
128: else if ((sp->s_type&XTYPE)==XTEXT)
129: sp->s_value += usedot[sp->s_index].e_xvalue;
130: else if ((sp->s_type&XTYPE)==XBSS) {
131: bs = sp->s_value;
132: sp->s_value = hdr.a_bss + datbase;
133: hdr.a_bss += bs;
134: }
135: assignindex:
136: if (!ISLABEL(sp))
137: sp->s_index = relpos++;
138: }
139: }
140:
141: /*
142: * For all of the stabs that had their final value undefined during pass 1
143: * and during pass 2 assign a final value.
144: * We have already given stab entrys a initial approximation
145: * when we constsructed the sorted symbol table.
146: * Iteration order doesn't matter.
147: */
148:
149: stabfix()
150: {
151: register struct symtab *sp, **cosp;
152: register struct symtab *p;
153:
154: SYMITERATE(cosp, sp){
155: if(sp->s_ptype && (sp->s_type & STABFLAG)) {
156: p = sp->s_dest;
157: /*
158: * STABFLOATING indicates that the offset has been saved in s_desc, s_other
159: */
160: if(sp->s_tag == STABFLOATING) {
161: sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) );
162: sp->s_value = sp->s_value + p->s_value;
163: }
164: else sp->s_value = p->s_value;
165: sp->s_index = p->s_index;
166: sp->s_type = p->s_type;
167:
168:
169: }
170: }
171: }
172:
173: char *Calloc(number, size)
174: int number, size;
175: {
176: register char *newstuff;
177: char *sbrk();
178: newstuff = sbrk(number*size);
179: if ((int)newstuff == -1){
180: yyerror("Ran out of Memory");
181: delexit();
182: }
183: return(newstuff);
184: }
185:
186: char *ClearCalloc(number, size)
187: int number, size;
188: {
189: register char *newstuff; /* r11 */
190: register int length = number * size; /* r10 */
191: #ifdef lint
192: length = length;
193: #endif length
194: newstuff = Calloc(number, size);
195: asm("movc5 $0, (r0), $0, r10, (r11)");
196: return(newstuff);
197: }
198:
199: struct symtab *symalloc()
200: {
201: if (symsleft == 0){
202: newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
203: symsleft = SYMDALLOP;
204: nextsym = &newbox->symslots[0];
205: if (alloctail == 0){
206: allochead = alloctail = newbox;
207: } else {
208: alloctail->nextalloc = newbox;
209: alloctail = newbox;
210: }
211: }
212: --symsleft;
213: ++nsyms;
214: return(nextsym++);
215: }
216:
217: strpoolalloc()
218: {
219: register struct strpool *new;
220:
221: new = (struct strpool *)Calloc(1, sizeof (struct strpool));
222: new->str_nalloc = 0;
223: new->str_next = strplhead;
224: strplhead = new;
225: }
226:
227: symcmp(Pptr, Qptr)
228: struct symtab **Pptr, **Qptr;
229: {
230: register struct symtab *p = *Pptr;
231: register struct symtab *q = *Qptr;
232: if (p->s_index < q->s_index)
233: return(-1);
234: if (p->s_index > q->s_index)
235: return(1);
236: if (p->s_value < q->s_value)
237: return(-1);
238: if (p->s_value > q->s_value)
239: return(1);
240: /*
241: * Force jxxx entries to virtually preceed labels defined
242: * to follow the jxxxx instruction, so that bumping the
243: * jxxx instruction correctly fixes up the following labels
244: */
245: if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/
246: return(-1);
247: if (q->s_tag >= IGNOREBOUND)
248: return(1);
249: /*
250: * both are now just plain labels; the relative order doesn't
251: * matter. Both can't be jxxxes, as they would have different
252: * values.
253: */
254: return(0);
255: } /*end of symcmp*/
256:
257: /*
258: * We construct the auxiliary table of pointers, symptrs and
259: * symdelim
260: * We also assign preliminary values to stab entries that did not yet
261: * have an absolute value (because they initially referred to
262: * forward references). We don't worry about .stabds, as they
263: * already have an estimated final value
264: */
265:
266: sortsymtab()
267: {
268: register struct symtab *sp;
269: register struct symtab **cowalk;
270: register struct allocbox *allocwalk;
271: struct symtab *ubsp;
272: int segno;
273: int slotno;
274: int symsin; /*number put into symptrs*/
275:
276: symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
277: /*
278: * Allocate one word at the beginning of the symptr array
279: * so that backwards scans through the symptr array will
280: * work correctly while scanning through the zeroth segment
281: */
282: *symptrs++ = 0;
283: cowalk = symptrs;
284: symsin = 0;
285: DECLITERATE(allocwalk, sp, ubsp) {
286: if (sp->s_ptype && (sp->s_type &STABFLAG)){
287: sp->s_value = sp->s_dest->s_value;
288: sp->s_index = sp->s_dest->s_index;
289: }
290: if (symsin >= nsyms)
291: yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
292: *cowalk++ = sp;
293: symsin++;
294: }
295: if (symsin != nsyms)
296: yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
297: symsin, nsyms);
298: symptrub = &symptrs[nsyms ];
299: qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
300: symdelim[0] = symptrs;
301: for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
302: segno < NLOC + NLOC;
303: segno++, slotno++){
304: for (; sp && sp->s_index == segno; sp = *++cowalk);
305: symdelim[slotno] = cowalk; /*forms the ub delimeter*/
306: }
307: } /*end of sortsymtab*/
308:
309: #ifdef DEBUG
310: dumpsymtab()
311: {
312: register int segno;
313: register struct symtab *sp, **cosp, *ub;
314: char *tagstring();
315:
316: printf("Symbol Table dump:\n");
317: for (segno = 0; segno < NLOC + NLOC; segno++){
318: printf("Segment number: %d\n", segno);
319: SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
320: printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
321: segno, FETCHNAME(sp),
322: sp->s_value, sp->s_index,
323: tagstring(sp->s_tag));
324: printf("\t\ttype: %d jxbump %d jxfear: %d\n",
325: sp->s_type, sp->s_jxbump, sp->s_jxfear);
326: }
327: printf("\n\n");
328: }
329: }
330:
331: static char tagbuff[4];
332:
333: char *tagstring(tag)
334: unsigned char tag;
335: {
336: switch(tag){
337: case JXACTIVE: return("active");
338: case JXNOTYET: return("notyet");
339: case JXALIGN: return("align");
340: case JXQUESTIONABLE: return("jxquestionable");
341: case JXINACTIVE: return("inactive");
342: case JXTUNNEL: return("tunnel");
343: case OBSOLETE: return("obsolete");
344: case IGNOREBOUND: return("ignorebound");
345: case STABFLOATING: return("stabfloating");
346: case STABFIXED: return("stabfixed");
347: case LABELID: return("labelid");
348: case OKTOBUMP: return("oktobump");
349: case ISET: return("iset");
350: case ILSYM: return("ilsym");
351: default: sprintf(tagbuff,"%d", tag);
352: return(tagbuff);
353: }
354: }
355: #endif DEBUG
356:
357: htaballoc()
358: {
359: register struct hashdallop *new;
360: new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
361: if (htab == 0)
362: htab = new;
363: else { /* add AFTER the 1st slot */
364: new->h_next = htab->h_next;
365: htab->h_next = new;
366: }
367: }
368:
369: #define HASHCLOGGED (NHASH / 2)
370:
371: /*
372: * Lookup a symbol stored in extern yytext.
373: * All strings passed in via extern yytext had better have
374: * a trailing null. Strings are placed in yytext for hashing by
375: * syminstall() and by yylex();
376: *
377: * We take pains to avoid function calls; this functdion
378: * is called quite frequently, and the calls overhead
379: * in the vax contributes significantly to the overall
380: * execution speed of as.
381: */
382: struct symtab **lookup(instflg)
383: int instflg; /* 0: don't install */
384: {
385: static int initialprobe;
386: register struct symtab **hp;
387: register char *from;
388: register char *to;
389: register int len;
390: register int nprobes;
391: static struct hashdallop *hdallop;
392: static struct symtab **emptyslot;
393: static struct hashdallop *emptyhd;
394: static struct symtab **hp_ub;
395:
396: emptyslot = 0;
397: for (nprobes = 0, from = yytext;
398: *from;
399: nprobes <<= 2, nprobes += *from++)
400: continue;
401: nprobes += from[-1] << 5;
402: nprobes %= NHASH;
403: if (nprobes < 0)
404: nprobes += NHASH;
405:
406: initialprobe = nprobes;
407: for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
408: for (hp = &(hdallop->h_htab[initialprobe]),
409: nprobes = 1,
410: hp_ub = &(hdallop->h_htab[NHASH]);
411: (*hp) && (nprobes < NHASH);
412: hp += nprobes,
413: hp -= (hp >= hp_ub) ? NHASH:0,
414: nprobes += 2)
415: {
416: from = yytext;
417: to = FETCHNAME(*hp);
418: while (*from && *to)
419: if (*from++ != *to++)
420: goto nextprobe;
421: if (*to == *from) /*assert both are == 0*/
422: return(hp);
423: nextprobe: ;
424: }
425: if (*hp == 0 && emptyslot == 0 &&
426: hdallop->h_nused < HASHCLOGGED) {
427: emptyslot = hp;
428: emptyhd = hdallop;
429: }
430: }
431: if (emptyslot == 0) {
432: htaballoc();
433: hdallop = htab->h_next; /* aren't we smart! */
434: hp = &hdallop->h_htab[initialprobe];
435: } else {
436: hdallop = emptyhd;
437: hp = emptyslot;
438: }
439: if (instflg) {
440: *hp = symalloc();
441: hdallop->h_nused++;
442: for (from = yytext, len = 0; *from++; len++)
443: continue;
444: (*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH);
445: }
446: return(hp);
447: } /*end of lookup*/
448: /*
449: * save a string str with len in the places indicated by place
450: */
451: struct strdesc *savestr(str, len, place)
452: char *str;
453: int len;
454: int place;
455: {
456: reg struct strdesc *res;
457: int tlen;
458: /*
459: * Compute the total length of the record to live in core
460: */
461: tlen = sizeof(struct strdesc) - sizeof(res->sd_string);
462: if (place & STR_CORE)
463: tlen += len;
464: /*
465: * See if there is enough space for the record,
466: * and allocate the record.
467: */
468: if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc))
469: strpoolalloc();
470: res = (struct strdesc *)(strplhead->str_names + strplhead->str_nalloc);
471: /*
472: * Save the string information that is always present
473: */
474: res->sd_stroff = strfilepos;
475: res->sd_strlen = len;
476: res->sd_place = place;
477: /*
478: * Now, save the string itself. If str is null, then
479: * the characters have already been dumped to the file
480: */
481: if ((place & STR_CORE) && str)
482: movestr(res[0].sd_string, str, len);
483: if (place & STR_FILE){
484: if (str){
485: fwrite(str, 1, len, strfile);
486: }
487: strfilepos += len;
488: }
489: /*
490: * Adjust the in core string pool size
491: */
492: strplhead->str_nalloc += tlen;
493: return(res);
494: }
495: /*
496: * The relocation information is saved internally in an array of
497: * lists of relocation buffers. The relocation buffers are
498: * exactly the same size as a token buffer; if we use VM for the
499: * temporary file we reclaim this storage, otherwise we create
500: * them by mallocing.
501: */
502: #define RELBUFLG TOKBUFLG
503: #define NRELOC ((TOKBUFLG - \
504: (sizeof (int) + sizeof (struct relbufdesc *)) \
505: ) / (sizeof (struct relocation_info)))
506:
507: struct relbufdesc{
508: int rel_count;
509: struct relbufdesc *rel_next;
510: struct relocation_info rel_reloc[NRELOC];
511: };
512: extern struct relbufdesc *tok_free;
513: #define rel_free tok_free
514: static struct relbufdesc *rel_temp;
515: struct relocation_info r_can_1PC;
516: struct relocation_info r_can_0PC;
517:
518: initoutrel()
519: {
520: r_can_0PC.r_address = 0;
521: r_can_0PC.r_symbolnum = 0;
522: r_can_0PC.r_pcrel = 0;
523: r_can_0PC.r_length = 0;
524: r_can_0PC.r_extern = 0;
525:
526: r_can_1PC = r_can_0PC;
527: r_can_1PC.r_pcrel = 1;
528: }
529:
530: outrel(xp, reloc_how)
531: register struct exp *xp;
532: int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */
533: {
534: struct relocation_info reloc;
535: register int x_type_mask;
536: int pcrel;
537:
538: x_type_mask = xp->e_xtype & ~XFORW;
539: pcrel = reloc_how & RELOC_PCREL;
540: reloc_how &= ~RELOC_PCREL;
541:
542: if (bitoff&07)
543: yyerror("Padding error");
544: if (x_type_mask == XUNDEF)
545: yyerror("Undefined reference");
546:
547: if ( (x_type_mask != XABS) || pcrel ) {
548: if (ty_NORELOC[reloc_how])
549: yyerror("Illegal Relocation of floating or large int number.");
550: reloc = pcrel ? r_can_1PC : r_can_0PC;
551: reloc.r_address = dotp->e_xvalue -
552: ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
553: reloc.r_length = ty_nlg[reloc_how];
554: switch(x_type_mask){
555: case XXTRN | XUNDEF:
556: reloc.r_symbolnum = xp->e_xname->s_index;
557: reloc.r_extern = 1;
558: break;
559: default:
560: if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
561: x_type_mask = XTEXT | (x_type_mask&XXTRN);
562: reloc.r_symbolnum = x_type_mask;
563: break;
564: }
565: if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
566: if (rel_free){
567: rel_temp = rel_free;
568: rel_free = rel_temp->rel_next;
569: } else {
570: rel_temp = (struct relbufdesc *)
571: Calloc(1,sizeof (struct relbufdesc));
572: }
573: rel_temp->rel_count = 0;
574: rel_temp->rel_next = relfil;
575: relfil = rusefile[dotp - &usedot[0]] = rel_temp;
576: }
577: relfil->rel_reloc[relfil->rel_count++] = reloc;
578: }
579: /*
580: * write the unrelocated value to the text file
581: */
582: dotp->e_xvalue += ty_nbyte[reloc_how];
583: if (pcrel)
584: xp->e_xvalue -= dotp->e_xvalue;
585: switch(reloc_how){
586: case TYPO:
587: case TYPQ:
588:
589: case TYPF:
590: case TYPD:
591: case TYPG:
592: case TYPH:
593: bignumwrite(xp->e_number, reloc_how);
594: break;
595:
596: default:
597: bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
598: break;
599: }
600: }
601: /*
602: * Flush out all of the relocation information.
603: * Note that the individual lists of buffers are in
604: * reverse order, so we must reverse them
605: */
606: off_t closeoutrel(relocfile)
607: BFILE *relocfile;
608: {
609: int locindex;
610: u_long Closeoutrel();
611:
612: trsize = 0;
613: for (locindex = 0; locindex < NLOC; locindex++){
614: trsize += Closeoutrel(rusefile[locindex], relocfile);
615: }
616: drsize = 0;
617: for (locindex = 0; locindex < NLOC; locindex++){
618: drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
619: }
620: return(trsize + drsize);
621: }
622:
623: u_long Closeoutrel(relfil, relocfile)
624: struct relbufdesc *relfil;
625: BFILE *relocfile;
626: {
627: u_long tail;
628: if (relfil == 0)
629: return(0L);
630: tail = Closeoutrel(relfil->rel_next, relocfile);
631: bwrite((char *)&relfil->rel_reloc[0],
632: relfil->rel_count * sizeof (struct relocation_info),
633: relocfile);
634: return(tail + relfil->rel_count * sizeof (struct relocation_info));
635: }
636:
637: #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
638: int sizesymtab()
639: {
640: return (sizeof (struct nlist) * NOUTSYMS);
641: }
642: /*
643: * Write out n symbols to file f, beginning at p
644: * ignoring symbols that are obsolete, jxxx instructions, and
645: * possibly, labels
646: */
647: int symwrite(symfile)
648: BFILE *symfile;
649: {
650: int symsout; /*those actually written*/
651: int symsdesired = NOUTSYMS;
652: reg struct symtab *sp, *ub;
653: char *name; /* temp to save the name */
654: int totalstr;
655: /*
656: * We use sp->s_index to hold the length of the
657: * name; it isn't used for anything else
658: */
659: register struct allocbox *allocwalk;
660:
661: symsout = 0;
662: totalstr = sizeof(totalstr);
663: DECLITERATE(allocwalk, sp, ub) {
664: if (sp->s_tag >= IGNOREBOUND)
665: continue;
666: if (ISLABEL(sp))
667: continue;
668: symsout++;
669: name = sp->s_name; /* save pointer */
670: /*
671: * the length of the symbol table string
672: * always includes the trailing null;
673: * blast the pointer to its a.out value.
674: */
675: if (sp->s_name && (sp->s_index = STRLEN(sp))){
676: sp->s_nmx = totalstr;
677: totalstr += sp->s_index;
678: } else {
679: sp->s_nmx = 0;
680: }
681: if (sp->s_ptype != 0)
682: sp->s_type = sp->s_ptype;
683: else
684: sp->s_type = (sp->s_type & (~XFORW));
685: if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
686: sp->s_type = N_TEXT | (sp->s_type & N_EXT);
687: bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
688: sp->s_name = name; /* restore pointer */
689: }
690: if (symsout != symsdesired)
691: yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
692: symsout, symsdesired);
693: /*
694: * Construct the string pool from the symbols that were written,
695: * possibly fetching from the string file if the string
696: * is not core resident.
697: */
698: bwrite(&totalstr, sizeof(totalstr), symfile);
699: symsout = 0;
700: DECLITERATE(allocwalk, sp, ub) {
701: if (sp->s_tag >= IGNOREBOUND)
702: continue;
703: if (ISLABEL(sp))
704: continue;
705: symsout++;
706: if (STRLEN(sp) > 0){
707: if (STRPLACE(sp) & STR_CORE){
708: bwrite(FETCHNAME(sp), STRLEN(sp), symfile);
709: } else if (STRPLACE(sp) & STR_FILE){
710: char rbuf[2048];
711: int left, nread;
712: fseek(strfile, STROFF(sp), 0);
713: for (left = STRLEN(sp); left > 0; left -= nread){
714: nread = fread(rbuf, sizeof(char),
715: min(sizeof(rbuf), left), strfile);
716: if (nread == 0)
717: break;
718: bwrite(rbuf, nread, symfile);
719: }
720: }
721: }
722: }
723: if (symsout != symsdesired)
724: yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n",
725: symsout, symsdesired);
726: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.