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