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