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