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