xref: /csrg-svn/old/as.tahoe/assyms.c (revision 32438)
132437Sbostic /*
232437Sbostic  *	Copyright (c) 1982 Regents of the University of California
332437Sbostic  */
432437Sbostic #ifndef lint
532437Sbostic static char sccsid[] = "@(#)assyms.c 4.14 8/11/83";
632437Sbostic #endif not lint
732437Sbostic 
832437Sbostic #include <stdio.h>
932437Sbostic #include <ctype.h>
1032437Sbostic #include "as.h"
1132437Sbostic #include "asscan.h"
1232437Sbostic #include "assyms.h"
1332437Sbostic 
1432437Sbostic /*
1532437Sbostic  *	Managers for chunks of symbols allocated from calloc()
1632437Sbostic  *	We maintain a linked list of such chunks.
1732437Sbostic  *
1832437Sbostic  */
1932437Sbostic struct	allocbox	*allochead;	/*head of chunk list*/
2032437Sbostic struct	allocbox	*alloctail;	/*tail*/
2132437Sbostic struct	allocbox	*newbox;	/*for creating a new chunk*/
2232437Sbostic struct	symtab		*nextsym;	/*next symbol free*/
2332437Sbostic int			symsleft;	/*slots left in current chunk*/
2432437Sbostic 
2532437Sbostic struct	symtab		**symptrs;
2632437Sbostic struct	symtab		**symdelim[NLOC + NLOC +1];
2732437Sbostic struct	symtab		**symptrub;
2832437Sbostic /*
2932437Sbostic  *	Managers for the dynamically extendable hash table
3032437Sbostic  */
3132437Sbostic struct	hashdallop	*htab;
3232437Sbostic 
3332437Sbostic Iptr	itab[NINST];	/*maps opcodes to instructions*/
3432437Sbostic /*
3532437Sbostic  *	Counts what went into the symbol table, so that the
3632437Sbostic  *	size of the symbol table can be computed.
3732437Sbostic  */
3832437Sbostic int	nsyms;		/* total number in the symbol table */
3932437Sbostic int	njxxx;		/* number of jxxx entrys */
4032437Sbostic int	nforgotten;	/* number of symbols erroneously entered */
4132437Sbostic int	nlabels;	/* number of label entries */
4232437Sbostic 
4332437Sbostic /*
4432437Sbostic  *	Managers of the symbol literal storage.
4532437Sbostic  */
4632437Sbostic struct	strpool		*strplhead = 0;
4732437Sbostic 
symtabinit()4832437Sbostic symtabinit()
4932437Sbostic {
5032437Sbostic 	allochead = 0;
5132437Sbostic 	alloctail = 0;
5232437Sbostic 	nextsym = 0;
5332437Sbostic 	symsleft = 0;
5432437Sbostic 	strpoolalloc();		/* get the first strpool storage area */
5532437Sbostic 	htab = 0;
5632437Sbostic 	htaballoc();		/* get the first part of the hash table */
5732437Sbostic }
5832437Sbostic 
5932437Sbostic /*
6032437Sbostic  *	Install all known instructions in the symbol table
6132437Sbostic  */
syminstall()6232437Sbostic syminstall()
6332437Sbostic {
6432437Sbostic 	register	Iptr	ip;
6532437Sbostic 	register	struct	symtab	**hp;
6632437Sbostic 	register	char	*p1, *p2;
6732437Sbostic 	register	int	i;
6832437Sbostic 
6932437Sbostic 	for (i = 0; i < NINST; i++)
7032437Sbostic 		itab[i] = (Iptr)0xAAAAAAAA;
7132437Sbostic 
7232437Sbostic 	for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) {
7332437Sbostic 		p1 = FETCHNAME(ip);
7432437Sbostic 		p2 = yytext;
7532437Sbostic 		while (*p2++ = *p1++);
7632437Sbostic 		hp = lookup(0);		/* 0 => don't install this*/
7732437Sbostic 		if (*hp==NULL) {
7832437Sbostic 			*hp = (struct symtab *)ip;
7932437Sbostic 			if (   (ip->s_tag!=INSTn)
8032437Sbostic 			    && (ip->s_tag!=INST0)
8132437Sbostic 			    && (ip->s_tag!=0))
8232437Sbostic 				continue; /* was pseudo-op */
8332437Sbostic 			itab[ip->i_opcode & 0xFF] = ip;
8432437Sbostic 		}
8532437Sbostic 	}
8632437Sbostic }	/*end of syminstall*/
8732437Sbostic 
8832437Sbostic #define ISLABEL(sp) \
8932437Sbostic 	(   (!savelabels) \
9032437Sbostic 	 && (sp->s_tag == LABELID) \
9132437Sbostic 	 && (STRPLACE(sp) & STR_CORE) \
9232437Sbostic 	 && (FETCHNAME(sp)[0] == 'L'))
9332437Sbostic /*
9432437Sbostic  *	Assign final values to symbols,
9532437Sbostic  *	and overwrite the index field with its relative position in
9632437Sbostic  *	the symbol table we give to the loader.
9732437Sbostic  */
9832437Sbostic extern struct exec hdr;
9932437Sbostic 
freezesymtab()10032437Sbostic freezesymtab()
10132437Sbostic {
10232437Sbostic 	register	struct	symtab	*sp;
10332437Sbostic 				long	bs;
10432437Sbostic 	register	int	relpos = 0;
10532437Sbostic 	register	struct	symtab		*ubsp;
10632437Sbostic 	register	struct	allocbox	*allocwalk;
10732437Sbostic 
10832437Sbostic 	DECLITERATE(allocwalk, sp, ubsp)
10932437Sbostic 	{
11032437Sbostic 		if (sp->s_tag >= IGNOREBOUND)
11132437Sbostic 			continue; 		/*totally ignore jxxx entries */
11232437Sbostic 		/*
11332437Sbostic 		 *	Ignore stabs, but give them a symbol table index
11432437Sbostic 		 */
11532437Sbostic 		if (sp->s_type & STABFLAG)
11632437Sbostic 			goto assignindex;
11732437Sbostic 		if ((sp->s_type&XTYPE)==XUNDEF)
11832437Sbostic 			sp->s_type = XXTRN+XUNDEF;
11932437Sbostic 		else if ((sp->s_type&XTYPE)==XDATA)
12032437Sbostic 			sp->s_value += usedot[sp->s_index].e_xvalue;
12132437Sbostic 		else if ((sp->s_type&XTYPE)==XTEXT)
12232437Sbostic 			sp->s_value += usedot[sp->s_index].e_xvalue;
12332437Sbostic 		else if ((sp->s_type&XTYPE)==XBSS) {
12432437Sbostic 			bs = sp->s_value;
12532437Sbostic 			sp->s_value = hdr.a_bss + datbase;
12632437Sbostic 			hdr.a_bss += bs;
12732437Sbostic 		}
12832437Sbostic 	   assignindex:
12932437Sbostic 		if (!ISLABEL(sp))
13032437Sbostic 			sp->s_index = relpos++;
13132437Sbostic 	}
13232437Sbostic }
13332437Sbostic 
13432437Sbostic /*
13532437Sbostic  *	For all of the stabs that had their final value undefined during pass 1
13632437Sbostic  *	and during pass 2 assign a final value.
13732437Sbostic  *	We have already given stab entrys a initial approximation
13832437Sbostic  *	when we constsructed the sorted symbol table.
13932437Sbostic  *	Iteration order doesn't matter.
14032437Sbostic  */
14132437Sbostic 
stabfix()14232437Sbostic stabfix()
14332437Sbostic {
14432437Sbostic 	register struct symtab *sp, **cosp;
14532437Sbostic 	register struct symtab *p;
14632437Sbostic 
14732437Sbostic 	SYMITERATE(cosp, sp){
14832437Sbostic 		if(sp->s_ptype && (sp->s_type & STABFLAG)) {
14932437Sbostic 			p = sp->s_dest;
15032437Sbostic /*
15132437Sbostic  * STABFLOATING indicates that the offset has been saved in s_desc, s_other
15232437Sbostic  */
15332437Sbostic 			if(sp->s_tag == STABFLOATING) {
15432437Sbostic 			  sp->s_value = ( ( ((unsigned char) sp->s_other) << 16)  					| ( (unsigned short) sp->s_desc )  );
15532437Sbostic 			  sp->s_value = sp->s_value + p->s_value;
15632437Sbostic 			}
15732437Sbostic 			else sp->s_value = p->s_value;
15832437Sbostic 			sp->s_index = p->s_index;
15932437Sbostic 			sp->s_type = p->s_type;
16032437Sbostic 
16132437Sbostic 
16232437Sbostic 		}
16332437Sbostic 	}
16432437Sbostic }
16532437Sbostic 
Calloc(number,size)16632437Sbostic char *Calloc(number, size)
16732437Sbostic 	int	number, size;
16832437Sbostic {
16932437Sbostic 	register	char *newstuff;
17032437Sbostic 	char	*sbrk();
17132437Sbostic 	newstuff = sbrk(number*size);
17232437Sbostic 	if ((int)newstuff == -1){
17332437Sbostic 		yyerror("Ran out of Memory");
17432437Sbostic 		delexit();
17532437Sbostic 	}
17632437Sbostic 	return(newstuff);
17732437Sbostic }
17832437Sbostic 
ClearCalloc(number,size)17932437Sbostic char *ClearCalloc(number, size)
18032437Sbostic 	int	number, size;
18132437Sbostic {
18232437Sbostic 	register	char	*newstuff;		/* r11 */
18332437Sbostic 	register	int	length = number * size;	/* r10 */
18432437Sbostic #ifdef lint
18532437Sbostic 	length = length;
18632437Sbostic #endif length
18732437Sbostic 	newstuff = Calloc(number, size);
18832437Sbostic 	strncpy (newstuff, "\0", length);
18932437Sbostic 	return(newstuff);
19032437Sbostic }
19132437Sbostic 
symalloc()19232437Sbostic struct symtab *symalloc()
19332437Sbostic {
19432437Sbostic 	if (symsleft == 0){
19532437Sbostic 		newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
19632437Sbostic 		symsleft = SYMDALLOP;
19732437Sbostic 		nextsym = &newbox->symslots[0];
19832437Sbostic 		if (alloctail == 0){
19932437Sbostic 			allochead = alloctail = newbox;
20032437Sbostic 		} else {
20132437Sbostic 			alloctail->nextalloc = newbox;
20232437Sbostic 			alloctail = newbox;
20332437Sbostic 		}
20432437Sbostic 	}
20532437Sbostic 	--symsleft;
20632437Sbostic 	++nsyms;
20732437Sbostic 	return(nextsym++);
20832437Sbostic }
20932437Sbostic 
strpoolalloc()21032437Sbostic strpoolalloc()
21132437Sbostic {
21232437Sbostic 	register	struct	strpool	*new;
21332437Sbostic 
21432437Sbostic 	new = (struct strpool *)Calloc(1, sizeof (struct strpool));
21532437Sbostic 	new->str_nalloc = 0;
21632437Sbostic 	new->str_next = strplhead;
21732437Sbostic 	strplhead = new;
21832437Sbostic }
21932437Sbostic 
22032437Sbostic symcmp(Pptr, Qptr)
22132437Sbostic 	struct symtab **Pptr, **Qptr;
22232437Sbostic {
22332437Sbostic 	register struct symtab *p = *Pptr;
22432437Sbostic 	register struct symtab *q = *Qptr;
22532437Sbostic 	if (p->s_index < q->s_index)
22632437Sbostic 		return(-1);
22732437Sbostic 	if (p->s_index > q->s_index)
22832437Sbostic 		return(1);
22932437Sbostic 	if (p->s_value < q->s_value)
23032437Sbostic 		return(-1);
23132437Sbostic 	if (p->s_value > q->s_value)
23232437Sbostic 		return(1);
23332437Sbostic 	/*
23432437Sbostic 	 *	Force jxxx entries to virtually preceed labels defined
23532437Sbostic 	 *	to follow the jxxxx instruction, so that bumping the
23632437Sbostic 	 *	jxxx instruction correctly fixes up the following labels
23732437Sbostic 	 */
23832437Sbostic 	if (p->s_tag >= IGNOREBOUND)	/*p points to a jxxx*/
23932437Sbostic 		return(-1);
24032437Sbostic 	if (q->s_tag >= IGNOREBOUND)
24132437Sbostic 		return(1);
24232437Sbostic 	/*
24332437Sbostic 	 *	both are now just plain labels; the relative order doesn't
24432437Sbostic 	 *	matter.  Both can't be jxxxes, as they would have different
24532437Sbostic 	 *	values.
24632437Sbostic 	 */
24732437Sbostic 	return(0);
24832437Sbostic }	/*end of symcmp*/
24932437Sbostic 
25032437Sbostic /*
25132437Sbostic  *	We construct the auxiliary table of pointers, symptrs and
25232437Sbostic  *	symdelim
25332437Sbostic  *	We also assign preliminary values to stab entries that did not yet
25432437Sbostic  *	have an absolute value (because they initially referred to
25532437Sbostic  *	forward references). We don't worry about .stabds, as they
25632437Sbostic  *	already have an estimated final value
25732437Sbostic  */
25832437Sbostic 
sortsymtab()25932437Sbostic sortsymtab()
26032437Sbostic {
26132437Sbostic 	register	struct	symtab	*sp;
26232437Sbostic 	register	struct	symtab	**cowalk;
26332437Sbostic 	register	struct	allocbox	*allocwalk;
26432437Sbostic 			struct	symtab	*ubsp;
26532437Sbostic 				int	segno;
26632437Sbostic 				int	slotno;
26732437Sbostic 				int	symsin;	/*number put into symptrs*/
26832437Sbostic 
26932437Sbostic 	symptrs =  (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
27032437Sbostic 	/*
27132437Sbostic 	 *	Allocate one word at the beginning of the symptr array
27232437Sbostic 	 *	so that backwards scans through the symptr array will
27332437Sbostic 	 *	work correctly while scanning through the zeroth segment
27432437Sbostic 	 */
27532437Sbostic 	*symptrs++ = 0;
27632437Sbostic 	cowalk = symptrs;
27732437Sbostic 	symsin = 0;
27832437Sbostic 	DECLITERATE(allocwalk, sp, ubsp) {
27932437Sbostic 		if (sp->s_ptype && (sp->s_type &STABFLAG)){
28032437Sbostic 			sp->s_value = sp->s_dest->s_value;
28132437Sbostic 			sp->s_index = sp->s_dest->s_index;
28232437Sbostic 		}
28332437Sbostic 		if (symsin >= nsyms)
28432437Sbostic 			yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
28532437Sbostic 		*cowalk++ = sp;
28632437Sbostic 		symsin++;
28732437Sbostic 	}
28832437Sbostic 	if (symsin != nsyms)
28932437Sbostic 		yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
29032437Sbostic 			symsin, nsyms);
29132437Sbostic 	symptrub = &symptrs[nsyms ];
29232437Sbostic 	qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
29332437Sbostic 	symdelim[0] = symptrs;
29432437Sbostic 	for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
29532437Sbostic 	     segno < NLOC + NLOC;
29632437Sbostic 	     segno++, slotno++){
29732437Sbostic 		for (; sp && sp->s_index == segno; sp = *++cowalk);
29832437Sbostic 		symdelim[slotno] = cowalk;	/*forms the ub delimeter*/
29932437Sbostic 	}
30032437Sbostic }	/*end of sortsymtab*/
30132437Sbostic 
30232437Sbostic #ifdef DEBUG
dumpsymtab()30332437Sbostic dumpsymtab()
30432437Sbostic {
30532437Sbostic 	register	int	segno;
30632437Sbostic 	register	struct symtab *sp, **cosp, *ub;
30732437Sbostic 	char		*tagstring();
30832437Sbostic 
30932437Sbostic 	printf("Symbol Table dump:\n");
31032437Sbostic 	for (segno = 0; segno < NLOC + NLOC; segno++){
31132437Sbostic 		printf("Segment number: %d\n", segno);
31232437Sbostic 		SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
31332437Sbostic 			printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
31432437Sbostic 				segno, sp->s_name ? FETCHNAME(sp) : "(NULL)",
31532437Sbostic 				sp->s_value, sp->s_index,
31632437Sbostic 				tagstring(sp->s_tag));
31732437Sbostic 			printf("\t\ttype: %d jxbump %d jxfear: %d\n",
31832437Sbostic 				sp->s_type, sp->s_jxbump, sp->s_jxfear);
31932437Sbostic 		}
32032437Sbostic 		printf("\n\n");
32132437Sbostic 	}
32232437Sbostic }
32332437Sbostic 
32432437Sbostic static	char tagbuff[4];
32532437Sbostic 
tagstring(tag)32632437Sbostic char *tagstring(tag)
32732437Sbostic 	unsigned	char	tag;
32832437Sbostic {
32932437Sbostic 	switch(tag){
33032437Sbostic 		case JXACTIVE:		return("active");
33132437Sbostic 		case JXNOTYET:		return("notyet");
33232437Sbostic 		case JXALIGN:		return("align");
33332437Sbostic 		case JXQUESTIONABLE:	return("jxquestionable");
33432437Sbostic 		case JXINACTIVE:	return("inactive");
33532437Sbostic 		case JXTUNNEL:		return("tunnel");
33632437Sbostic 		case OBSOLETE:		return("obsolete");
33732437Sbostic 		case IGNOREBOUND:	return("ignorebound");
33832437Sbostic 		case STABFLOATING:	return("stabfloating");
33932437Sbostic 		case STABFIXED:		return("stabfixed");
34032437Sbostic 		case LABELID:		return("labelid");
34132437Sbostic 		case OKTOBUMP:		return("oktobump");
34232437Sbostic 		case ISET:		return("iset");
34332437Sbostic 		case ILSYM:		return("ilsym");
344*32438Sbostic 		default:		(void)sprintf(tagbuff,"%d", tag);
34532437Sbostic 					return(tagbuff);
34632437Sbostic 	}
34732437Sbostic }
34832437Sbostic #endif DEBUG
34932437Sbostic 
htaballoc()35032437Sbostic htaballoc()
35132437Sbostic {
35232437Sbostic 	register	struct	hashdallop	*new;
35332437Sbostic 	new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
35432437Sbostic 	if (htab == 0)
35532437Sbostic 		htab = new;
35632437Sbostic 	else {		/* add AFTER the 1st slot */
35732437Sbostic 		new->h_next = htab->h_next;
35832437Sbostic 		htab->h_next = new;
35932437Sbostic 	}
36032437Sbostic }
36132437Sbostic 
36232437Sbostic #define 	HASHCLOGGED	(NHASH / 2)
36332437Sbostic 
36432437Sbostic /*
36532437Sbostic  *	Lookup a symbol stored in extern yytext.
36632437Sbostic  *	All strings passed in via extern yytext had better have
36732437Sbostic  *	a trailing null.  Strings are placed in yytext for hashing by
36832437Sbostic  *	syminstall() and by yylex();
36932437Sbostic  *
37032437Sbostic  *	We take pains to avoid function calls; this functdion
37132437Sbostic  *	is called quite frequently, and the calls overhead
37232437Sbostic  *	in the vax contributes significantly to the overall
37332437Sbostic  *	execution speed of as.
37432437Sbostic  */
lookup(instflg)37532437Sbostic struct symtab **lookup(instflg)
37632437Sbostic 	int	instflg;		/* 0: don't install */
37732437Sbostic {
37832437Sbostic 	static	 int		initialprobe;
37932437Sbostic 	register struct	symtab 	**hp;
38032437Sbostic 	register char 		*from;
38132437Sbostic 	register char		*to;
38232437Sbostic 	register	int	len;
38332437Sbostic 	register	int	nprobes;
38432437Sbostic 	static	struct	hashdallop *hdallop;
38532437Sbostic 	static	struct	symtab	**emptyslot;
38632437Sbostic 	static 	struct	hashdallop *emptyhd;
38732437Sbostic 	static	struct	symtab	**hp_ub;
38832437Sbostic 
38932437Sbostic 	emptyslot = 0;
39032437Sbostic 	for (nprobes = 0, from = yytext;
39132437Sbostic 	     *from;
39232437Sbostic 	     nprobes <<= 2, nprobes += *from++)
39332437Sbostic 		continue;
39432437Sbostic 	nprobes += from[-1] << 5;
39532437Sbostic 	nprobes %= NHASH;
39632437Sbostic 	if (nprobes < 0)
39732437Sbostic 		nprobes += NHASH;
39832437Sbostic 
39932437Sbostic 	initialprobe = nprobes;
40032437Sbostic 	for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
40132437Sbostic 		for (hp = &(hdallop->h_htab[initialprobe]),
40232437Sbostic 				nprobes = 1,
40332437Sbostic 				hp_ub = &(hdallop->h_htab[NHASH]);
40432437Sbostic 		     (*hp) && (nprobes < NHASH);
40532437Sbostic 				hp += nprobes,
40632437Sbostic 				hp -= (hp >= hp_ub) ? NHASH:0,
40732437Sbostic 				nprobes += 2)
40832437Sbostic 		{
40932437Sbostic 			from = yytext;
41032437Sbostic 			to = FETCHNAME(*hp);
41132437Sbostic 			while (*from && *to)
41232437Sbostic 				if (*from++ != *to++)
41332437Sbostic 					goto nextprobe;
41432437Sbostic 			if (*to == *from)	/*assert both are == 0*/
41532437Sbostic 				return(hp);
41632437Sbostic 		nextprobe: ;
41732437Sbostic 		}
41832437Sbostic 		if (*hp == 0 && emptyslot == 0 &&
41932437Sbostic 		    hdallop->h_nused < HASHCLOGGED) {
42032437Sbostic 			emptyslot = hp;
42132437Sbostic 			emptyhd = hdallop;
42232437Sbostic 		}
42332437Sbostic 	}
42432437Sbostic 	if (emptyslot == 0) {
42532437Sbostic 		htaballoc();
42632437Sbostic 		hdallop = htab->h_next;		/* aren't we smart! */
42732437Sbostic 		hp = &hdallop->h_htab[initialprobe];
42832437Sbostic 	} else {
42932437Sbostic 		hdallop = emptyhd;
43032437Sbostic 		hp = emptyslot;
43132437Sbostic 	}
43232437Sbostic 	if (instflg) {
43332437Sbostic 		*hp = symalloc();
43432437Sbostic 		hdallop->h_nused++;
43532437Sbostic 		for (from = yytext, len = 0; *from++; len++)
43632437Sbostic 			continue;
43732437Sbostic 		(*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH);
43832437Sbostic 	}
43932437Sbostic 	return(hp);
44032437Sbostic }	/*end of lookup*/
44132437Sbostic /*
44232437Sbostic  *	save a string str with len in the places indicated by place
44332437Sbostic  */
savestr(str,len,place)44432437Sbostic struct strdesc *savestr(str, len, place)
44532437Sbostic 	char	*str;
44632437Sbostic 	int	len;
44732437Sbostic 	int	place;
44832437Sbostic {
44932437Sbostic 	reg	struct	strdesc	*res;
45032437Sbostic 	reg	int	tlen;
45132437Sbostic 	/*
45232437Sbostic 	 *	Compute the total length of the record to live in core
45332437Sbostic 	 */
45432437Sbostic 	tlen = sizeof(struct strdesc) - sizeof(res->sd_string);
45532437Sbostic 	if (place & STR_CORE)
45632437Sbostic 		tlen += (len + 3) & ~3;
45732437Sbostic 	/*
45832437Sbostic 	 *	See if there is enough space for the record,
45932437Sbostic 	 *	and allocate the record.
46032437Sbostic 	 */
46132437Sbostic 	if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc))
46232437Sbostic 		strpoolalloc();
46332437Sbostic 	res = (struct strdesc *)(strplhead->str_names +
46432437Sbostic 		strplhead->str_nalloc);
46532437Sbostic 	/*
46632437Sbostic 	 *	Save the string information that is always present
46732437Sbostic 	 */
46832437Sbostic 	res->sd_stroff = strfilepos;
46932437Sbostic 	res->sd_strlen = len;
47032437Sbostic 	res->sd_place = place;
47132437Sbostic 	/*
47232437Sbostic 	 *	Now, save the string itself.  If str is null, then
47332437Sbostic 	 *	the characters have already been dumped to the file
47432437Sbostic 	 */
47532437Sbostic 	if ((place & STR_CORE) && str)
47632437Sbostic 		movestr(res[0].sd_string, str, len);
47732437Sbostic 	if (place & STR_FILE){
47832437Sbostic 		if (str){
47932437Sbostic 			fwrite(str, 1, len, strfile);
48032437Sbostic 		}
48132437Sbostic 		strfilepos += len;
48232437Sbostic 	}
48332437Sbostic 	/*
48432437Sbostic 	 *	Adjust the in core string pool size
48532437Sbostic 	 */
48632437Sbostic 	strplhead->str_nalloc += tlen;
48732437Sbostic 	return(res);
48832437Sbostic }
48932437Sbostic /*
49032437Sbostic  *	The relocation information is saved internally in an array of
49132437Sbostic  *	lists of relocation buffers.  The relocation buffers are
49232437Sbostic  *	exactly the same size as a token buffer; if we use VM for the
49332437Sbostic  *	temporary file we reclaim this storage, otherwise we create
49432437Sbostic  *	them by mallocing.
49532437Sbostic  */
49632437Sbostic #define	RELBUFLG	TOKBUFLG
49732437Sbostic #define	NRELOC		((TOKBUFLG - \
49832437Sbostic 			  (sizeof (int) + sizeof (struct relbufdesc *)) \
49932437Sbostic 			) / (sizeof (struct relocation_info)))
50032437Sbostic 
50132437Sbostic struct	relbufdesc{
50232437Sbostic 	int	rel_count;
50332437Sbostic 	struct	relbufdesc	*rel_next;
50432437Sbostic 	struct	relocation_info	rel_reloc[NRELOC];
50532437Sbostic };
50632437Sbostic extern	struct	relbufdesc	*tok_free;
50732437Sbostic #define	rel_free tok_free
50832437Sbostic static	struct	relbufdesc	*rel_temp;
50932437Sbostic struct	relocation_info r_can_1PC;
51032437Sbostic struct	relocation_info	r_can_0PC;
51132437Sbostic 
initoutrel()51232437Sbostic initoutrel()
51332437Sbostic {
51432437Sbostic 	r_can_0PC.r_address = 0;
51532437Sbostic 	r_can_0PC.r_symbolnum = 0;
51632437Sbostic 	r_can_0PC.r_pcrel = 0;
51732437Sbostic 	r_can_0PC.r_length = 0;
51832437Sbostic 	r_can_0PC.r_extern = 0;
51932437Sbostic 
52032437Sbostic 	r_can_1PC = r_can_0PC;
52132437Sbostic 	r_can_1PC.r_pcrel = 1;
52232437Sbostic }
52332437Sbostic 
outrel(xp,reloc_how)52432437Sbostic outrel(xp, reloc_how)
52532437Sbostic 	register	struct	exp	*xp;
52632437Sbostic 	int		reloc_how;	/* TYPB..TYPD + (possibly)RELOC_PCREL */
52732437Sbostic {
52832437Sbostic 	struct		relocation_info	reloc;
52932437Sbostic 	register	int	x_type_mask;
53032437Sbostic 			int	pcrel;
53132437Sbostic 
53232437Sbostic 	x_type_mask = xp->e_xtype & ~XFORW;
53332437Sbostic 	pcrel = reloc_how & RELOC_PCREL;
53432437Sbostic 	reloc_how &= ~RELOC_PCREL;
53532437Sbostic 
53632437Sbostic 	if (bitoff&07)
53732437Sbostic 		yyerror("Padding error");
53832437Sbostic 	if (x_type_mask == XUNDEF)
53932437Sbostic 		yyerror("Undefined reference");
54032437Sbostic 
54132437Sbostic 	if ( (x_type_mask != XABS) || pcrel ) {
54232437Sbostic 		if (ty_NORELOC[reloc_how])
54332437Sbostic 			yyerror("Illegal Relocation of floating or large int number.");
54432437Sbostic 		reloc = pcrel ? r_can_1PC : r_can_0PC;
54532437Sbostic 		reloc.r_address = dotp->e_xvalue -
54632437Sbostic 		    ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
54732437Sbostic 		reloc.r_length = ty_nlg[reloc_how];
54832437Sbostic 		switch(x_type_mask){
54932437Sbostic 			case XXTRN | XUNDEF:
55032437Sbostic 				reloc.r_symbolnum = xp->e_xname->s_index;
55132437Sbostic 				reloc.r_extern = 1;
55232437Sbostic 				break;
55332437Sbostic 			default:
55432437Sbostic 				if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
55532437Sbostic 					x_type_mask = XTEXT | (x_type_mask&XXTRN);
55632437Sbostic 				reloc.r_symbolnum = x_type_mask;
55732437Sbostic 				break;
55832437Sbostic 		}
55932437Sbostic 		if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
56032437Sbostic 			if (rel_free){
56132437Sbostic 				rel_temp = rel_free;
56232437Sbostic 				rel_free = rel_temp->rel_next;
56332437Sbostic 			} else {
56432437Sbostic 				rel_temp = (struct relbufdesc *)
56532437Sbostic 					Calloc(1,sizeof (struct relbufdesc));
56632437Sbostic 			}
56732437Sbostic 			rel_temp->rel_count = 0;
56832437Sbostic 			rel_temp->rel_next = relfil;
56932437Sbostic 			relfil = rusefile[dotp - &usedot[0]] = rel_temp;
57032437Sbostic 		}
57132437Sbostic 		relfil->rel_reloc[relfil->rel_count++] = reloc;
57232437Sbostic 	}
57332437Sbostic 	/*
57432437Sbostic 	 *	write the unrelocated value to the text file
57532437Sbostic 	 */
57632437Sbostic 	dotp->e_xvalue += ty_nbyte[reloc_how];
57732437Sbostic 	if (pcrel)
57832437Sbostic 		xp->e_xvalue -= dotp->e_xvalue;
57932437Sbostic 	switch(reloc_how){
58032437Sbostic 	case TYPQ:
58132437Sbostic 		bwrite(&(xp->e_number.num_num.numIq_int.Iq_ulong[1]),
58232437Sbostic 			sizeof (long), txtfil);
58332437Sbostic 		bwrite(&(xp->e_number.num_num.numIq_int.Iq_ulong[0]),
58432437Sbostic 			sizeof (long), txtfil);
58532437Sbostic 		break;
58632437Sbostic 	case TYPD:
58732437Sbostic 		bwrite(&(xp->e_number.num_num.numFd_float.Fd_ulong[0]),
58832437Sbostic 			sizeof (long), txtfil);
58932437Sbostic 		bwrite(&(xp->e_number.num_num.numFd_float.Fd_ulong[1]),
59032437Sbostic 			sizeof (long), txtfil);
59132437Sbostic 		break;
59232437Sbostic 	case TYPF:
59332437Sbostic 		bwrite(&(xp->e_number.num_num.numFf_float.Ff_ulong[0]),
59432437Sbostic 			sizeof (long), txtfil);
59532437Sbostic 		break;
59632437Sbostic 
59732437Sbostic 	case TYPB:
59832437Sbostic 		bwrite(((char *)&(xp->e_xvalue))+3, ty_nbyte[reloc_how], txtfil);
59932437Sbostic 		break;
60032437Sbostic 	case TYPW:
60132437Sbostic 		bwrite(((char *)&(xp->e_xvalue))+2, ty_nbyte[reloc_how], txtfil);
60232437Sbostic 		break;
60332437Sbostic 	case TYPL:
60432437Sbostic 		bwrite ((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
60532437Sbostic 		break;
60632437Sbostic 	}
60732437Sbostic 	if (liston && (passno == 2))
60832437Sbostic 		switch (reloc_how)
60932437Sbostic 		{
61032437Sbostic 		  case TYPQ:
61132437Sbostic 			  long_out(xp->e_number.num_num.numIq_int.Iq_ulong[1]);
61232437Sbostic 			  long_out(xp->e_number.num_num.numIq_int.Iq_ulong[0]);
61332437Sbostic 		  case TYPD:
61432437Sbostic 			  long_out(xp->e_number.num_num.numIq_int.Iq_ulong[0]);
61532437Sbostic 			  long_out(xp->e_number.num_num.numIq_int.Iq_ulong[1]);
61632437Sbostic 			  break;
61732437Sbostic 		  case TYPF:
61832437Sbostic 			  long_out(xp->e_number.num_num.numFf_float.Ff_ulong[0]);
61932437Sbostic 			  break;
62032437Sbostic 
62132437Sbostic 		  case TYPB:
62232437Sbostic 			  byte_out(xp->e_xvalue);
62332437Sbostic 			  break;
62432437Sbostic 		  case TYPW:
62532437Sbostic 			  word_out(xp->e_xvalue);
62632437Sbostic 			  break;
62732437Sbostic 		  case TYPL:
62832437Sbostic 			  long_out(xp->e_xvalue);
62932437Sbostic 			  break;
63032437Sbostic 		}
63132437Sbostic }
63232437Sbostic /*
63332437Sbostic  *	Flush out all of the relocation information.
63432437Sbostic  *	Note that the individual lists of buffers are in
63532437Sbostic  *	reverse order, so we must reverse them
63632437Sbostic  */
closeoutrel(relocfile)63732437Sbostic off_t closeoutrel(relocfile)
63832437Sbostic 	BFILE	*relocfile;
63932437Sbostic {
64032437Sbostic 	int	locindex;
64132437Sbostic 	u_long	Closeoutrel();
64232437Sbostic 
64332437Sbostic 	trsize = 0;
64432437Sbostic 	for (locindex = 0; locindex < NLOC; locindex++){
64532437Sbostic 		trsize += Closeoutrel(rusefile[locindex], relocfile);
64632437Sbostic 	}
64732437Sbostic 	drsize = 0;
64832437Sbostic 	for (locindex = 0; locindex < NLOC; locindex++){
64932437Sbostic 		drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
65032437Sbostic 	}
65132437Sbostic 	return(trsize + drsize);
65232437Sbostic }
65332437Sbostic 
Closeoutrel(relfil,relocfile)65432437Sbostic u_long Closeoutrel(relfil, relocfile)
65532437Sbostic 	struct	relbufdesc	*relfil;
65632437Sbostic 	BFILE	*relocfile;
65732437Sbostic {
65832437Sbostic 	u_long	tail;
65932437Sbostic 	if (relfil == 0)
66032437Sbostic 		return(0L);
66132437Sbostic 	tail = Closeoutrel(relfil->rel_next, relocfile);
66232437Sbostic 	bwrite((char *)&relfil->rel_reloc[0],
66332437Sbostic 		relfil->rel_count * sizeof (struct relocation_info),
66432437Sbostic 		relocfile);
66532437Sbostic 	return(tail + relfil->rel_count * sizeof (struct relocation_info));
66632437Sbostic }
66732437Sbostic 
66832437Sbostic #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
sizesymtab()66932437Sbostic int sizesymtab()
67032437Sbostic {
67132437Sbostic 	return (sizeof (struct nlist) * NOUTSYMS);
67232437Sbostic }
67332437Sbostic /*
67432437Sbostic  *	Write out n symbols to file f, beginning at p
67532437Sbostic  *	ignoring symbols that are obsolete, jxxx instructions, and
67632437Sbostic  *	possibly, labels
67732437Sbostic  */
symwrite(symfile)67832437Sbostic int symwrite(symfile)
67932437Sbostic 	BFILE *symfile;
68032437Sbostic {
68132437Sbostic 		int	symsout;		/*those actually written*/
68232437Sbostic 		int	symsdesired = NOUTSYMS;
68332437Sbostic 	reg	struct	symtab *sp, *ub;
68432437Sbostic 		char	*name;			/* temp to save the name */
68532437Sbostic 		int	totalstr;
68632437Sbostic 	/*
68732437Sbostic 	 *	We use sp->s_index to hold the length of the
68832437Sbostic 	 *	name; it isn't used for anything else
68932437Sbostic 	 */
69032437Sbostic 	register	struct	allocbox	*allocwalk;
69132437Sbostic 
69232437Sbostic 	symsout = 0;
69332437Sbostic 	totalstr = sizeof(totalstr);
69432437Sbostic 	DECLITERATE(allocwalk, sp, ub) {
69532437Sbostic 		if (sp->s_tag >= IGNOREBOUND)
69632437Sbostic 			continue;
69732437Sbostic 		if (ISLABEL(sp))
69832437Sbostic 			continue;
69932437Sbostic 		symsout++;
70032437Sbostic 		name = sp->s_name;		/* save pointer */
70132437Sbostic 		/*
70232437Sbostic 		 *	the length of the symbol table string
70332437Sbostic 		 *	always includes the trailing null;
70432437Sbostic 		 *	blast the pointer to its a.out value.
70532437Sbostic 		 */
70632437Sbostic 		if (sp->s_name && (sp->s_index = STRLEN(sp))){
70732437Sbostic 			sp->s_nmx = totalstr;
70832437Sbostic 			totalstr += sp->s_index;
70932437Sbostic 		} else {
71032437Sbostic 			sp->s_nmx = 0;
71132437Sbostic 		}
71232437Sbostic 		if (sp->s_ptype != 0)
71332437Sbostic 			sp->s_type = sp->s_ptype;
71432437Sbostic 		else
71532437Sbostic 			sp->s_type = (sp->s_type & (~XFORW));
71632437Sbostic 		if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
71732437Sbostic 			sp->s_type = N_TEXT | (sp->s_type & N_EXT);
71832437Sbostic 		bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
71932437Sbostic 		sp->s_name = name;		/* restore pointer */
72032437Sbostic 	}
72132437Sbostic 	if (symsout != symsdesired)
72232437Sbostic 		yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
72332437Sbostic 			symsout, symsdesired);
72432437Sbostic 	/*
72532437Sbostic 	 *	Construct the string pool from the symbols that were written,
72632437Sbostic 	 *	possibly fetching from the string file if the string
72732437Sbostic 	 *	is not core resident.
72832437Sbostic 	 */
72932437Sbostic 	bwrite(&totalstr, sizeof(totalstr), symfile);
73032437Sbostic 	symsout = 0;
73132437Sbostic 	DECLITERATE(allocwalk, sp, ub) {
73232437Sbostic 		if (sp->s_tag >= IGNOREBOUND)
73332437Sbostic 			continue;
73432437Sbostic 		if (ISLABEL(sp))
73532437Sbostic 			continue;
73632437Sbostic 		symsout++;
73732437Sbostic 		if (sp->s_name && STRLEN(sp) > 0){
73832437Sbostic 		 if (STRPLACE(sp) & STR_CORE){
73932437Sbostic 			bwrite(FETCHNAME(sp), STRLEN(sp), symfile);
74032437Sbostic 		 } else if (STRPLACE(sp) & STR_FILE){
74132437Sbostic 			char	rbuf[2048];
74232437Sbostic 			int	left, nread;
74332437Sbostic 			fseek(strfile, STROFF(sp), 0);
74432437Sbostic 			for (left = STRLEN(sp); left > 0; left -= nread){
74532437Sbostic 				nread = fread(rbuf, sizeof(char),
74632437Sbostic 					min(sizeof(rbuf), left), strfile);
74732437Sbostic 				if (nread == 0)
74832437Sbostic 					break;
74932437Sbostic 				bwrite(rbuf, nread, symfile);
75032437Sbostic 			}
75132437Sbostic 		 }
75232437Sbostic 		}
75332437Sbostic 	}
75432437Sbostic 	if (symsout != symsdesired)
75532437Sbostic 		yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n",
75632437Sbostic 			symsout, symsdesired);
75732437Sbostic }
758