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