recording file death
[deliverable/binutils-gdb.git] / gas / config / obj-coff-bfd.c
1 /* coff object file format with bfd
2 Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
3
4 This file is part of GAS.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21
22 How does this releate to the rest of GAS ?
23
24 Well, all the other files in gas are more or less a black box. It
25 takes care of opening files, parsing command lines, stripping blanks
26 etc etc. This module gets a chance to register what it wants to do by
27 saying that it is interested in various pseduo ops. The other big
28 change is write_object_file. This runs through all the data
29 structures that gas builds, and outputs the file in the format of our
30 choice.
31
32 Hacked for BFDness by steve chamberlain
33
34 This object module now supports the Hitachi H8/300 and the AMD 29k
35
36 sac@cygnus.com
37 */
38
39 #include "as.h"
40 #include "obstack.h"
41 #include "subsegs.h"
42 #include "frags.h"
43 #include "../bfd/libbfd.h"
44
45
46 /* This vector is used to turn an internal segment into a section #
47 suitable for insertion into a coff symbol table
48 */
49
50 const short seg_N_TYPE[] = { /* in: segT out: N_TYPE bits */
51 C_ABS_SECTION,
52 1,
53 2,
54 3,
55 4,
56 5,
57 6,
58 7,
59 8,
60 9,
61 10,
62 C_UNDEF_SECTION, /* SEG_UNKNOWN */
63 C_UNDEF_SECTION, /* SEG_ABSENT */
64 C_UNDEF_SECTION, /* SEG_PASS1 */
65 C_UNDEF_SECTION, /* SEG_GOOF */
66 C_UNDEF_SECTION, /* SEG_BIG */
67 C_UNDEF_SECTION, /* SEG_DIFFERENCE */
68 C_DEBUG_SECTION, /* SEG_DEBUG */
69 C_NTV_SECTION, /* SEG_NTV */
70 C_PTV_SECTION, /* SEG_PTV */
71 C_REGISTER_SECTION, /* SEG_REGISTER */
72 };
73
74
75 int function_lineoff = -1; /* Offset in line#s where the last function
76 started (the odd entry for line #0) */
77
78 int our_lineno_number = 0; /* we use this to build pointers from .bf's
79 into the linetable. It should match
80 exactly the values that are later
81 assigned in text_lineno_number by
82 write.c. */
83
84 int text_lineno_number = 0;
85
86 /* Add 4 to the real value to get the index and compensate the
87 negatives. This vector is used by S_GET_SEGMENT to turn a coff
88 section number into a segment number
89 */
90 static symbolS *previous_file_symbol = NULL;
91 void c_symbol_merge();
92
93 symbolS *c_section_symbol();
94 bfd *abfd;
95 void EXFUN(bfd_as_write_hook,(struct internal_filehdr *,
96 bfd *abfd));
97
98 static void EXFUN(fixup_segment,(fixS * fixP,
99 segT this_segment_type));
100
101 static void EXFUN(fill_section,(bfd *abfd ,
102 struct internal_filehdr *f, unsigned
103 long *));
104
105
106 char *EXFUN(s_get_name,(symbolS *s));
107 static symbolS *EXFUN(tag_find_or_make,(char *name));
108 static symbolS* EXFUN(tag_find,(char *name));
109
110
111 static int
112 EXFUN(c_line_new,(
113 symbolS *symbol,
114 long paddr,
115 unsigned short line_number,
116 fragS* frag));
117
118
119 static void EXFUN(w_symbols,
120 (bfd *abfd ,
121 char *where ,
122 symbolS *symbol_rootP));
123
124
125
126 static void EXFUN( obj_coff_def,(int what));
127 static void EXFUN( obj_coff_lcomm,(void));
128 static void EXFUN( obj_coff_dim,(void));
129 static void EXFUN( obj_coff_text,(void));
130 static void EXFUN( obj_coff_data,(void));
131 static void EXFUN( obj_coff_endef,(void));
132 static void EXFUN( obj_coff_line,(void));
133 static void EXFUN( obj_coff_ln,(void));
134 static void EXFUN( obj_coff_scl,(void));
135 static void EXFUN( obj_coff_size,(void));
136 static void EXFUN( obj_coff_tag,(void));
137 static void EXFUN( obj_coff_type,(void));
138 static void EXFUN( obj_coff_val,(void));
139 static void EXFUN( obj_coff_section,(void));
140 static void EXFUN( tag_init,(void));
141 static void EXFUN( tag_insert,(char *name, symbolS *symbolP));
142
143
144 static struct hash_control *tag_hash;
145 static symbolS *def_symbol_in_progress = NULL;
146
147 const pseudo_typeS obj_pseudo_table[] = {
148 { "def", obj_coff_def, 0 },
149 { "dim", obj_coff_dim, 0 },
150 { "endef", obj_coff_endef, 0 },
151 { "line", obj_coff_line, 0 },
152 { "ln", obj_coff_ln, 0 },
153 { "scl", obj_coff_scl, 0 },
154 { "size", obj_coff_size, 0 },
155 { "tag", obj_coff_tag, 0 },
156 { "type", obj_coff_type, 0 },
157 { "val", obj_coff_val, 0 },
158 { "section", obj_coff_section, 0 },
159 { "text", obj_coff_text, 0 },
160 { "data", obj_coff_data, 0 },
161 /* we don't yet handle this. */
162 { "ident", s_ignore, 0 },
163 { "ABORT", s_abort, 0 },
164 { "lcomm", obj_coff_lcomm, 0},
165 { NULL} /* end sentinel */
166 }; /* obj_pseudo_table */
167
168
169
170 /* Section stuff
171
172 We allow more than just the standard 3 sections, infact, we allow
173 10 sections, (though the usual three have to be there).
174
175 This structure performs the mappings for us:
176
177 */
178
179 /* OBS stuff
180 static struct internal_scnhdr bss_section_header;
181 struct internal_scnhdr data_section_header;
182 struct internal_scnhdr text_section_header;
183
184 const segT N_TYPE_seg [32] =
185 {
186
187 };
188
189 */
190
191 #define N_SEG 32
192 typedef struct
193 {
194 segT seg_t;
195 int i;
196 } seg_info_type;
197
198 seg_info_type seg_info_off_by_4[N_SEG] =
199 {
200 {SEG_PTV, },
201 {SEG_NTV, },
202 {SEG_DEBUG, },
203 {SEG_ABSOLUTE, },
204 {SEG_UNKNOWN, },
205 {SEG_E0},
206 {SEG_E1},
207 {SEG_E2},
208 {SEG_E3},
209 {SEG_E4},
210 {SEG_E5},
211 {SEG_E6},
212 {SEG_E7},
213 {SEG_E8},
214 {SEG_E9},
215 {15},
216 {16},
217 {17},
218 {18},
219 {19},
220 {20},
221 {0},
222 {0},
223 {0},
224 {SEG_REGISTER},0,0,0,0};
225
226 #define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])
227 #define SEG_INFO_FROM_SEG_NUMBER(x) (seg_info_off_by_4[(x)])
228
229
230 static relax_addressT
231 DEFUN(relax_align,(address, alignment),
232 register relax_addressT address AND
233 register long alignment )
234 {
235 relax_addressT mask;
236 relax_addressT new_address;
237
238 mask = ~ ( (~0) << alignment );
239 new_address = (address + mask) & (~ mask);
240 return (new_address - address);
241 } /* relax_align() */
242
243
244 segT
245 DEFUN(s_get_segment,(x) ,
246 symbolS* x)
247 {
248 return SEG_INFO_FROM_SECTION_NUMBER(x->sy_symbol.ost_entry.n_scnum).seg_t;
249 }
250
251
252
253 /* calculate the size of the frag chain and fill in the section header
254 to contain all of it, also fill in the addr of the sections */
255 static unsigned int DEFUN(size_section,(abfd, idx),
256 bfd *abfd AND
257 unsigned int idx)
258 {
259
260 unsigned int size = 0;
261 fragS *frag = segment_info[idx].frchainP->frch_root;
262 while (frag) {
263 if (frag->fr_address != size) {
264 printf("Out of step\n");
265 size = frag->fr_address;
266 }
267 size += frag->fr_fix;
268 switch (frag->fr_type) {
269 case rs_fill:
270 case rs_org:
271 size += frag->fr_offset * frag->fr_var;
272 break;
273 case rs_align:
274 size += relax_align(size, frag->fr_offset);
275 }
276 frag = frag->fr_next;
277 }
278 segment_info[idx].scnhdr.s_size = size;
279 return size;
280 }
281
282
283 static unsigned int DEFUN(count_entries_in_chain,(idx),
284 unsigned int idx)
285 {
286 unsigned int nrelocs;
287 fixS *fixup_ptr;
288
289 /* Count the relocations */
290 fixup_ptr = segment_info[idx].fix_root;
291 nrelocs = 0;
292 while (fixup_ptr != (fixS *)NULL)
293 {
294 if (TC_COUNT_RELOC(fixup_ptr))
295 {
296
297 #ifdef TC_A29K
298
299 if (fixup_ptr->fx_r_type == RELOC_CONSTH)
300 nrelocs+=2;
301 else
302 nrelocs++;
303 #else
304 nrelocs++;
305 #endif
306 }
307
308 fixup_ptr = fixup_ptr->fx_next;
309 }
310 return nrelocs;
311 }
312
313 /* output all the relocations for a section */
314 void DEFUN(do_relocs_for,(abfd, file_cursor),
315 bfd *abfd AND
316 unsigned long *file_cursor)
317 {
318 unsigned int nrelocs;
319
320
321
322 unsigned int idx;
323
324
325
326
327 for (idx = SEG_E0; idx < SEG_E9; idx++)
328 {
329 if (segment_info[idx].scnhdr.s_name[0])
330 {
331
332 struct external_reloc *ext_ptr;
333 struct external_reloc *external_reloc_vec;
334 unsigned int external_reloc_size;
335 unsigned int count = 0;
336 unsigned int base = segment_info[idx].scnhdr.s_paddr;
337 fixS * fix_ptr = segment_info[idx].fix_root;
338 nrelocs = count_entries_in_chain(idx);
339 external_reloc_size = nrelocs * RELSZ;
340 external_reloc_vec =
341 (struct external_reloc*)malloc(external_reloc_size);
342
343
344
345 ext_ptr = external_reloc_vec;
346
347 /* Fill in the internal coff style reloc struct from the
348 internal fix list */
349 while (fix_ptr)
350 {
351 symbolS *symbol_ptr;
352 struct internal_reloc intr;
353
354 /* Only output some of the relocations */
355 if (TC_COUNT_RELOC(fix_ptr))
356 {
357 symbolS *dot;
358 symbol_ptr = fix_ptr->fx_addsy;
359
360 intr.r_type = TC_COFF_FIX2RTYPE(fix_ptr);
361 intr.r_vaddr = base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where ;
362
363
364 /* Turn the segment of the symbol into an offset
365 */
366 dot =
367 segment_info[S_GET_SEGMENT(symbol_ptr)].dot;
368
369 if (dot)
370 {
371 intr.r_symndx = dot->sy_number;
372 }
373 else
374 {
375 intr.r_symndx = symbol_ptr->sy_number;
376 }
377
378
379 (void)bfd_coff_swap_reloc_out(abfd, &intr, ext_ptr);
380 ext_ptr++;
381
382 #if defined(TC_A29K)
383 /* The 29k has a special kludge for the high 16 bit reloc.
384 Two relocations are emmited, R_IHIHALF, and
385 R_IHCONST. The second one doesn't contain a symbol,
386 but uses the value for offset */
387
388 if (intr.r_type == R_IHIHALF)
389 {
390 /* now emit the second bit */
391 intr.r_type = R_IHCONST;
392 intr.r_symndx = fix_ptr->fx_addnumber;
393 (void)bfd_coff_swap_reloc_out(abfd,&intr,ext_ptr);
394 ext_ptr++;
395 }
396 #endif
397 }
398
399 fix_ptr = fix_ptr->fx_next;
400 }
401
402 /* Write out the reloc table */
403 segment_info[idx].scnhdr.s_relptr = *file_cursor;
404 segment_info[idx].scnhdr.s_nreloc = nrelocs;
405 bfd_write((PTR)external_reloc_vec, 1, external_reloc_size, abfd);
406 *file_cursor += external_reloc_size;
407 free( external_reloc_vec);
408 }
409 }
410 }
411
412
413 /* run through a frag chain and write out the data to go with it, fill
414 in the scnhdrs with the info on the file postions
415 */
416 static void DEFUN(fill_section,(abfd, filehdr, file_cursor),
417 bfd *abfd AND
418 struct internal_filehdr *filehdr AND
419 unsigned long *file_cursor)
420 {
421
422 unsigned int i;
423 unsigned int paddr = 0;
424
425 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
426 {
427 unsigned int offset = 0;
428
429 struct internal_scnhdr *s = &( segment_info[i].scnhdr);
430
431 if (s->s_name[0])
432 {
433 fragS *frag = segment_info[i].frchainP->frch_root;
434 char *buffer = malloc(s->s_size);
435 s->s_scnptr = *file_cursor;
436 s->s_paddr = paddr;
437 s->s_vaddr = paddr;
438
439 s->s_flags = STYP_REG;
440 if (strcmp(s->s_name,".text")==0)
441 s->s_flags |= STYP_TEXT;
442 else if (strcmp(s->s_name,".data")==0)
443 s->s_flags |= STYP_DATA;
444 else if (strcmp(s->s_name,".bss")==0)
445 s->s_flags |= STYP_BSS | STYP_NOLOAD;
446
447 while (frag) {
448 unsigned int fill_size;
449 switch (frag->fr_type) {
450
451 case rs_fill:
452 case rs_align:
453 case rs_org:
454 if(frag->fr_fix)
455 {
456 memcpy(buffer + frag->fr_address,
457 frag->fr_literal,
458 frag->fr_fix);
459 offset += frag->fr_fix;
460 }
461
462 fill_size = frag->fr_var;
463 if (fill_size)
464 {
465 unsigned int count ;
466 unsigned int off = frag->fr_fix;
467 for (count = frag->fr_offset; count; count--)
468 {
469 memcpy(buffer + frag->fr_address + off,
470 frag->fr_literal + frag->fr_fix,
471 fill_size);
472 off += fill_size;
473 offset += fill_size;
474
475 }
476
477 }
478 break;
479 default:
480 abort();
481 }
482 frag = frag->fr_next;
483 }
484
485
486 bfd_write(buffer, s->s_size,1,abfd);
487 free(buffer);
488
489 *file_cursor += s->s_size;
490 paddr += s->s_size;
491 }
492 }
493
494 }
495
496
497
498 /* Coff file generation & utilities */
499
500
501 static void
502 DEFUN(coff_header_append,(abfd, filehdr, aouthdr),
503 bfd *abfd AND
504 struct internal_filehdr *filehdr AND
505 struct internal_aouthdr *aouthdr)
506 {
507 unsigned int i;
508 char buffer[1000];
509 char buffero[1000];
510
511 bfd_seek(abfd, 0, 0);
512 #if 0
513 filehdr.f_opthdr = bfd_coff_swap_aouthdr_out(abfd, aouthdr,
514 buffero);
515 #else
516 filehdr->f_opthdr = 0;
517 #endif
518 i = bfd_coff_swap_filehdr_out(abfd, filehdr, buffer);
519
520 bfd_write(buffer, i ,1, abfd);
521 bfd_write(buffero, filehdr->f_opthdr, 1, abfd);
522
523 for (i = SEG_E0; i < SEG_E9; i++)
524 {
525 if (segment_info[i].scnhdr.s_name[0])
526 {
527 unsigned int size =
528 bfd_coff_swap_scnhdr_out(abfd,
529 &(segment_info[i].scnhdr),
530 buffer);
531 bfd_write(buffer, size, 1, abfd);
532 }
533 }
534 }
535
536
537 char *
538 DEFUN(symbol_to_chars,(abfd, where, symbolP),
539 bfd*abfd AND
540 char *where AND
541 symbolS *symbolP)
542 {
543 unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
544 unsigned int i;
545
546 /* Turn any symbols with register attributes into abs symbols */
547 if (S_GET_SEGMENT(symbolP) == SEG_REGISTER)
548 {
549 S_SET_SEGMENT(symbolP, SEG_ABSOLUTE);
550 }
551 /* At the same time, relocate all symbols to their output value */
552
553 S_SET_VALUE(symbolP,
554 segment_info[S_GET_SEGMENT(symbolP)].scnhdr.s_paddr
555 + S_GET_VALUE(symbolP));
556
557 where += bfd_coff_swap_sym_out(abfd, &symbolP->sy_symbol.ost_entry,
558 where);
559
560 for (i = 0; i < numaux; i++)
561 {
562 where += bfd_coff_swap_aux_out(abfd,
563 &symbolP->sy_symbol.ost_auxent[i],
564 S_GET_DATA_TYPE(symbolP),
565 S_GET_STORAGE_CLASS(symbolP),
566 where);
567 }
568 return where;
569
570 }
571
572
573
574
575 void obj_symbol_new_hook(symbolP)
576 symbolS *symbolP;
577 {
578 char underscore = 0; /* Symbol has leading _ */
579
580 /* Effective symbol */
581 /* Store the pointer in the offset. */
582 S_SET_ZEROES(symbolP, 0L);
583 S_SET_DATA_TYPE(symbolP, T_NULL);
584 S_SET_STORAGE_CLASS(symbolP, 0);
585 S_SET_NUMBER_AUXILIARY(symbolP, 0);
586 /* Additional information */
587 symbolP->sy_symbol.ost_flags = 0;
588 /* Auxiliary entries */
589 bzero((char*)&symbolP->sy_symbol.ost_auxent[0], AUXESZ);
590
591 #ifdef STRIP_UNDERSCORE
592 /* Remove leading underscore at the beginning of the symbol.
593 * This is to be compatible with the standard librairies.
594 */
595 if (*S_GET_NAME(symbolP) == '_') {
596 underscore = 1;
597 S_SET_NAME(symbolP, S_GET_NAME(symbolP) + 1);
598 } /* strip underscore */
599 #endif /* STRIP_UNDERSCORE */
600
601 if (S_IS_STRING(symbolP))
602 SF_SET_STRING(symbolP);
603 if (!underscore && S_IS_LOCAL(symbolP))
604 SF_SET_LOCAL(symbolP);
605
606 return;
607 } /* obj_symbol_new_hook() */
608
609 /* stack stuff */
610 stack* stack_init(chunk_size, element_size)
611 unsigned long chunk_size;
612 unsigned long element_size;
613 {
614 stack* st;
615
616 if ((st = (stack*)malloc(sizeof(stack))) == (stack*)0)
617 return (stack*)0;
618 if ((st->data = malloc(chunk_size)) == (char*)0) {
619 free(st);
620 return (stack*)0;
621 }
622 st->pointer = 0;
623 st->size = chunk_size;
624 st->chunk_size = chunk_size;
625 st->element_size = element_size;
626 return st;
627 } /* stack_init() */
628
629 void stack_delete(st)
630 stack* st;
631 {
632 free(st->data);
633 free(st);
634 }
635
636 char *stack_push(st, element)
637 stack *st;
638 char *element;
639 {
640 if (st->pointer + st->element_size >= st->size) {
641 st->size += st->chunk_size;
642 if ((st->data = xrealloc(st->data, st->size)) == (char*)0)
643 return (char*)0;
644 }
645 memcpy(st->data + st->pointer, element, st->element_size);
646 st->pointer += st->element_size;
647 return st->data + st->pointer;
648 } /* stack_push() */
649
650 char* stack_pop(st)
651 stack* st;
652 {
653 if ((st->pointer -= st->element_size) < 0) {
654 st->pointer = 0;
655 return (char*)0;
656 }
657
658 return st->data + st->pointer;
659 }
660
661 char* stack_top(st)
662 stack* st;
663 {
664 return st->data + st->pointer - st->element_size;
665 }
666
667
668 /*
669 * Handle .ln directives.
670 */
671
672 static void obj_coff_ln() {
673 if (def_symbol_in_progress != NULL) {
674 as_warn(".ln pseudo-op inside .def/.endef: ignored.");
675 demand_empty_rest_of_line();
676 return;
677 } /* wrong context */
678
679 c_line_new(0,
680 obstack_next_free(&frags) - frag_now->fr_literal,
681 get_absolute_expression(),
682 frag_now);
683
684 demand_empty_rest_of_line();
685 return;
686 } /* obj_coff_line() */
687
688 /*
689 * def()
690 *
691 * Handle .def directives.
692 *
693 * One might ask : why can't we symbol_new if the symbol does not
694 * already exist and fill it with debug information. Because of
695 * the C_EFCN special symbol. It would clobber the value of the
696 * function symbol before we have a chance to notice that it is
697 * a C_EFCN. And a second reason is that the code is more clear this
698 * way. (at least I think it is :-).
699 *
700 */
701
702 #define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
703 #define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
704 *input_line_pointer == '\t') \
705 input_line_pointer++;
706
707 static void
708 DEFUN(obj_coff_def,(what),
709 int what)
710 {
711 char name_end; /* Char after the end of name */
712 char *symbol_name; /* Name of the debug symbol */
713 char *symbol_name_copy; /* Temporary copy of the name */
714 unsigned int symbol_name_length;
715 /*$char* directiveP;$ */ /* Name of the pseudo opcode */
716 /*$char directive[MAX_DIRECTIVE];$ */ /* Backup of the directive */
717 /*$char end = 0;$ */ /* If 1, stop parsing */
718
719 if (def_symbol_in_progress != NULL) {
720 as_warn(".def pseudo-op used inside of .def/.endef: ignored.");
721 demand_empty_rest_of_line();
722 return;
723 } /* if not inside .def/.endef */
724
725 SKIP_WHITESPACES();
726
727 def_symbol_in_progress = (symbolS *) obstack_alloc(&notes, sizeof(*def_symbol_in_progress));
728 bzero(def_symbol_in_progress, sizeof(*def_symbol_in_progress));
729
730 symbol_name = input_line_pointer;
731 name_end = get_symbol_end();
732 symbol_name_length = strlen(symbol_name);
733 symbol_name_copy = xmalloc(symbol_name_length + 1);
734 strcpy(symbol_name_copy, symbol_name);
735
736 /* Initialize the new symbol */
737 #ifdef STRIP_UNDERSCORE
738 S_SET_NAME(def_symbol_in_progress, (*symbol_name_copy == '_'
739 ? symbol_name_copy + 1
740 : symbol_name_copy));
741 #else /* STRIP_UNDERSCORE */
742 S_SET_NAME(def_symbol_in_progress, symbol_name_copy);
743 #endif /* STRIP_UNDERSCORE */
744 /* free(symbol_name_copy); */
745 def_symbol_in_progress->sy_name_offset = ~0;
746 def_symbol_in_progress->sy_number = ~0;
747 def_symbol_in_progress->sy_frag = &zero_address_frag;
748
749 if (S_IS_STRING(def_symbol_in_progress)) {
750 SF_SET_STRING(def_symbol_in_progress);
751 } /* "long" name */
752
753 *input_line_pointer = name_end;
754
755 demand_empty_rest_of_line();
756 return;
757 } /* obj_coff_def() */
758
759 unsigned int dim_index;
760 static void
761 DEFUN_VOID(obj_coff_endef)
762 {
763 symbolS *symbolP = 0;
764 /* DIM BUG FIX sac@cygnus.com */
765 dim_index =0;
766 if (def_symbol_in_progress == NULL) {
767 as_warn(".endef pseudo-op used outside of .def/.endef: ignored.");
768 demand_empty_rest_of_line();
769 return;
770 } /* if not inside .def/.endef */
771
772 /* Set the section number according to storage class. */
773 switch (S_GET_STORAGE_CLASS(def_symbol_in_progress)) {
774 case C_STRTAG:
775 case C_ENTAG:
776 case C_UNTAG:
777 SF_SET_TAG(def_symbol_in_progress);
778 /* intentional fallthrough */
779 case C_FILE:
780 case C_TPDEF:
781 SF_SET_DEBUG(def_symbol_in_progress);
782 S_SET_SEGMENT(def_symbol_in_progress, SEG_DEBUG);
783 break;
784
785 case C_EFCN:
786 SF_SET_LOCAL(def_symbol_in_progress); /* Do not emit this symbol. */
787 /* intentional fallthrough */
788 case C_BLOCK:
789 SF_SET_PROCESS(def_symbol_in_progress); /* Will need processing before writing */
790 /* intentional fallthrough */
791 case C_FCN:
792 S_SET_SEGMENT(def_symbol_in_progress, SEG_E0);
793
794 if (def_symbol_in_progress->sy_symbol.ost_entry.n_name[1] == 'b') { /* .bf */
795 if (function_lineoff < 0) {
796 fprintf(stderr, "`.bf' symbol without preceding function\n");
797 } /* missing function symbol */
798 SA_GET_SYM_LNNOPTR(def_symbol_in_progress) = function_lineoff;
799 SF_SET_PROCESS(def_symbol_in_progress); /* Will need relocating */
800 function_lineoff = -1;
801 }
802 break;
803
804 #ifdef C_AUTOARG
805 case C_AUTOARG:
806 #endif /* C_AUTOARG */
807 case C_AUTO:
808 case C_REG:
809 case C_MOS:
810 case C_MOE:
811 case C_MOU:
812 case C_ARG:
813 case C_REGPARM:
814 case C_FIELD:
815 case C_EOS:
816 SF_SET_DEBUG(def_symbol_in_progress);
817 S_SET_SEGMENT(def_symbol_in_progress, SEG_ABSOLUTE);
818 break;
819
820 case C_EXT:
821 case C_STAT:
822 case C_LABEL:
823 /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
824 break;
825
826 case C_USTATIC:
827 case C_EXTDEF:
828 case C_ULABEL:
829 as_warn("unexpected storage class %d", S_GET_STORAGE_CLASS(def_symbol_in_progress));
830 break;
831 } /* switch on storage class */
832
833 /* Now that we have built a debug symbol, try to
834 find if we should merge with an existing symbol
835 or not. If a symbol is C_EFCN or SEG_ABSOLUTE or
836 untagged SEG_DEBUG it never merges. */
837
838 /* Two cases for functions. Either debug followed
839 by definition or definition followed by debug.
840 For definition first, we will merge the debug
841 symbol into the definition. For debug first, the
842 lineno entry MUST point to the definition
843 function or else it will point off into space
844 when crawl_symbols() merges the debug
845 symbol into the real symbol. Therefor, let's
846 presume the debug symbol is a real function
847 reference. */
848
849 /* FIXME-SOON If for some reason the definition
850 label/symbol is never seen, this will probably
851 leave an undefined symbol at link time. */
852
853 if (S_GET_STORAGE_CLASS(def_symbol_in_progress) == C_EFCN
854 || (S_GET_SEGMENT(def_symbol_in_progress) == SEG_DEBUG
855 && !SF_GET_TAG(def_symbol_in_progress))
856 || S_GET_SEGMENT(def_symbol_in_progress) == SEG_ABSOLUTE
857 || (symbolP = symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP)) == NULL) {
858
859 symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
860
861 } else {
862 /* This symbol already exists, merge the
863 newly created symbol into the old one.
864 This is not mandatory. The linker can
865 handle duplicate symbols correctly. But I
866 guess that it save a *lot* of space if
867 the assembly file defines a lot of
868 symbols. [loic] */
869
870 /* The debug entry (def_symbol_in_progress)
871 is merged into the previous definition. */
872
873 c_symbol_merge(def_symbol_in_progress, symbolP);
874 /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
875 def_symbol_in_progress = symbolP;
876
877 if (SF_GET_FUNCTION(def_symbol_in_progress)
878 || SF_GET_TAG(def_symbol_in_progress)) {
879 /* For functions, and tags, the symbol *must* be where the debug symbol
880 appears. Move the existing symbol to the current place. */
881 /* If it already is at the end of the symbol list, do nothing */
882 if (def_symbol_in_progress != symbol_lastP) {
883 symbol_remove(def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
884 symbol_append(def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
885 } /* if not already in place */
886 } /* if function */
887 } /* normal or mergable */
888
889 if (SF_GET_TAG(def_symbol_in_progress)
890 && symbol_find_base(S_GET_NAME(def_symbol_in_progress), DO_NOT_STRIP) == NULL) {
891 tag_insert(S_GET_NAME(def_symbol_in_progress), def_symbol_in_progress);
892 } /* If symbol is a {structure,union} tag, associate symbol to its name. */
893
894 if (SF_GET_FUNCTION(def_symbol_in_progress)) {
895 know(sizeof(def_symbol_in_progress) <= sizeof(long));
896 function_lineoff
897 = c_line_new((long)
898 def_symbol_in_progress,0, 0, &zero_address_frag);
899
900
901
902 SF_SET_PROCESS(def_symbol_in_progress);
903
904 if (symbolP == NULL) {
905 /* That is, if this is the first
906 time we've seen the function... */
907 symbol_table_insert(def_symbol_in_progress);
908 } /* definition follows debug */
909 } /* Create the line number entry pointing to the function being defined */
910
911 def_symbol_in_progress = NULL;
912 demand_empty_rest_of_line();
913 return;
914 } /* obj_coff_endef() */
915
916 static void
917 DEFUN_VOID(obj_coff_dim)
918 {
919 register int dim_index;
920
921 if (def_symbol_in_progress == NULL)
922 {
923 as_warn(".dim pseudo-op used outside of .def/.endef: ignored.");
924 demand_empty_rest_of_line();
925 return;
926 } /* if not inside .def/.endef */
927
928 S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
929
930 for (dim_index = 0; dim_index < DIMNUM; dim_index++)
931 {
932 SKIP_WHITESPACES();
933 SA_SET_SYM_DIMEN(def_symbol_in_progress, dim_index, get_absolute_expression());
934
935 switch (*input_line_pointer)
936 {
937
938 case ',':
939 input_line_pointer++;
940 break;
941
942 default:
943 as_warn("badly formed .dim directive ignored");
944 /* intentional fallthrough */
945 case '\n':
946 case ';':
947 dim_index = DIMNUM;
948 break;
949 } /* switch on following character */
950 } /* for each dimension */
951
952 demand_empty_rest_of_line();
953 return;
954 } /* obj_coff_dim() */
955
956 static void obj_coff_line() {
957 if (def_symbol_in_progress == NULL) {
958 obj_coff_ln();
959 return;
960 } /* if it looks like a stabs style line */
961
962 S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
963 SA_SET_SYM_LNNO(def_symbol_in_progress, get_absolute_expression());
964
965 demand_empty_rest_of_line();
966 return;
967 } /* obj_coff_line() */
968
969 static void obj_coff_size() {
970 if (def_symbol_in_progress == NULL) {
971 as_warn(".size pseudo-op used outside of .def/.endef ignored.");
972 demand_empty_rest_of_line();
973 return;
974 } /* if not inside .def/.endef */
975
976 S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
977 SA_SET_SYM_SIZE(def_symbol_in_progress, get_absolute_expression());
978 demand_empty_rest_of_line();
979 return;
980 } /* obj_coff_size() */
981
982 static void obj_coff_scl() {
983 if (def_symbol_in_progress == NULL) {
984 as_warn(".scl pseudo-op used outside of .def/.endef ignored.");
985 demand_empty_rest_of_line();
986 return;
987 } /* if not inside .def/.endef */
988
989 S_SET_STORAGE_CLASS(def_symbol_in_progress, get_absolute_expression());
990 demand_empty_rest_of_line();
991 return;
992 } /* obj_coff_scl() */
993
994 static void obj_coff_tag() {
995 char *symbol_name;
996 char name_end;
997
998 if (def_symbol_in_progress == NULL) {
999 as_warn(".tag pseudo-op used outside of .def/.endef ignored.");
1000 demand_empty_rest_of_line();
1001 return;
1002 } /* if not inside .def/.endef */
1003
1004 S_SET_NUMBER_AUXILIARY(def_symbol_in_progress, 1);
1005 symbol_name = input_line_pointer;
1006 name_end = get_symbol_end();
1007
1008 /* Assume that the symbol referred to by .tag is always defined. */
1009 /* This was a bad assumption. I've added find_or_make. xoxorich. */
1010 SA_SET_SYM_TAGNDX(def_symbol_in_progress, (long) tag_find_or_make(symbol_name));
1011 if (SA_GET_SYM_TAGNDX(def_symbol_in_progress) == 0L) {
1012 as_warn("tag not found for .tag %s", symbol_name);
1013 } /* not defined */
1014
1015 SF_SET_TAGGED(def_symbol_in_progress);
1016 *input_line_pointer = name_end;
1017
1018 demand_empty_rest_of_line();
1019 return;
1020 } /* obj_coff_tag() */
1021
1022 static void obj_coff_type() {
1023 if (def_symbol_in_progress == NULL) {
1024 as_warn(".type pseudo-op used outside of .def/.endef ignored.");
1025 demand_empty_rest_of_line();
1026 return;
1027 } /* if not inside .def/.endef */
1028
1029 S_SET_DATA_TYPE(def_symbol_in_progress, get_absolute_expression());
1030
1031 if (ISFCN(S_GET_DATA_TYPE(def_symbol_in_progress)) &&
1032 S_GET_STORAGE_CLASS(def_symbol_in_progress) != C_TPDEF) {
1033 SF_SET_FUNCTION(def_symbol_in_progress);
1034 } /* is a function */
1035
1036 demand_empty_rest_of_line();
1037 return;
1038 } /* obj_coff_type() */
1039
1040 static void obj_coff_val() {
1041 if (def_symbol_in_progress == NULL) {
1042 as_warn(".val pseudo-op used outside of .def/.endef ignored.");
1043 demand_empty_rest_of_line();
1044 return;
1045 } /* if not inside .def/.endef */
1046
1047 if (is_name_beginner(*input_line_pointer)) {
1048 char *symbol_name = input_line_pointer;
1049 char name_end = get_symbol_end();
1050
1051 if (!strcmp(symbol_name, ".")) {
1052 def_symbol_in_progress->sy_frag = frag_now;
1053 S_SET_VALUE(def_symbol_in_progress, obstack_next_free(&frags) - frag_now->fr_literal);
1054 /* If the .val is != from the .def (e.g. statics) */
1055 } else if (strcmp(S_GET_NAME(def_symbol_in_progress), symbol_name)) {
1056 def_symbol_in_progress->sy_forward = symbol_find_or_make(symbol_name);
1057
1058 /* If the segment is undefined when the forward
1059 reference is solved, then copy the segment id
1060 from the forward symbol. */
1061 SF_SET_GET_SEGMENT(def_symbol_in_progress);
1062 }
1063 /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
1064 *input_line_pointer = name_end;
1065 } else {
1066 S_SET_VALUE(def_symbol_in_progress, get_absolute_expression());
1067 } /* if symbol based */
1068
1069 demand_empty_rest_of_line();
1070 return;
1071 } /* obj_coff_val() */
1072
1073 /*
1074 * Maintain a list of the tagnames of the structres.
1075 */
1076
1077 static void tag_init() {
1078 tag_hash = hash_new();
1079 return ;
1080 } /* tag_init() */
1081
1082 static void tag_insert(name, symbolP)
1083 char *name;
1084 symbolS *symbolP;
1085 {
1086 register char * error_string;
1087
1088 if (*(error_string = hash_jam(tag_hash, name, (char *)symbolP))) {
1089 as_fatal("Inserting \"%s\" into structure table failed: %s",
1090 name, error_string);
1091 }
1092 return ;
1093 } /* tag_insert() */
1094
1095 static symbolS *tag_find_or_make(name)
1096 char *name;
1097 {
1098 symbolS *symbolP;
1099
1100 if ((symbolP = tag_find(name)) == NULL) {
1101 symbolP = symbol_new(name,
1102 SEG_UNKNOWN,
1103 0,
1104 &zero_address_frag);
1105
1106 tag_insert(S_GET_NAME(symbolP), symbolP);
1107 symbol_table_insert(symbolP);
1108 } /* not found */
1109
1110 return(symbolP);
1111 } /* tag_find_or_make() */
1112
1113 static symbolS *tag_find(name)
1114 char *name;
1115 {
1116 #ifdef STRIP_UNDERSCORE
1117 if (*name == '_') name++;
1118 #endif /* STRIP_UNDERSCORE */
1119 return((symbolS*)hash_find(tag_hash, name));
1120 } /* tag_find() */
1121
1122 void obj_read_begin_hook() {
1123 /* These had better be the same. Usually 18 bytes. */
1124 #ifndef BFD_HEADERS
1125 know(sizeof(SYMENT) == sizeof(AUXENT));
1126 know(SYMESZ == AUXESZ);
1127 #endif
1128 tag_init();
1129
1130 return;
1131 } /* obj_read_begin_hook() */
1132
1133 /* This function runs through the symbol table and puts all the
1134 externals onto another chain */
1135
1136 /* The chain of externals */
1137 symbolS *symbol_externP = NULL;
1138 symbolS *symbol_extern_lastP = NULL;
1139
1140 stack*block_stack;
1141 symbolS *last_functionP = NULL;
1142 symbolS *last_tagP;
1143
1144
1145 static unsigned int DEFUN_VOID(yank_symbols)
1146 {
1147 symbolS *symbolP;
1148 unsigned int symbol_number =0;
1149
1150 for (symbolP = symbol_rootP;
1151 symbolP;
1152 symbolP = symbolP ? symbol_next(symbolP) : symbol_rootP) {
1153 if (!SF_GET_DEBUG(symbolP)) {
1154 /* Debug symbols do not need all this rubbish */
1155 symbolS* real_symbolP;
1156
1157 /* L* and C_EFCN symbols never merge. */
1158 if (!SF_GET_LOCAL(symbolP)
1159 && (real_symbolP = symbol_find_base(S_GET_NAME(symbolP), DO_NOT_STRIP))
1160 && real_symbolP != symbolP) {
1161 /* FIXME-SOON: where do dups come from?
1162 Maybe tag references before definitions? xoxorich. */
1163 /* Move the debug data from the debug symbol to the
1164 real symbol. Do NOT do the oposite (i.e. move from
1165 real symbol to debug symbol and remove real symbol from the
1166 list.) Because some pointers refer to the real symbol
1167 whereas no pointers refer to the debug symbol. */
1168 c_symbol_merge(symbolP, real_symbolP);
1169 /* Replace the current symbol by the real one */
1170 /* The symbols will never be the last or the first
1171 because : 1st symbol is .file and 3 last symbols are
1172 .text, .data, .bss */
1173 symbol_remove(real_symbolP, &symbol_rootP, &symbol_lastP);
1174 symbol_insert(real_symbolP, symbolP, &symbol_rootP, &symbol_lastP);
1175 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1176 symbolP = real_symbolP;
1177 } /* if not local but dup'd */
1178
1179 if (flagseen['R'] && (S_GET_SEGMENT(symbolP) == SEG_E1)) {
1180 S_SET_SEGMENT(symbolP, SEG_E0);
1181 } /* push data into text */
1182
1183 S_SET_VALUE(symbolP,
1184 S_GET_VALUE(symbolP) + symbolP->sy_frag->fr_address);
1185
1186 if (!S_IS_DEFINED(symbolP) && !SF_GET_LOCAL(symbolP))
1187 {
1188 S_SET_EXTERNAL(symbolP);
1189 }
1190 else if (S_GET_STORAGE_CLASS(symbolP) == C_NULL)
1191 {
1192 if (S_GET_SEGMENT(symbolP) == SEG_E0)
1193 {
1194 S_SET_STORAGE_CLASS(symbolP, C_LABEL);
1195 }
1196 else
1197 {
1198 S_SET_STORAGE_CLASS(symbolP, C_STAT);
1199 }
1200 }
1201
1202 /* Mainly to speed up if not -g */
1203 if (SF_GET_PROCESS(symbolP))
1204 {
1205 /* Handle the nested blocks auxiliary info. */
1206 if (S_GET_STORAGE_CLASS(symbolP) == C_BLOCK) {
1207 if (!strcmp(S_GET_NAME(symbolP), ".bb"))
1208 stack_push(block_stack, (char *) &symbolP);
1209 else { /* .eb */
1210 register symbolS* begin_symbolP;
1211 begin_symbolP = *(symbolS**)stack_pop(block_stack);
1212 if (begin_symbolP == (symbolS*)0)
1213 as_warn("mismatched .eb");
1214 else
1215 SA_SET_SYM_ENDNDX(begin_symbolP, symbol_number+2);
1216 }
1217 }
1218 /* If we are able to identify the type of a function, and we
1219 are out of a function (last_functionP == 0) then, the
1220 function symbol will be associated with an auxiliary
1221 entry. */
1222 if (last_functionP == (symbolS*)0 &&
1223 SF_GET_FUNCTION(symbolP)) {
1224 last_functionP = symbolP;
1225
1226 if (S_GET_NUMBER_AUXILIARY(symbolP) < 1) {
1227 S_SET_NUMBER_AUXILIARY(symbolP, 1);
1228 } /* make it at least 1 */
1229
1230 /* Clobber possible stale .dim information. */
1231 bzero(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen,
1232 sizeof(symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
1233 }
1234 /* The C_FCN doesn't need any additional information.
1235 I don't even know if this is needed for sdb. But the
1236 standard assembler generates it, so...
1237 */
1238 if (S_GET_STORAGE_CLASS(symbolP) == C_EFCN) {
1239 if (last_functionP == (symbolS*)0)
1240 as_fatal("C_EFCN symbol out of scope");
1241 SA_SET_SYM_FSIZE(last_functionP,
1242 (long)(S_GET_VALUE(symbolP) -
1243 S_GET_VALUE(last_functionP)));
1244 SA_SET_SYM_ENDNDX(last_functionP, symbol_number);
1245 last_functionP = (symbolS*)0;
1246 }
1247 }
1248 } else if (SF_GET_TAG(symbolP)) {
1249 /* First descriptor of a structure must point to
1250 the first slot after the structure description. */
1251 last_tagP = symbolP;
1252
1253 } else if (S_GET_STORAGE_CLASS(symbolP) == C_EOS) {
1254 /* +2 take in account the current symbol */
1255 SA_SET_SYM_ENDNDX(last_tagP, symbol_number + 2);
1256 } else if (S_GET_STORAGE_CLASS(symbolP) == C_FILE) {
1257 if (S_GET_VALUE(symbolP)) {
1258 S_SET_VALUE((symbolS *) S_GET_VALUE(symbolP), symbol_number);
1259 S_SET_VALUE(symbolP, 0);
1260 } /* no one points at the first .file symbol */
1261 } /* if debug or tag or eos or file */
1262
1263 /* We must put the external symbols apart. The loader
1264 does not bomb if we do not. But the references in
1265 the endndx field for a .bb symbol are not corrected
1266 if an external symbol is removed between .bb and .be.
1267 I.e in the following case :
1268 [20] .bb endndx = 22
1269 [21] foo external
1270 [22] .be
1271 ld will move the symbol 21 to the end of the list but
1272 endndx will still be 22 instead of 21. */
1273
1274
1275 if (SF_GET_LOCAL(symbolP)) {
1276 /* remove C_EFCN and LOCAL (L...) symbols */
1277 /* next pointer remains valid */
1278 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1279
1280 }
1281 else if (!S_IS_DEFINED(symbolP)
1282 && !S_IS_DEBUG(symbolP)
1283 && !SF_GET_STATICS(symbolP) &&
1284 S_GET_STORAGE_CLASS(symbolP) == C_EXT)
1285 { /* C_EXT && !SF_GET_FUNCTION(symbolP)) */
1286 /* if external, Remove from the list */
1287 symbolS *hold = symbol_previous(symbolP);
1288
1289 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1290 symbol_clear_list_pointers(symbolP);
1291 symbol_append(symbolP, symbol_extern_lastP, &symbol_externP, &symbol_extern_lastP);
1292 symbolP = hold;
1293 } else {
1294 if (SF_GET_STRING(symbolP)) {
1295 symbolP->sy_name_offset = string_byte_count;
1296 string_byte_count += strlen(S_GET_NAME(symbolP)) + 1;
1297 } else {
1298 symbolP->sy_name_offset = 0;
1299 } /* fix "long" names */
1300
1301 symbolP->sy_number = symbol_number;
1302 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
1303 } /* if local symbol */
1304 } /* traverse the symbol list */
1305 return symbol_number;
1306
1307 }
1308
1309
1310 static unsigned int DEFUN_VOID(glue_symbols)
1311 {
1312 unsigned int symbol_number = 0;
1313 symbolS *symbolP;
1314 for (symbolP = symbol_externP; symbol_externP;) {
1315 symbolS *tmp = symbol_externP;
1316
1317 /* append */
1318 symbol_remove(tmp, &symbol_externP, &symbol_extern_lastP);
1319 symbol_append(tmp, symbol_lastP, &symbol_rootP, &symbol_lastP);
1320
1321 /* and process */
1322 if (SF_GET_STRING(tmp)) {
1323 tmp->sy_name_offset = string_byte_count;
1324 string_byte_count += strlen(S_GET_NAME(tmp)) + 1;
1325 } else {
1326 tmp->sy_name_offset = 0;
1327 } /* fix "long" names */
1328
1329 tmp->sy_number = symbol_number;
1330 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(tmp);
1331 } /* append the entire extern chain */
1332 return symbol_number;
1333
1334 }
1335
1336 static unsigned int DEFUN_VOID(tie_tags)
1337 {
1338 unsigned int symbol_number = 0;
1339
1340 symbolS*symbolP;
1341 for (symbolP = symbol_rootP; symbolP; symbolP =
1342 symbol_next(symbolP))
1343 {
1344 symbolP->sy_number = symbol_number;
1345
1346
1347
1348 if (SF_GET_TAGGED(symbolP))
1349 {
1350 SA_SET_SYM_TAGNDX
1351 (symbolP,
1352 ((symbolS*) SA_GET_SYM_TAGNDX(symbolP))->sy_number);
1353 }
1354
1355 symbol_number += 1 + S_GET_NUMBER_AUXILIARY(symbolP);
1356 }
1357 return symbol_number;
1358
1359 }
1360
1361 static void
1362 DEFUN(crawl_symbols,(headers, abfd),
1363 struct internal_filehdr *headers AND
1364 bfd *abfd)
1365 {
1366
1367 unsigned int i;
1368 unsigned int ptr = 0;
1369
1370
1371 symbolS *symbolP;
1372
1373 /* Initialize the stack used to keep track of the matching .bb .be */
1374
1375 block_stack = stack_init(512, sizeof(symbolS*));
1376 /* JF deal with forward references first... */
1377 for (symbolP = symbol_rootP;
1378 symbolP;
1379 symbolP = symbol_next(symbolP))
1380 {
1381
1382 if (symbolP->sy_forward) {
1383 S_SET_VALUE(symbolP, (S_GET_VALUE(symbolP)
1384 + S_GET_VALUE(symbolP->sy_forward)
1385 + symbolP->sy_forward->sy_frag->fr_address));
1386
1387 if (SF_GET_GET_SEGMENT(symbolP)) {
1388 S_SET_SEGMENT(symbolP, S_GET_SEGMENT(symbolP->sy_forward));
1389 } /* forward segment also */
1390
1391 symbolP->sy_forward=0;
1392 } /* if it has a forward reference */
1393 } /* walk the symbol chain */
1394
1395
1396 /* The symbol list should be ordered according to the following sequence
1397 * order :
1398 * . .file symbol
1399 * . debug entries for functions
1400 * . fake symbols for the sections, including.text .data and .bss
1401 * . defined symbols
1402 * . undefined symbols
1403 * But this is not mandatory. The only important point is to put the
1404 * undefined symbols at the end of the list.
1405 */
1406
1407 if (symbol_rootP == NULL
1408 || S_GET_STORAGE_CLASS(symbol_rootP) != C_FILE) {
1409 c_dot_file_symbol("fake");
1410 }
1411 /* Is there a .file symbol ? If not insert one at the beginning. */
1412
1413 /*
1414 * Build up static symbols for the sections, they are filled in later
1415 */
1416
1417
1418 for (i = SEG_E0; i < SEG_E9; i++)
1419 {
1420 if (segment_info[i].scnhdr.s_name[0])
1421 {
1422 segment_info[i].dot =
1423 c_section_symbol(segment_info[i].scnhdr.s_name,
1424 i-SEG_E0+1);
1425
1426 }
1427 }
1428
1429
1430 /* Take all the externals out and put them into another chain */
1431 headers->f_nsyms = yank_symbols();
1432 /* Take the externals and glue them onto the end.*/
1433 headers->f_nsyms += glue_symbols();
1434
1435 headers->f_nsyms = tie_tags();
1436 know(symbol_externP == NULL);
1437 know(symbol_extern_lastP == NULL);
1438
1439 return;
1440 }
1441
1442 /*
1443 * Find strings by crawling along symbol table chain.
1444 */
1445
1446 void DEFUN(w_strings,(where),
1447 char *where)
1448 {
1449 symbolS *symbolP;
1450
1451 /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
1452 md_number_to_chars(where, string_byte_count, sizeof(string_byte_count));
1453 where += sizeof(string_byte_count);
1454 for (symbolP = symbol_rootP;
1455 symbolP;
1456 symbolP = symbol_next(symbolP))
1457 {
1458 unsigned int size;
1459
1460 if (SF_GET_STRING(symbolP)) {
1461 size = strlen(S_GET_NAME(symbolP)) + 1;
1462
1463 memcpy(where, S_GET_NAME(symbolP),size);
1464 where += size;
1465
1466 }
1467 }
1468
1469 }
1470
1471
1472
1473
1474
1475 static void
1476 DEFUN(do_linenos_for,(abfd, file_cursor),
1477 bfd *abfd AND
1478 unsigned long *file_cursor)
1479 {
1480 unsigned int idx;
1481
1482 for (idx = SEG_E0; idx < SEG_E9; idx++)
1483 {
1484 segment_info_type *s = segment_info + idx;
1485
1486 if (s->scnhdr.s_nlnno != 0)
1487 {
1488 struct lineno_list *line_ptr ;
1489
1490 struct external_lineno *buffer =
1491 (struct external_lineno *)xmalloc(s->scnhdr.s_nlnno * LINESZ);
1492
1493 struct external_lineno *dst= buffer;
1494
1495 /* Run through the table we've built and turn it into its external
1496 form */
1497
1498 for (line_ptr = s->lineno_list_head;
1499 line_ptr != (struct lineno_list *)NULL;
1500 line_ptr = line_ptr->next)
1501 {
1502 if (line_ptr->line.l_lnno == 0)
1503 {
1504 /* Turn a pointer to a symbol into the symbols' index */
1505 line_ptr->line.l_addr.l_symndx =
1506 ( (symbolS *)line_ptr->line.l_addr.l_symndx)->sy_number;
1507 }
1508 (void) bfd_coff_swap_lineno_out(abfd, &(line_ptr->line), dst);
1509 dst++;
1510 }
1511
1512 s->scnhdr.s_lnnoptr = *file_cursor;
1513
1514 bfd_write(buffer, 1, s->scnhdr.s_nlnno* LINESZ, abfd);
1515 free(buffer);
1516
1517 *file_cursor += s->scnhdr.s_nlnno * LINESZ;
1518 }
1519 }
1520 }
1521
1522
1523 /* Now we run through the list of frag chains in a segment and
1524 make all the subsegment frags appear at the end of the
1525 list, as if the seg 0 was extra long */
1526
1527 static void DEFUN_VOID(remove_subsegs)
1528 {
1529 unsigned int i;
1530
1531 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1532 {
1533 frchainS *head = segment_info[i].frchainP;
1534 fragS dummy;
1535 fragS * prev_frag = &dummy;
1536
1537 while (head && head->frch_seg == i)
1538 {
1539 prev_frag->fr_next = head->frch_root;
1540 prev_frag = head->frch_last;
1541 head = head->frch_next;
1542 }
1543 prev_frag->fr_next = 0;
1544 }
1545 }
1546
1547
1548 extern void DEFUN_VOID(write_object_file)
1549 {
1550 int i;
1551 struct frchain *frchain_ptr;
1552
1553 struct internal_filehdr filehdr;
1554 struct internal_aouthdr aouthdr;
1555 unsigned long file_cursor;
1556 bfd *abfd;
1557 unsigned int addr = 0;
1558 abfd = bfd_openw(out_file_name, TARGET_FORMAT);
1559
1560
1561 if (abfd == 0) {
1562 as_perror ("FATAL: Can't create %s", out_file_name);
1563 exit(42);
1564 }
1565 bfd_set_format(abfd, bfd_object);
1566 bfd_set_arch_mach(abfd, BFD_ARCH, 0);
1567
1568
1569
1570 string_byte_count = 4;
1571
1572 for (frchain_ptr = frchain_root;
1573 frchain_ptr != (struct frchain *)NULL;
1574 frchain_ptr = frchain_ptr->frch_next) {
1575 /* Run through all the sub-segments and align them up. Also close any
1576 open frags. We tack a .fill onto the end of the frag chain so
1577 that any .align's size can be worked by looking at the next
1578 frag */
1579
1580 subseg_new(frchain_ptr->frch_seg, frchain_ptr->frch_subseg);
1581 #define SUB_SEGMENT_ALIGN 1
1582 frag_align(SUB_SEGMENT_ALIGN,0);
1583 frag_wane(frag_now);
1584 frag_now->fr_fix = 0;
1585 know( frag_now->fr_next == NULL );
1586 }
1587
1588
1589 remove_subsegs();
1590
1591
1592 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1593 {
1594 relax_segment(segment_info[i].frchainP->frch_root, i);
1595 }
1596
1597
1598
1599
1600
1601 filehdr.f_nscns = 0;
1602
1603 /* Find out how big the sections are */
1604 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1605 {
1606
1607 if (segment_info[i].scnhdr.s_name[0])
1608 {
1609 filehdr.f_nscns++;
1610 }
1611 segment_info[i].scnhdr.s_paddr = addr;
1612 if (i == SEG_E2) {
1613 /* THis is a special case, we leave the size alone, which will have */
1614 /* been made up from all and any lcomms seen */
1615 }
1616 else {
1617 addr += size_section(abfd, i);
1618 }
1619 }
1620
1621
1622
1623 /* Turn the gas native symbol table shape into a coff symbol table */
1624 crawl_symbols(&filehdr, abfd);
1625
1626 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
1627 {
1628 fixup_segment(segment_info[i].fix_root, i);
1629 }
1630
1631 file_cursor = FILHSZ + SCNHSZ * filehdr.f_nscns ;
1632
1633 bfd_seek(abfd, file_cursor, 0);
1634
1635
1636 do_relocs_for(abfd, &file_cursor);
1637
1638 do_linenos_for(abfd, &file_cursor);
1639
1640
1641 /* Plant the data */
1642
1643 fill_section(abfd,&filehdr, &file_cursor);
1644
1645 filehdr.f_magic = COFF_MAGIC;
1646 filehdr.f_timdat = 0;
1647 filehdr.f_flags = 0;
1648
1649
1650
1651 {
1652
1653 unsigned int symtable_size = filehdr.f_nsyms * SYMESZ;
1654 char *buffer1 = malloc(symtable_size + string_byte_count + 4);
1655 char *ptr = buffer1;
1656 filehdr.f_symptr = bfd_tell(abfd);
1657 w_symbols(abfd, buffer1, symbol_rootP);
1658 w_strings(buffer1 + symtable_size);
1659 bfd_write(buffer1, 1,symtable_size + string_byte_count + 4, abfd);
1660 free(buffer1);
1661
1662 }
1663 coff_header_append(abfd, &filehdr, &aouthdr);
1664
1665 bfd_close_all_done(abfd);
1666 }
1667
1668
1669 static void DEFUN(change_to_section,(name, len, exp),
1670 char *name AND
1671 unsigned int len AND
1672 unsigned int exp)
1673 {
1674 unsigned int i;
1675 /* Find out if we've already got a section of this name etc */
1676 for(i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0] ; i++)
1677 {
1678 if (strncmp(segment_info[i].scnhdr.s_name, name, len) == 0)
1679 {
1680 subseg_new(i, exp);
1681 return;
1682
1683 }
1684 }
1685 /* No section, add one */
1686 strncpy(segment_info[i].scnhdr.s_name, name, 8);
1687 subseg_new(i, exp);
1688 }
1689
1690 static void
1691 DEFUN_VOID(obj_coff_section)
1692 {
1693 /* Strip out the section name */
1694 char *section_name ;
1695 char *section_name_end;
1696 char c;
1697
1698 unsigned int len;
1699 unsigned int exp;
1700
1701 section_name = input_line_pointer;
1702 c = get_symbol_end();
1703 section_name_end = input_line_pointer;
1704
1705 len = section_name_end - section_name ;
1706 input_line_pointer++;
1707 SKIP_WHITESPACE();
1708 if (c == ',')
1709 {
1710 exp = get_absolute_expression();
1711 }
1712 else if ( *input_line_pointer == ',')
1713 {
1714
1715 input_line_pointer++;
1716 exp = get_absolute_expression();
1717 }
1718 else
1719 {
1720 exp = 0;
1721 }
1722
1723 change_to_section(section_name, len,exp);
1724
1725 }
1726
1727
1728 static void obj_coff_text()
1729 {
1730 change_to_section(".text",5, get_absolute_expression());
1731 }
1732
1733
1734 static void obj_coff_data()
1735 {
1736 change_to_section(".data",5, get_absolute_expression());
1737 }
1738
1739 void c_symbol_merge(debug, normal)
1740 symbolS *debug;
1741 symbolS *normal;
1742 {
1743 S_SET_DATA_TYPE(normal, S_GET_DATA_TYPE(debug));
1744 S_SET_STORAGE_CLASS(normal, S_GET_STORAGE_CLASS(debug));
1745
1746 if (S_GET_NUMBER_AUXILIARY(debug) > S_GET_NUMBER_AUXILIARY(normal)) {
1747 S_SET_NUMBER_AUXILIARY(normal, S_GET_NUMBER_AUXILIARY(debug));
1748 } /* take the most we have */
1749
1750 if (S_GET_NUMBER_AUXILIARY(debug) > 0) {
1751 memcpy((char*)&normal->sy_symbol.ost_auxent[0], (char*)&debug->sy_symbol.ost_auxent[0], S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
1752 } /* Move all the auxiliary information */
1753
1754 /* Move the debug flags. */
1755 SF_SET_DEBUG_FIELD(normal, SF_GET_DEBUG_FIELD(debug));
1756 } /* c_symbol_merge() */
1757
1758 static int
1759 DEFUN(c_line_new,(symbol, paddr, line_number, frag),
1760 symbolS *symbol AND
1761 long paddr AND
1762 unsigned short line_number AND
1763 fragS* frag)
1764 {
1765 struct lineno_list* new_line =
1766 (struct lineno_list *)xmalloc(sizeof(struct lineno_list));
1767
1768 segment_info_type *s = segment_info + now_seg;
1769 new_line->line.l_lnno = line_number;
1770 if (line_number == 0)
1771 {
1772 new_line->line.l_addr.l_symndx = (long)symbol;
1773 }
1774 else
1775 {
1776 new_line->line.l_addr.l_paddr = paddr;
1777 }
1778
1779 new_line->frag = (char*)frag;
1780 new_line->next = (struct lineno_list*)NULL;
1781
1782
1783 if (s->lineno_list_head == (struct lineno_list *)NULL)
1784 {
1785 s->lineno_list_head = new_line;
1786 }
1787 else
1788 {
1789 s->lineno_list_tail->next = new_line;
1790 }
1791 s->lineno_list_tail = new_line;
1792 return LINESZ * s->scnhdr.s_nlnno ++;
1793 }
1794
1795 void c_dot_file_symbol(filename)
1796 char *filename;
1797 {
1798 symbolS* symbolP;
1799
1800 symbolP = symbol_new(".file",
1801 SEG_DEBUG,
1802 0,
1803 &zero_address_frag);
1804
1805 S_SET_STORAGE_CLASS(symbolP, C_FILE);
1806 S_SET_NUMBER_AUXILIARY(symbolP, 1);
1807 SA_SET_FILE_FNAME(symbolP, filename);
1808 SF_SET_DEBUG(symbolP);
1809 S_SET_VALUE(symbolP, (long) previous_file_symbol);
1810
1811 previous_file_symbol = symbolP;
1812
1813 /* Make sure that the symbol is first on the symbol chain */
1814 if (symbol_rootP != symbolP) {
1815 if (symbolP == symbol_lastP) {
1816 symbol_lastP = symbol_lastP->sy_previous;
1817 } /* if it was the last thing on the list */
1818
1819 symbol_remove(symbolP, &symbol_rootP, &symbol_lastP);
1820 symbol_insert(symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
1821 symbol_rootP = symbolP;
1822 } /* if not first on the list */
1823
1824 } /* c_dot_file_symbol() */
1825
1826 /*
1827 * Build a 'section static' symbol.
1828 */
1829
1830 symbolS *c_section_symbol(name,idx)
1831 char *name;
1832 int idx;
1833 {
1834 symbolS *symbolP;
1835
1836 symbolP = symbol_new(name,idx,
1837 0,
1838 &zero_address_frag);
1839
1840 S_SET_STORAGE_CLASS(symbolP, C_STAT);
1841 S_SET_NUMBER_AUXILIARY(symbolP, 1);
1842
1843 SF_SET_STATICS(symbolP);
1844
1845 return symbolP;
1846 } /* c_section_symbol() */
1847
1848 static void
1849 DEFUN(w_symbols,(abfd, where, symbol_rootP),
1850 bfd *abfd AND
1851 char *where AND
1852 symbolS *symbol_rootP)
1853 {
1854 symbolS *symbolP;
1855 unsigned int i;
1856
1857 /* First fill in those values we have only just worked out */
1858 for (i = SEG_E0; i < SEG_E9; i++)
1859 {
1860 symbolP = segment_info[i].dot;
1861 if (symbolP)
1862 {
1863
1864 SA_SET_SCN_SCNLEN(symbolP, segment_info[i].scnhdr.s_size);
1865 SA_SET_SCN_NRELOC(symbolP, segment_info[i].scnhdr.s_nreloc);
1866 SA_SET_SCN_NLINNO(symbolP, segment_info[i].scnhdr.s_nlnno);
1867
1868 }
1869 }
1870
1871 /*
1872 * Emit all symbols left in the symbol chain.
1873 */
1874 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next(symbolP)) {
1875 /* Used to save the offset of the name. It is used to point
1876 to the string in memory but must be a file offset. */
1877 register char * temp;
1878
1879 tc_coff_symbol_emit_hook(symbolP);
1880
1881 temp = S_GET_NAME(symbolP);
1882 if (SF_GET_STRING(symbolP)) {
1883 S_SET_OFFSET(symbolP, symbolP->sy_name_offset);
1884 S_SET_ZEROES(symbolP, 0);
1885 } else {
1886 bzero(symbolP->sy_symbol.ost_entry.n_name, SYMNMLEN);
1887 strncpy(symbolP->sy_symbol.ost_entry.n_name, temp, SYMNMLEN);
1888 }
1889 where = symbol_to_chars(abfd, where, symbolP);
1890 S_SET_NAME(symbolP,temp);
1891 }
1892
1893 } /* w_symbols() */
1894
1895 static void DEFUN_VOID(obj_coff_lcomm)
1896 {
1897 char *name;
1898 char c;
1899 int temp;
1900 char *p;
1901 symbolS *symbolP;
1902 name = input_line_pointer;
1903
1904
1905
1906 c = get_symbol_end();
1907 p = input_line_pointer;
1908 *p = c;
1909 SKIP_WHITESPACE();
1910 if (*input_line_pointer != ',') {
1911 as_bad("Expected comma after name");
1912 ignore_rest_of_line();
1913 return;
1914 }
1915 if (*input_line_pointer == '\n') {
1916 as_bad("Missing size expression");
1917 return;
1918 }
1919 input_line_pointer++;
1920 if ((temp = get_absolute_expression ()) < 0) {
1921 as_warn("lcomm length (%d.) <0! Ignored.", temp);
1922 ignore_rest_of_line();
1923 return;
1924 }
1925 *p = 0;
1926 symbolP = symbol_find_or_make(name);
1927 S_SET_VALUE(symbolP, segment_info[SEG_E2].scnhdr.s_size);
1928 S_SET_SEGMENT(symbolP, SEG_E2);
1929 segment_info[SEG_E2].scnhdr.s_size += temp;
1930 S_SET_STORAGE_CLASS(symbolP, C_STAT);
1931 demand_empty_rest_of_line();
1932 }
1933
1934
1935 #if 1
1936 static void DEFUN(fixup_segment,(fixP, this_segment_type),
1937 register fixS * fixP AND
1938 segT this_segment_type)
1939 {
1940 register symbolS *add_symbolP;
1941 register symbolS *sub_symbolP;
1942 register long add_number;
1943 register int size;
1944 register char *place;
1945 register long where;
1946 register char pcrel;
1947 register fragS *fragP;
1948 register segT add_symbol_segment = SEG_ABSOLUTE;
1949
1950
1951 for ( ; fixP; fixP = fixP->fx_next)
1952 {
1953 fragP = fixP->fx_frag;
1954 know(fragP);
1955 where = fixP->fx_where;
1956 place = fragP->fr_literal + where;
1957 size = fixP->fx_size;
1958 add_symbolP = fixP->fx_addsy;
1959 #ifdef TC_I960
1960 if (fixP->fx_callj && TC_S_IS_CALLNAME(add_symbolP)) {
1961 /* Relocation should be done via the
1962 associated 'bal' entry point
1963 symbol. */
1964
1965 if (!TC_S_IS_BALNAME(tc_get_bal_of_call(add_symbolP))) {
1966 as_bad("No 'bal' entry point for leafproc %s",
1967 S_GET_NAME(add_symbolP));
1968 continue;
1969 }
1970 fixP->fx_addsy = add_symbolP = tc_get_bal_of_call(add_symbolP);
1971 } /* callj relocation */
1972 #endif
1973 sub_symbolP = fixP->fx_subsy;
1974 add_number = fixP->fx_offset;
1975 pcrel = fixP->fx_pcrel;
1976
1977 if (add_symbolP) {
1978 add_symbol_segment = S_GET_SEGMENT(add_symbolP);
1979 } /* if there is an addend */
1980
1981 if (sub_symbolP) {
1982 if (!add_symbolP) {
1983 /* Its just -sym */
1984 if (S_GET_SEGMENT(sub_symbolP) != SEG_ABSOLUTE) {
1985 as_bad("Negative of non-absolute symbol %s", S_GET_NAME(sub_symbolP));
1986 } /* not absolute */
1987
1988 add_number -= S_GET_VALUE(sub_symbolP);
1989
1990 /* if sub_symbol is in the same segment that add_symbol
1991 and add_symbol is either in DATA, TEXT, BSS or ABSOLUTE */
1992 } else if ((S_GET_SEGMENT(sub_symbolP) == add_symbol_segment)
1993 && (SEG_NORMAL(add_symbol_segment)
1994 || (add_symbol_segment == SEG_ABSOLUTE))) {
1995 /* Difference of 2 symbols from same segment. */
1996 /* Can't make difference of 2 undefineds: 'value' means */
1997 /* something different for N_UNDF. */
1998 #ifdef TC_I960
1999 /* Makes no sense to use the difference of 2 arbitrary symbols
2000 * as the target of a call instruction.
2001 */
2002 if (fixP->fx_callj) {
2003 as_bad("callj to difference of 2 symbols");
2004 }
2005 #endif /* TC_I960 */
2006 add_number += S_GET_VALUE(add_symbolP) -
2007 S_GET_VALUE(sub_symbolP);
2008
2009 add_symbolP = NULL;
2010 fixP->fx_addsy = NULL;
2011 } else {
2012 /* Different segments in subtraction. */
2013 know(!(S_IS_EXTERNAL(sub_symbolP) && (S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)));
2014
2015 if ((S_GET_SEGMENT(sub_symbolP) == SEG_ABSOLUTE)) {
2016 add_number -= S_GET_VALUE(sub_symbolP);
2017 } else {
2018 as_bad("Can't emit reloc {- %s-seg symbol \"%s\"} @ file address %d.",
2019 segment_name(S_GET_SEGMENT(sub_symbolP)),
2020 S_GET_NAME(sub_symbolP), fragP->fr_address + where);
2021 } /* if absolute */
2022 }
2023 } /* if sub_symbolP */
2024
2025 if (add_symbolP) {
2026 if (add_symbol_segment == this_segment_type && pcrel) {
2027 /*
2028 * This fixup was made when the symbol's segment was
2029 * SEG_UNKNOWN, but it is now in the local segment.
2030 * So we know how to do the address without relocation.
2031 */
2032 #ifdef TC_I960
2033 /* reloc_callj() may replace a 'call' with a 'calls' or a 'bal',
2034 * in which cases it modifies *fixP as appropriate. In the case
2035 * of a 'calls', no further work is required, and *fixP has been
2036 * set up to make the rest of the code below a no-op.
2037 */
2038 reloc_callj(fixP);
2039 #endif /* TC_I960 */
2040
2041 add_number += S_GET_VALUE(add_symbolP);
2042 add_number -= md_pcrel_from (fixP);
2043 pcrel = 0; /* Lie. Don't want further pcrel processing. */
2044 fixP->fx_addsy = NULL; /* No relocations please. */
2045 } else
2046 {
2047 switch (add_symbol_segment)
2048 {
2049 case SEG_ABSOLUTE:
2050 #ifdef TC_I960
2051 reloc_callj(fixP); /* See comment about reloc_callj() above*/
2052 #endif /* TC_I960 */
2053 add_number += S_GET_VALUE(add_symbolP);
2054 fixP->fx_addsy = NULL;
2055 add_symbolP = NULL;
2056 break;
2057 default:
2058
2059 add_number += S_GET_VALUE(add_symbolP) +
2060 segment_info[S_GET_SEGMENT(add_symbolP)].scnhdr.s_paddr ;
2061 break;
2062
2063 case SEG_UNKNOWN:
2064 #ifdef TC_I960
2065 if ((int)fixP->fx_bit_fixP == 13) {
2066 /* This is a COBR instruction. They have only a
2067 * 13-bit displacement and are only to be used
2068 * for local branches: flag as error, don't generate
2069 * relocation.
2070 */
2071 as_bad("can't use COBR format with external label");
2072 fixP->fx_addsy = NULL; /* No relocations please. */
2073 continue;
2074 } /* COBR */
2075 #endif /* TC_I960 */
2076
2077
2078
2079 break;
2080
2081
2082 } /* switch on symbol seg */
2083 } /* if not in local seg */
2084 } /* if there was a + symbol */
2085
2086 if (pcrel) {
2087 add_number -= md_pcrel_from(fixP);
2088 if (add_symbolP == 0) {
2089 fixP->fx_addsy = & abs_symbol;
2090 } /* if there's an add_symbol */
2091 } /* if pcrel */
2092
2093 if (!fixP->fx_bit_fixP) {
2094 if ((size==1 &&
2095 (add_number& ~0xFF) && (add_number&~0xFF!=(-1&~0xFF))) ||
2096 (size==2 &&
2097 (add_number& ~0xFFFF) && (add_number&~0xFFFF!=(-1&~0xFFFF)))) {
2098 as_bad("Value of %d too large for field of %d bytes at 0x%x",
2099 add_number, size, fragP->fr_address + where);
2100 } /* generic error checking */
2101 } /* not a bit fix */
2102 /* once this fix has been applied, we don't have to output anything
2103 nothing more need be done -*/
2104 md_apply_fix(fixP, add_number);
2105
2106 } /* For each fixS in this segment. */
2107
2108
2109 } /* fixup_segment() */
2110 #endif
2111
2112
2113
2114
This page took 0.075367 seconds and 4 git commands to generate.