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