15828Srrh /*
219833Sdist * Copyright (c) 1982 Regents of the University of California.
319833Sdist * All rights reserved. The Berkeley software License Agreement
419833Sdist * specifies the terms and conditions for redistribution.
55828Srrh */
619833Sdist
75828Srrh #ifndef lint
8*32432Sbostic static char sccsid[] = "@(#)assyms.c 5.2 (Berkeley) 10/22/87";
95828Srrh #endif not lint
105828Srrh
11600Sbill #include <stdio.h>
12600Sbill #include <ctype.h>
13600Sbill #include "as.h"
14600Sbill #include "asscan.h"
15600Sbill #include "assyms.h"
16600Sbill
17600Sbill /*
18600Sbill * Managers for chunks of symbols allocated from calloc()
19600Sbill * We maintain a linked list of such chunks.
20600Sbill *
21600Sbill */
22600Sbill struct allocbox *allochead; /*head of chunk list*/
23600Sbill struct allocbox *alloctail; /*tail*/
24600Sbill struct allocbox *newbox; /*for creating a new chunk*/
25600Sbill struct symtab *nextsym; /*next symbol free*/
26600Sbill int symsleft; /*slots left in current chunk*/
27600Sbill
28600Sbill struct symtab **symptrs;
29600Sbill struct symtab **symdelim[NLOC + NLOC +1];
30600Sbill struct symtab **symptrub;
31600Sbill /*
32600Sbill * Managers for the dynamically extendable hash table
33600Sbill */
34600Sbill struct hashdallop *htab;
35600Sbill
365828Srrh Iptr *itab[NINST]; /*maps opcodes to instructions*/
37600Sbill /*
38600Sbill * Counts what went into the symbol table, so that the
39600Sbill * size of the symbol table can be computed.
40600Sbill */
41600Sbill int nsyms; /* total number in the symbol table */
42600Sbill int njxxx; /* number of jxxx entrys */
43600Sbill int nforgotten; /* number of symbols erroneously entered */
44600Sbill int nlabels; /* number of label entries */
45600Sbill
46600Sbill /*
47600Sbill * Managers of the symbol literal storage.
48600Sbill */
49600Sbill struct strpool *strplhead = 0;
50600Sbill
symtabinit()51600Sbill symtabinit()
52600Sbill {
53600Sbill allochead = 0;
54600Sbill alloctail = 0;
55600Sbill nextsym = 0;
56600Sbill symsleft = 0;
57600Sbill strpoolalloc(); /* get the first strpool storage area */
58600Sbill htab = 0;
59600Sbill htaballoc(); /* get the first part of the hash table */
60600Sbill }
61600Sbill
62600Sbill /*
63600Sbill * Install all known instructions in the symbol table
64600Sbill */
syminstall()65600Sbill syminstall()
66600Sbill {
675828Srrh register Iptr ip;
68600Sbill register struct symtab **hp;
69600Sbill register char *p1, *p2;
705828Srrh register int i;
71600Sbill
725828Srrh for (i = 0; i < NINST; i++)
735828Srrh itab[i] = (Iptr*)BADPOINT;
745828Srrh
7513514Srrh for (ip = (Iptr)instab; FETCHNAME(ip)[0]; ip++) {
7613514Srrh p1 = FETCHNAME(ip);
77600Sbill p2 = yytext;
78600Sbill while (*p2++ = *p1++);
79600Sbill hp = lookup(0); /* 0 => don't install this*/
80600Sbill if (*hp==NULL) {
81600Sbill *hp = (struct symtab *)ip;
82634Shenry if ( (ip->s_tag!=INSTn)
83634Shenry && (ip->s_tag!=INST0)
84634Shenry && (ip->s_tag!=0))
85600Sbill continue; /* was pseudo-op */
865828Srrh if (itab[ip->i_eopcode] == (Iptr*)BADPOINT){
875828Srrh itab[ip->i_eopcode] =
885828Srrh (Iptr*)ClearCalloc(256, sizeof(Iptr));
895828Srrh for (i = 0; i < 256; i++)
905828Srrh itab[ip->i_eopcode][i] =
915828Srrh (Iptr)BADPOINT;
925828Srrh }
935828Srrh itab[ip->i_eopcode][ip->i_popcode] = ip;
94600Sbill }
95600Sbill }
96600Sbill } /*end of syminstall*/
97600Sbill
9814450Srrh #define ISLABEL(sp) \
9914450Srrh ( (!savelabels) \
10014450Srrh && (sp->s_tag == LABELID) \
10114450Srrh && (STRPLACE(sp) & STR_CORE) \
10214450Srrh && (FETCHNAME(sp)[0] == 'L'))
103600Sbill /*
104600Sbill * Assign final values to symbols,
105600Sbill * and overwrite the index field with its relative position in
106600Sbill * the symbol table we give to the loader.
107600Sbill */
108600Sbill extern struct exec hdr;
109600Sbill
freezesymtab()110600Sbill freezesymtab()
111600Sbill {
112600Sbill register struct symtab *sp;
113600Sbill long bs;
114600Sbill register int relpos = 0;
115600Sbill register struct symtab *ubsp;
116600Sbill register struct allocbox *allocwalk;
117600Sbill
118600Sbill DECLITERATE(allocwalk, sp, ubsp)
119600Sbill {
120634Shenry if (sp->s_tag >= IGNOREBOUND)
121600Sbill continue; /*totally ignore jxxx entries */
122600Sbill /*
123600Sbill * Ignore stabs, but give them a symbol table index
124600Sbill */
125634Shenry if (sp->s_type & STABFLAG)
126600Sbill goto assignindex;
127634Shenry if ((sp->s_type&XTYPE)==XUNDEF)
128634Shenry sp->s_type = XXTRN+XUNDEF;
129634Shenry else if ((sp->s_type&XTYPE)==XDATA)
130634Shenry sp->s_value += usedot[sp->s_index].e_xvalue;
131634Shenry else if ((sp->s_type&XTYPE)==XTEXT)
132634Shenry sp->s_value += usedot[sp->s_index].e_xvalue;
133634Shenry else if ((sp->s_type&XTYPE)==XBSS) {
134634Shenry bs = sp->s_value;
135634Shenry sp->s_value = hdr.a_bss + datbase;
136600Sbill hdr.a_bss += bs;
137600Sbill }
138600Sbill assignindex:
13914450Srrh if (!ISLABEL(sp))
14014450Srrh sp->s_index = relpos++;
141600Sbill }
142600Sbill }
143600Sbill
144600Sbill /*
145600Sbill * For all of the stabs that had their final value undefined during pass 1
146600Sbill * and during pass 2 assign a final value.
147600Sbill * We have already given stab entrys a initial approximation
148600Sbill * when we constsructed the sorted symbol table.
149600Sbill * Iteration order doesn't matter.
150600Sbill */
15112592Scsvaf
stabfix()15212592Scsvaf stabfix()
15312592Scsvaf {
154600Sbill register struct symtab *sp, **cosp;
155600Sbill register struct symtab *p;
156600Sbill
157600Sbill SYMITERATE(cosp, sp){
158634Shenry if(sp->s_ptype && (sp->s_type & STABFLAG)) {
159634Shenry p = sp->s_dest;
16012592Scsvaf /*
16112592Scsvaf * STABFLOATING indicates that the offset has been saved in s_desc, s_other
16212592Scsvaf */
16312592Scsvaf if(sp->s_tag == STABFLOATING) {
16412592Scsvaf sp->s_value = ( ( ((unsigned char) sp->s_other) << 16) | ( (unsigned short) sp->s_desc ) );
16512592Scsvaf sp->s_value = sp->s_value + p->s_value;
16612592Scsvaf }
16712592Scsvaf else sp->s_value = p->s_value;
168634Shenry sp->s_index = p->s_index;
169634Shenry sp->s_type = p->s_type;
17012592Scsvaf
17112592Scsvaf
172600Sbill }
173600Sbill }
174600Sbill }
175600Sbill
Calloc(number,size)176600Sbill char *Calloc(number, size)
177600Sbill int number, size;
178600Sbill {
179600Sbill register char *newstuff;
1805828Srrh char *sbrk();
1815828Srrh newstuff = sbrk(number*size);
182600Sbill if ((int)newstuff == -1){
183600Sbill yyerror("Ran out of Memory");
184600Sbill delexit();
185600Sbill }
186600Sbill return(newstuff);
187600Sbill }
188600Sbill
ClearCalloc(number,size)189600Sbill char *ClearCalloc(number, size)
190600Sbill int number, size;
191600Sbill {
192600Sbill register char *newstuff; /* r11 */
193600Sbill register int length = number * size; /* r10 */
1945828Srrh #ifdef lint
1955828Srrh length = length;
1965828Srrh #endif length
197600Sbill newstuff = Calloc(number, size);
198600Sbill asm("movc5 $0, (r0), $0, r10, (r11)");
199600Sbill return(newstuff);
200600Sbill }
201600Sbill
symalloc()202600Sbill struct symtab *symalloc()
203600Sbill {
204600Sbill if (symsleft == 0){
205600Sbill newbox = (struct allocbox *)ClearCalloc(1,ALLOCQTY);
206600Sbill symsleft = SYMDALLOP;
207600Sbill nextsym = &newbox->symslots[0];
208600Sbill if (alloctail == 0){
209600Sbill allochead = alloctail = newbox;
210600Sbill } else {
211600Sbill alloctail->nextalloc = newbox;
212600Sbill alloctail = newbox;
213600Sbill }
214600Sbill }
215600Sbill --symsleft;
216600Sbill ++nsyms;
217600Sbill return(nextsym++);
218600Sbill }
219600Sbill
strpoolalloc()220600Sbill strpoolalloc()
221600Sbill {
222600Sbill register struct strpool *new;
223600Sbill
224600Sbill new = (struct strpool *)Calloc(1, sizeof (struct strpool));
225600Sbill new->str_nalloc = 0;
226600Sbill new->str_next = strplhead;
227600Sbill strplhead = new;
228600Sbill }
229600Sbill
230600Sbill symcmp(Pptr, Qptr)
231600Sbill struct symtab **Pptr, **Qptr;
232600Sbill {
233600Sbill register struct symtab *p = *Pptr;
234600Sbill register struct symtab *q = *Qptr;
235634Shenry if (p->s_index < q->s_index)
236600Sbill return(-1);
237634Shenry if (p->s_index > q->s_index)
238600Sbill return(1);
239634Shenry if (p->s_value < q->s_value)
240600Sbill return(-1);
241634Shenry if (p->s_value > q->s_value)
242600Sbill return(1);
243600Sbill /*
244600Sbill * Force jxxx entries to virtually preceed labels defined
245600Sbill * to follow the jxxxx instruction, so that bumping the
246600Sbill * jxxx instruction correctly fixes up the following labels
247600Sbill */
248634Shenry if (p->s_tag >= IGNOREBOUND) /*p points to a jxxx*/
249600Sbill return(-1);
250634Shenry if (q->s_tag >= IGNOREBOUND)
251600Sbill return(1);
252600Sbill /*
253600Sbill * both are now just plain labels; the relative order doesn't
254600Sbill * matter. Both can't be jxxxes, as they would have different
255600Sbill * values.
256600Sbill */
257600Sbill return(0);
258600Sbill } /*end of symcmp*/
259600Sbill
260600Sbill /*
261600Sbill * We construct the auxiliary table of pointers, symptrs and
262600Sbill * symdelim
263600Sbill * We also assign preliminary values to stab entries that did not yet
264600Sbill * have an absolute value (because they initially referred to
265600Sbill * forward references). We don't worry about .stabds, as they
266600Sbill * already have an estimated final value
267600Sbill */
268600Sbill
sortsymtab()269600Sbill sortsymtab()
270600Sbill {
271600Sbill register struct symtab *sp;
272600Sbill register struct symtab **cowalk;
273600Sbill register struct allocbox *allocwalk;
274600Sbill struct symtab *ubsp;
275600Sbill int segno;
276600Sbill int slotno;
277600Sbill int symsin; /*number put into symptrs*/
278600Sbill
279600Sbill symptrs = (struct symtab **)Calloc(nsyms + 2, sizeof *symptrs);
280600Sbill /*
281600Sbill * Allocate one word at the beginning of the symptr array
282600Sbill * so that backwards scans through the symptr array will
283600Sbill * work correctly while scanning through the zeroth segment
284600Sbill */
285600Sbill *symptrs++ = 0;
286600Sbill cowalk = symptrs;
287600Sbill symsin = 0;
288600Sbill DECLITERATE(allocwalk, sp, ubsp) {
289634Shenry if (sp->s_ptype && (sp->s_type &STABFLAG)){
290634Shenry sp->s_value = sp->s_dest->s_value;
291634Shenry sp->s_index = sp->s_dest->s_index;
292600Sbill }
293600Sbill if (symsin >= nsyms)
294600Sbill yyerror("INTERNAL ERROR: overfilled symbol table indirection table");
295600Sbill *cowalk++ = sp;
296600Sbill symsin++;
297600Sbill }
298600Sbill if (symsin != nsyms)
299600Sbill yyerror("INTERNAL ERROR: installed %d syms, should have installed %d",
300600Sbill symsin, nsyms);
301600Sbill symptrub = &symptrs[nsyms ];
302600Sbill qsort(symptrs, nsyms, sizeof *symptrs, symcmp);
303600Sbill symdelim[0] = symptrs;
304600Sbill for (cowalk = symptrs, sp = *cowalk, segno = 0, slotno = 1;
305600Sbill segno < NLOC + NLOC;
306600Sbill segno++, slotno++){
307634Shenry for (; sp && sp->s_index == segno; sp = *++cowalk);
308600Sbill symdelim[slotno] = cowalk; /*forms the ub delimeter*/
309600Sbill }
310600Sbill } /*end of sortsymtab*/
311600Sbill
312600Sbill #ifdef DEBUG
dumpsymtab()313600Sbill dumpsymtab()
314600Sbill {
315600Sbill register int segno;
316600Sbill register struct symtab *sp, **cosp, *ub;
317600Sbill char *tagstring();
318600Sbill
319600Sbill printf("Symbol Table dump:\n");
320600Sbill for (segno = 0; segno < NLOC + NLOC; segno++){
321600Sbill printf("Segment number: %d\n", segno);
322600Sbill SEGITERATE(segno, 0, 0, cosp, sp, ub, ++){
323600Sbill printf("\tSeg: %d \"%s\" value: %d index: %d tag %s\n",
32413514Srrh segno, FETCHNAME(sp),
325634Shenry sp->s_value, sp->s_index,
326634Shenry tagstring(sp->s_tag));
327600Sbill printf("\t\ttype: %d jxbump %d jxfear: %d\n",
328634Shenry sp->s_type, sp->s_jxbump, sp->s_jxfear);
329600Sbill }
330600Sbill printf("\n\n");
331600Sbill }
332600Sbill }
333600Sbill
334600Sbill static char tagbuff[4];
335600Sbill
tagstring(tag)336600Sbill char *tagstring(tag)
337600Sbill unsigned char tag;
338600Sbill {
339600Sbill switch(tag){
340600Sbill case JXACTIVE: return("active");
341600Sbill case JXNOTYET: return("notyet");
342600Sbill case JXALIGN: return("align");
343600Sbill case JXQUESTIONABLE: return("jxquestionable");
344600Sbill case JXINACTIVE: return("inactive");
345600Sbill case JXTUNNEL: return("tunnel");
346600Sbill case OBSOLETE: return("obsolete");
347600Sbill case IGNOREBOUND: return("ignorebound");
348600Sbill case STABFLOATING: return("stabfloating");
349600Sbill case STABFIXED: return("stabfixed");
350600Sbill case LABELID: return("labelid");
351600Sbill case OKTOBUMP: return("oktobump");
352600Sbill case ISET: return("iset");
353600Sbill case ILSYM: return("ilsym");
354*32432Sbostic default: (void)sprintf(tagbuff,"%d", tag);
355600Sbill return(tagbuff);
356600Sbill }
357600Sbill }
358600Sbill #endif DEBUG
359600Sbill
htaballoc()360600Sbill htaballoc()
361600Sbill {
362600Sbill register struct hashdallop *new;
363600Sbill new = (struct hashdallop *)ClearCalloc(1, sizeof (struct hashdallop));
364600Sbill if (htab == 0)
365600Sbill htab = new;
366600Sbill else { /* add AFTER the 1st slot */
367600Sbill new->h_next = htab->h_next;
368600Sbill htab->h_next = new;
369600Sbill }
370600Sbill }
371600Sbill
372600Sbill #define HASHCLOGGED (NHASH / 2)
373600Sbill
374600Sbill /*
375600Sbill * Lookup a symbol stored in extern yytext.
376600Sbill * All strings passed in via extern yytext had better have
377600Sbill * a trailing null. Strings are placed in yytext for hashing by
378600Sbill * syminstall() and by yylex();
379600Sbill *
380600Sbill * We take pains to avoid function calls; this functdion
381600Sbill * is called quite frequently, and the calls overhead
382600Sbill * in the vax contributes significantly to the overall
383600Sbill * execution speed of as.
384600Sbill */
lookup(instflg)385600Sbill struct symtab **lookup(instflg)
386600Sbill int instflg; /* 0: don't install */
387600Sbill {
388600Sbill static int initialprobe;
389600Sbill register struct symtab **hp;
390600Sbill register char *from;
391600Sbill register char *to;
392600Sbill register int len;
393600Sbill register int nprobes;
39413514Srrh static struct hashdallop *hdallop;
39513514Srrh static struct symtab **emptyslot;
39613514Srrh static struct hashdallop *emptyhd;
39713514Srrh static struct symtab **hp_ub;
398600Sbill
399600Sbill emptyslot = 0;
400600Sbill for (nprobes = 0, from = yytext;
401600Sbill *from;
402600Sbill nprobes <<= 2, nprobes += *from++)
403600Sbill continue;
404600Sbill nprobes += from[-1] << 5;
405600Sbill nprobes %= NHASH;
406600Sbill if (nprobes < 0)
407600Sbill nprobes += NHASH;
408600Sbill
409600Sbill initialprobe = nprobes;
410600Sbill for (hdallop = htab; hdallop != 0; hdallop = hdallop->h_next){
411600Sbill for (hp = &(hdallop->h_htab[initialprobe]),
412600Sbill nprobes = 1,
413600Sbill hp_ub = &(hdallop->h_htab[NHASH]);
414600Sbill (*hp) && (nprobes < NHASH);
415600Sbill hp += nprobes,
416600Sbill hp -= (hp >= hp_ub) ? NHASH:0,
417600Sbill nprobes += 2)
418600Sbill {
419600Sbill from = yytext;
42013514Srrh to = FETCHNAME(*hp);
421600Sbill while (*from && *to)
422600Sbill if (*from++ != *to++)
423600Sbill goto nextprobe;
424600Sbill if (*to == *from) /*assert both are == 0*/
425600Sbill return(hp);
42613522Srrh nextprobe: ;
427600Sbill }
428600Sbill if (*hp == 0 && emptyslot == 0 &&
429600Sbill hdallop->h_nused < HASHCLOGGED) {
430600Sbill emptyslot = hp;
431600Sbill emptyhd = hdallop;
432600Sbill }
433600Sbill }
434600Sbill if (emptyslot == 0) {
435600Sbill htaballoc();
436600Sbill hdallop = htab->h_next; /* aren't we smart! */
437600Sbill hp = &hdallop->h_htab[initialprobe];
438600Sbill } else {
439600Sbill hdallop = emptyhd;
440600Sbill hp = emptyslot;
441600Sbill }
442600Sbill if (instflg) {
443600Sbill *hp = symalloc();
444600Sbill hdallop->h_nused++;
44513447Srrh for (from = yytext, len = 0; *from++; len++)
446600Sbill continue;
44713572Srrh (*hp)->s_name = (char *)savestr(yytext, len + 1, STR_BOTH);
448600Sbill }
449600Sbill return(hp);
450600Sbill } /*end of lookup*/
45113447Srrh /*
45213572Srrh * save a string str with len in the places indicated by place
45313447Srrh */
savestr(str,len,place)45413572Srrh struct strdesc *savestr(str, len, place)
45513447Srrh char *str;
45613572Srrh int len;
45713572Srrh int place;
458600Sbill {
45913514Srrh reg struct strdesc *res;
46013514Srrh int tlen;
46113572Srrh /*
46213572Srrh * Compute the total length of the record to live in core
46313572Srrh */
46413514Srrh tlen = sizeof(struct strdesc) - sizeof(res->sd_string);
46513572Srrh if (place & STR_CORE)
46613572Srrh tlen += len;
46713572Srrh /*
46813572Srrh * See if there is enough space for the record,
46913572Srrh * and allocate the record.
47013572Srrh */
47113514Srrh if (tlen >= (STRPOOLDALLOP - strplhead->str_nalloc))
472600Sbill strpoolalloc();
47313514Srrh res = (struct strdesc *)(strplhead->str_names + strplhead->str_nalloc);
47413572Srrh /*
47513572Srrh * Save the string information that is always present
47613572Srrh */
47713572Srrh res->sd_stroff = strfilepos;
47813572Srrh res->sd_strlen = len;
47913572Srrh res->sd_place = place;
48013572Srrh /*
48113572Srrh * Now, save the string itself. If str is null, then
48213572Srrh * the characters have already been dumped to the file
48313572Srrh */
48413572Srrh if ((place & STR_CORE) && str)
48513572Srrh movestr(res[0].sd_string, str, len);
48613572Srrh if (place & STR_FILE){
48713572Srrh if (str){
48813572Srrh fwrite(str, 1, len, strfile);
48913572Srrh }
49013572Srrh strfilepos += len;
49113572Srrh }
49213572Srrh /*
49313572Srrh * Adjust the in core string pool size
49413572Srrh */
49513514Srrh strplhead->str_nalloc += tlen;
49613447Srrh return(res);
497600Sbill }
498600Sbill /*
499600Sbill * The relocation information is saved internally in an array of
500600Sbill * lists of relocation buffers. The relocation buffers are
501600Sbill * exactly the same size as a token buffer; if we use VM for the
502600Sbill * temporary file we reclaim this storage, otherwise we create
503600Sbill * them by mallocing.
504600Sbill */
505600Sbill #define RELBUFLG TOKBUFLG
506600Sbill #define NRELOC ((TOKBUFLG - \
507600Sbill (sizeof (int) + sizeof (struct relbufdesc *)) \
508600Sbill ) / (sizeof (struct relocation_info)))
509600Sbill
510600Sbill struct relbufdesc{
511600Sbill int rel_count;
512600Sbill struct relbufdesc *rel_next;
513600Sbill struct relocation_info rel_reloc[NRELOC];
514600Sbill };
515600Sbill extern struct relbufdesc *tok_free;
516600Sbill #define rel_free tok_free
517600Sbill static struct relbufdesc *rel_temp;
518634Shenry struct relocation_info r_can_1PC;
519634Shenry struct relocation_info r_can_0PC;
520600Sbill
initoutrel()521600Sbill initoutrel()
522600Sbill {
523634Shenry r_can_0PC.r_address = 0;
524634Shenry r_can_0PC.r_symbolnum = 0;
525634Shenry r_can_0PC.r_pcrel = 0;
526634Shenry r_can_0PC.r_length = 0;
527634Shenry r_can_0PC.r_extern = 0;
528634Shenry
529634Shenry r_can_1PC = r_can_0PC;
530600Sbill r_can_1PC.r_pcrel = 1;
531600Sbill }
532600Sbill
outrel(xp,reloc_how)533675Shenry outrel(xp, reloc_how)
534675Shenry register struct exp *xp;
5355828Srrh int reloc_how; /* TYPB..TYPH + (possibly)RELOC_PCREL */
536600Sbill {
537675Shenry struct relocation_info reloc;
538675Shenry register int x_type_mask;
53913447Srrh int pcrel;
540600Sbill
541675Shenry x_type_mask = xp->e_xtype & ~XFORW;
542675Shenry pcrel = reloc_how & RELOC_PCREL;
543675Shenry reloc_how &= ~RELOC_PCREL;
544675Shenry
545600Sbill if (bitoff&07)
546600Sbill yyerror("Padding error");
547675Shenry if (x_type_mask == XUNDEF)
548600Sbill yyerror("Undefined reference");
549600Sbill
550675Shenry if ( (x_type_mask != XABS) || pcrel ) {
551675Shenry if (ty_NORELOC[reloc_how])
5525828Srrh yyerror("Illegal Relocation of floating or large int number.");
553675Shenry reloc = pcrel ? r_can_1PC : r_can_0PC;
554634Shenry reloc.r_address = dotp->e_xvalue -
555640Sbill ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase );
556675Shenry reloc.r_length = ty_nlg[reloc_how];
557675Shenry switch(x_type_mask){
558600Sbill case XXTRN | XUNDEF:
559675Shenry reloc.r_symbolnum = xp->e_xname->s_index;
560600Sbill reloc.r_extern = 1;
561600Sbill break;
562600Sbill default:
563675Shenry if (readonlydata && (x_type_mask&~XXTRN) == XDATA)
564675Shenry x_type_mask = XTEXT | (x_type_mask&XXTRN);
565675Shenry reloc.r_symbolnum = x_type_mask;
566600Sbill break;
567600Sbill }
568600Sbill if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){
569600Sbill if (rel_free){
570600Sbill rel_temp = rel_free;
571600Sbill rel_free = rel_temp->rel_next;
572600Sbill } else {
573600Sbill rel_temp = (struct relbufdesc *)
574600Sbill Calloc(1,sizeof (struct relbufdesc));
575600Sbill }
576600Sbill rel_temp->rel_count = 0;
577600Sbill rel_temp->rel_next = relfil;
578600Sbill relfil = rusefile[dotp - &usedot[0]] = rel_temp;
579600Sbill }
580600Sbill relfil->rel_reloc[relfil->rel_count++] = reloc;
581600Sbill }
582600Sbill /*
583600Sbill * write the unrelocated value to the text file
584600Sbill */
585675Shenry dotp->e_xvalue += ty_nbyte[reloc_how];
586675Shenry if (pcrel)
587675Shenry xp->e_xvalue -= dotp->e_xvalue;
5885828Srrh switch(reloc_how){
5895828Srrh case TYPO:
5905828Srrh case TYPQ:
5915828Srrh
5925828Srrh case TYPF:
5935828Srrh case TYPD:
5945828Srrh case TYPG:
5955828Srrh case TYPH:
5965828Srrh bignumwrite(xp->e_number, reloc_how);
5975828Srrh break;
5985828Srrh
5995828Srrh default:
6005828Srrh bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil);
6015828Srrh break;
6025828Srrh }
603600Sbill }
604600Sbill /*
605600Sbill * Flush out all of the relocation information.
606600Sbill * Note that the individual lists of buffers are in
607600Sbill * reverse order, so we must reverse them
608600Sbill */
closeoutrel(relocfile)609600Sbill off_t closeoutrel(relocfile)
610600Sbill BFILE *relocfile;
611600Sbill {
612600Sbill int locindex;
613600Sbill u_long Closeoutrel();
614600Sbill
615600Sbill trsize = 0;
616600Sbill for (locindex = 0; locindex < NLOC; locindex++){
617600Sbill trsize += Closeoutrel(rusefile[locindex], relocfile);
618600Sbill }
619600Sbill drsize = 0;
620600Sbill for (locindex = 0; locindex < NLOC; locindex++){
621600Sbill drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile);
622600Sbill }
623600Sbill return(trsize + drsize);
624600Sbill }
625600Sbill
Closeoutrel(relfil,relocfile)626600Sbill u_long Closeoutrel(relfil, relocfile)
627600Sbill struct relbufdesc *relfil;
628600Sbill BFILE *relocfile;
629600Sbill {
630600Sbill u_long tail;
631600Sbill if (relfil == 0)
632600Sbill return(0L);
633600Sbill tail = Closeoutrel(relfil->rel_next, relocfile);
634600Sbill bwrite((char *)&relfil->rel_reloc[0],
635600Sbill relfil->rel_count * sizeof (struct relocation_info),
636600Sbill relocfile);
637600Sbill return(tail + relfil->rel_count * sizeof (struct relocation_info));
638600Sbill }
639600Sbill
640634Shenry #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels))
sizesymtab()641600Sbill int sizesymtab()
642600Sbill {
643634Shenry return (sizeof (struct nlist) * NOUTSYMS);
644600Sbill }
645600Sbill /*
646600Sbill * Write out n symbols to file f, beginning at p
647600Sbill * ignoring symbols that are obsolete, jxxx instructions, and
648600Sbill * possibly, labels
649600Sbill */
symwrite(symfile)650600Sbill int symwrite(symfile)
651600Sbill BFILE *symfile;
652600Sbill {
65313514Srrh int symsout; /*those actually written*/
65413514Srrh int symsdesired = NOUTSYMS;
65513514Srrh reg struct symtab *sp, *ub;
65613514Srrh char *name; /* temp to save the name */
65714450Srrh int totalstr;
658634Shenry /*
659634Shenry * We use sp->s_index to hold the length of the
660634Shenry * name; it isn't used for anything else
661634Shenry */
662600Sbill register struct allocbox *allocwalk;
663600Sbill
664600Sbill symsout = 0;
66514450Srrh totalstr = sizeof(totalstr);
66614450Srrh DECLITERATE(allocwalk, sp, ub) {
667634Shenry if (sp->s_tag >= IGNOREBOUND)
668600Sbill continue;
66914450Srrh if (ISLABEL(sp))
670600Sbill continue;
671600Sbill symsout++;
672634Shenry name = sp->s_name; /* save pointer */
67313447Srrh /*
67413447Srrh * the length of the symbol table string
67514450Srrh * always includes the trailing null;
67614450Srrh * blast the pointer to its a.out value.
67713447Srrh */
67813514Srrh if (sp->s_name && (sp->s_index = STRLEN(sp))){
67914450Srrh sp->s_nmx = totalstr;
68014450Srrh totalstr += sp->s_index;
681634Shenry } else {
68213447Srrh sp->s_nmx = 0;
683634Shenry }
68414450Srrh if (sp->s_ptype != 0)
68514450Srrh sp->s_type = sp->s_ptype;
68614450Srrh else
68714450Srrh sp->s_type = (sp->s_type & (~XFORW));
688640Sbill if (readonlydata && (sp->s_type&~N_EXT) == N_DATA)
689640Sbill sp->s_type = N_TEXT | (sp->s_type & N_EXT);
6905828Srrh bwrite((char *)&sp->s_nm, sizeof (struct nlist), symfile);
691634Shenry sp->s_name = name; /* restore pointer */
692600Sbill }
693600Sbill if (symsout != symsdesired)
694600Sbill yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n",
695600Sbill symsout, symsdesired);
696600Sbill /*
69714450Srrh * Construct the string pool from the symbols that were written,
69814450Srrh * possibly fetching from the string file if the string
69914450Srrh * is not core resident.
700600Sbill */
70114450Srrh bwrite(&totalstr, sizeof(totalstr), symfile);
70214450Srrh symsout = 0;
70314450Srrh DECLITERATE(allocwalk, sp, ub) {
70414450Srrh if (sp->s_tag >= IGNOREBOUND)
70514450Srrh continue;
70614450Srrh if (ISLABEL(sp))
70714450Srrh continue;
70814450Srrh symsout++;
70914450Srrh if (STRLEN(sp) > 0){
71014450Srrh if (STRPLACE(sp) & STR_CORE){
71114450Srrh bwrite(FETCHNAME(sp), STRLEN(sp), symfile);
71214450Srrh } else if (STRPLACE(sp) & STR_FILE){
71314450Srrh char rbuf[2048];
71414450Srrh int left, nread;
71514450Srrh fseek(strfile, STROFF(sp), 0);
71614450Srrh for (left = STRLEN(sp); left > 0; left -= nread){
71714450Srrh nread = fread(rbuf, sizeof(char),
71814450Srrh min(sizeof(rbuf), left), strfile);
71914450Srrh if (nread == 0)
72014450Srrh break;
72114450Srrh bwrite(rbuf, nread, symfile);
72214450Srrh }
72314450Srrh }
72413447Srrh }
725600Sbill }
72614450Srrh if (symsout != symsdesired)
72714450Srrh yyerror("INTERNAL ERROR: Wrote %d strings, wanted %d\n",
72814450Srrh symsout, symsdesired);
729600Sbill }
730