Commit | Line | Data |
---|---|---|
5178805d | 1 | /* Copyright (c) 1980 Regents of the University of California */ |
0c940099 | 2 | static char sccsid[] = "@(#)assyms.c 4.6 %G%"; |
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 | ||
0c940099 | 463 | #ifdef FLEXNAMES |
5178805d BJ |
464 | char *savestr(str) |
465 | char *str; | |
466 | { | |
467 | register int len; | |
468 | register char *from, *to; | |
469 | char *res; | |
470 | ||
471 | for (from = str, len = 1; *from++; len++) | |
472 | continue; | |
473 | if (len >= (STRPOOLDALLOP - strplhead->str_nalloc)) | |
474 | strpoolalloc(); | |
475 | for ( res = to = strplhead->str_names + strplhead->str_nalloc, from = str; | |
476 | ( (*to++ = *from++) != '\0'); ) | |
477 | continue; | |
478 | strplhead->str_nalloc += len; | |
479 | return (res); | |
480 | } | |
0c940099 | 481 | #endif FLEXNAMES |
5178805d | 482 | |
5178805d BJ |
483 | /* |
484 | * The relocation information is saved internally in an array of | |
485 | * lists of relocation buffers. The relocation buffers are | |
486 | * exactly the same size as a token buffer; if we use VM for the | |
487 | * temporary file we reclaim this storage, otherwise we create | |
488 | * them by mallocing. | |
489 | */ | |
490 | #define RELBUFLG TOKBUFLG | |
491 | #define NRELOC ((TOKBUFLG - \ | |
492 | (sizeof (int) + sizeof (struct relbufdesc *)) \ | |
493 | ) / (sizeof (struct relocation_info))) | |
494 | ||
495 | struct relbufdesc{ | |
496 | int rel_count; | |
497 | struct relbufdesc *rel_next; | |
498 | struct relocation_info rel_reloc[NRELOC]; | |
499 | }; | |
500 | extern struct relbufdesc *tok_free; | |
501 | #define rel_free tok_free | |
502 | static struct relbufdesc *rel_temp; | |
451260e7 RH |
503 | struct relocation_info r_can_1PC; |
504 | struct relocation_info r_can_0PC; | |
5178805d BJ |
505 | |
506 | initoutrel() | |
507 | { | |
451260e7 RH |
508 | r_can_0PC.r_address = 0; |
509 | r_can_0PC.r_symbolnum = 0; | |
510 | r_can_0PC.r_pcrel = 0; | |
511 | r_can_0PC.r_length = 0; | |
512 | r_can_0PC.r_extern = 0; | |
513 | ||
514 | r_can_1PC = r_can_0PC; | |
5178805d BJ |
515 | r_can_1PC.r_pcrel = 1; |
516 | } | |
517 | ||
5b3c350a RH |
518 | outrel(xp, reloc_how) |
519 | register struct exp *xp; | |
520 | int reloc_how; /* TYPB..TYPD + (possibly)RELOC_PCREL */ | |
5178805d | 521 | { |
5b3c350a RH |
522 | struct relocation_info reloc; |
523 | register int x_type_mask; | |
524 | int pcrel; | |
5178805d | 525 | |
5b3c350a RH |
526 | x_type_mask = xp->e_xtype & ~XFORW; |
527 | pcrel = reloc_how & RELOC_PCREL; | |
528 | reloc_how &= ~RELOC_PCREL; | |
529 | ||
5178805d BJ |
530 | if (bitoff&07) |
531 | yyerror("Padding error"); | |
5b3c350a | 532 | if (x_type_mask == XUNDEF) |
5178805d BJ |
533 | yyerror("Undefined reference"); |
534 | ||
5b3c350a RH |
535 | if ( (x_type_mask != XABS) || pcrel ) { |
536 | if (ty_NORELOC[reloc_how]) | |
537 | yyerror("Illegal Relocation of float, double or quad."); | |
538 | reloc = pcrel ? r_can_1PC : r_can_0PC; | |
451260e7 | 539 | reloc.r_address = dotp->e_xvalue - |
030352e9 | 540 | ( (dotp < &usedot[NLOC] || readonlydata) ? 0 : datbase ); |
5b3c350a RH |
541 | reloc.r_length = ty_nlg[reloc_how]; |
542 | switch(x_type_mask){ | |
5178805d | 543 | case XXTRN | XUNDEF: |
5b3c350a | 544 | reloc.r_symbolnum = xp->e_xname->s_index; |
5178805d BJ |
545 | reloc.r_extern = 1; |
546 | break; | |
547 | default: | |
5b3c350a RH |
548 | if (readonlydata && (x_type_mask&~XXTRN) == XDATA) |
549 | x_type_mask = XTEXT | (x_type_mask&XXTRN); | |
550 | reloc.r_symbolnum = x_type_mask; | |
5178805d BJ |
551 | break; |
552 | } | |
553 | if ( (relfil == 0) || (relfil->rel_count >= NRELOC) ){ | |
554 | if (rel_free){ | |
555 | rel_temp = rel_free; | |
556 | rel_free = rel_temp->rel_next; | |
557 | } else { | |
558 | rel_temp = (struct relbufdesc *) | |
559 | Calloc(1,sizeof (struct relbufdesc)); | |
560 | } | |
561 | rel_temp->rel_count = 0; | |
562 | rel_temp->rel_next = relfil; | |
563 | relfil = rusefile[dotp - &usedot[0]] = rel_temp; | |
564 | } | |
565 | relfil->rel_reloc[relfil->rel_count++] = reloc; | |
566 | } | |
567 | /* | |
568 | * write the unrelocated value to the text file | |
569 | */ | |
5b3c350a RH |
570 | dotp->e_xvalue += ty_nbyte[reloc_how]; |
571 | if (pcrel) | |
572 | xp->e_xvalue -= dotp->e_xvalue; | |
573 | bwrite((char *)&(xp->e_xvalue), ty_nbyte[reloc_how], txtfil); | |
5178805d BJ |
574 | } |
575 | /* | |
576 | * Flush out all of the relocation information. | |
577 | * Note that the individual lists of buffers are in | |
578 | * reverse order, so we must reverse them | |
579 | */ | |
580 | off_t closeoutrel(relocfile) | |
581 | BFILE *relocfile; | |
582 | { | |
583 | int locindex; | |
584 | u_long Closeoutrel(); | |
585 | ||
586 | trsize = 0; | |
587 | for (locindex = 0; locindex < NLOC; locindex++){ | |
588 | trsize += Closeoutrel(rusefile[locindex], relocfile); | |
589 | } | |
590 | drsize = 0; | |
591 | for (locindex = 0; locindex < NLOC; locindex++){ | |
592 | drsize += Closeoutrel(rusefile[NLOC + locindex], relocfile); | |
593 | } | |
594 | return(trsize + drsize); | |
595 | } | |
596 | ||
597 | u_long Closeoutrel(relfil, relocfile) | |
598 | struct relbufdesc *relfil; | |
599 | BFILE *relocfile; | |
600 | { | |
601 | u_long tail; | |
602 | if (relfil == 0) | |
603 | return(0L); | |
604 | tail = Closeoutrel(relfil->rel_next, relocfile); | |
605 | bwrite((char *)&relfil->rel_reloc[0], | |
606 | relfil->rel_count * sizeof (struct relocation_info), | |
607 | relocfile); | |
608 | return(tail + relfil->rel_count * sizeof (struct relocation_info)); | |
609 | } | |
610 | ||
451260e7 | 611 | #define NOUTSYMS (nsyms - njxxx - nforgotten - (savelabels ? 0 : nlabels)) |
5178805d BJ |
612 | int sizesymtab() |
613 | { | |
451260e7 | 614 | return (sizeof (struct nlist) * NOUTSYMS); |
5178805d BJ |
615 | } |
616 | ||
617 | #ifdef FLEXNAMES | |
618 | /* | |
619 | * We write out the flexible length character strings for names | |
620 | * in two stages. | |
621 | * 1) We have always! maintain a fixed sized name list entry; | |
622 | * the string is indexed by a four byte quantity from the beginning | |
623 | * of the string pool area. Index 0 is reserved, and indicates | |
624 | * that there is no associated string. The first valid index is 4. | |
625 | * 2) We concatenate together and write all of the strings | |
626 | * in the string pool at the end of the name list. The first | |
627 | * four bytes in the string pool are indexed only by 0 (see above); | |
628 | * they contain the total number of bytes in the string pool. | |
629 | */ | |
630 | #endif FLEXNAMES | |
631 | ||
632 | /* | |
633 | * Write out n symbols to file f, beginning at p | |
634 | * ignoring symbols that are obsolete, jxxx instructions, and | |
635 | * possibly, labels | |
636 | */ | |
637 | ||
638 | int symwrite(symfile) | |
639 | BFILE *symfile; | |
640 | { | |
641 | int symsout; /*those actually written*/ | |
642 | int symsdesired = NOUTSYMS; | |
643 | register struct symtab *sp, *ub; | |
644 | #ifdef FLEXNAMES | |
451260e7 | 645 | char *name; /* temp to save the name */ |
5178805d | 646 | long stroff = sizeof (stroff); |
451260e7 RH |
647 | /* |
648 | * We use sp->s_index to hold the length of the | |
649 | * name; it isn't used for anything else | |
650 | */ | |
5178805d BJ |
651 | #endif FLEXNAMES |
652 | ||
653 | register struct allocbox *allocwalk; | |
654 | ||
655 | symsout = 0; | |
656 | DECLITERATE(allocwalk, sp, ub) | |
657 | { | |
451260e7 | 658 | if (sp->s_tag >= IGNOREBOUND) |
5178805d | 659 | continue; |
451260e7 | 660 | if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) |
5178805d BJ |
661 | continue; |
662 | symsout++; | |
451260e7 RH |
663 | |
664 | #ifdef FLEXNAMES | |
665 | name = sp->s_name; /* save pointer */ | |
666 | if ( (sp->s_index = strlen(sp->s_name)) != 0){ | |
667 | sp->s_nmx = stroff; /* clobber pointer */ | |
668 | stroff += sp->s_index + 1; | |
669 | } else { | |
670 | sp->s_nmx = 0; /* clobber pointer */ | |
671 | } | |
672 | #endif | |
673 | sp->s_type = (sp->s_ptype != 0) ? sp->s_ptype : (sp->s_type & (~XFORW)); | |
030352e9 BJ |
674 | if (readonlydata && (sp->s_type&~N_EXT) == N_DATA) |
675 | sp->s_type = N_TEXT | (sp->s_type & N_EXT); | |
451260e7 RH |
676 | bwrite(&sp->s_nm, sizeof (struct nlist), symfile); |
677 | #ifdef FLEXNAMES | |
678 | sp->s_name = name; /* restore pointer */ | |
5178805d | 679 | #endif FLEXNAMES |
5178805d BJ |
680 | } |
681 | if (symsout != symsdesired) | |
682 | yyerror("INTERNAL ERROR: Wrote %d symbols, wanted to write %d symbols\n", | |
683 | symsout, symsdesired); | |
684 | #ifdef FLEXNAMES | |
685 | /* | |
686 | * Pass 2 through the string pool | |
687 | */ | |
688 | symsout = 0; | |
689 | bwrite(&stroff, sizeof (stroff), symfile); | |
690 | stroff = sizeof (stroff); | |
691 | symsout = 0; | |
692 | DECLITERATE(allocwalk, sp, ub) | |
693 | { | |
451260e7 | 694 | if (sp->s_tag >= IGNOREBOUND) |
5178805d | 695 | continue; |
451260e7 | 696 | if ((sp->s_name[0] == 'L') && (sp->s_tag == LABELID) && !savelabels) |
5178805d | 697 | continue; |
451260e7 RH |
698 | sp->s_index = strlen(sp->s_name); |
699 | if (sp->s_index) | |
700 | bwrite(sp->s_name, sp->s_index + 1, symfile); | |
5178805d BJ |
701 | } |
702 | #endif FLEXNAMES | |
703 | } |