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