* config/obj-coff.h, config/obj-coff.c: Deleted all code used only when
[binutils-gdb.git] / gas / config / obj-coff.c
1 /* coff object file format
2 Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994
3 Free Software Foundation, Inc.
4
5 This file is part of GAS.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include "as.h"
22 #include "subsegs.h"
23 #include "obstack.h"
24
25 const char *s_get_name PARAMS ((symbolS * s));
26 static symbolS *tag_find_or_make PARAMS ((char *name));
27 static symbolS *tag_find PARAMS ((char *name));
28
29 static void obj_coff_def PARAMS ((int what));
30 static void obj_coff_dim PARAMS ((int));
31 static void obj_coff_endef PARAMS ((int));
32 static void obj_coff_line PARAMS ((int));
33 static void obj_coff_ln PARAMS ((int));
34 static void obj_coff_scl PARAMS ((int));
35 static void obj_coff_size PARAMS ((int));
36 static void obj_coff_tag PARAMS ((int));
37 static void obj_coff_type PARAMS ((int));
38 static void obj_coff_val PARAMS ((int));
39 static void tag_init PARAMS ((void));
40 static void tag_insert PARAMS ((const char *name, symbolS * symbolP));
41
42 static void SA_SET_SYM_TAGNDX PARAMS ((symbolS *, symbolS *));
43
44 static struct hash_control *tag_hash;
45 static symbolS *def_symbol_in_progress;
46
47 const pseudo_typeS obj_pseudo_table[] =
48 {
49 #ifndef IGNORE_DEBUG
50 {"def", obj_coff_def, 0},
51 {"dim", obj_coff_dim, 0},
52 {"endef", obj_coff_endef, 0},
53 {"line", obj_coff_line, 0},
54 {"ln", obj_coff_ln, 0},
55 {"appline", obj_coff_ln, 1},
56 {"scl", obj_coff_scl, 0},
57 {"size", obj_coff_size, 0},
58 {"tag", obj_coff_tag, 0},
59 {"type", obj_coff_type, 0},
60 {"val", obj_coff_val, 0},
61 #else
62 {"def", s_ignore, 0},
63 {"dim", s_ignore, 0},
64 {"endef", s_ignore, 0},
65 {"line", s_ignore, 0},
66 {"ln", s_ignore, 0},
67 {"scl", s_ignore, 0},
68 {"size", s_ignore, 0},
69 {"tag", s_ignore, 0},
70 {"type", s_ignore, 0},
71 {"val", s_ignore, 0},
72 #endif /* ignore debug */
73
74 { "section", obj_coff_section, 0 },
75
76 {"ident", s_ignore, 0}, /* we don't yet handle this. */
77 {"optim", s_ignore, 0}, /* For sun386i cc (?) */
78 /* other stuff */
79 {"ABORT", s_abort, 0},
80
81 {NULL} /* end sentinel */
82 }; /* obj_pseudo_table */
83
84 struct line_no {
85 struct line_no *next;
86 fragS *frag;
87 alent l;
88 };
89
90 #define GET_FILENAME_STRING(X) \
91 ((char*)(&((X)->sy_symbol.ost_auxent->x_file.x_n.x_offset))[1])
92
93 /* @@ Ick. */
94 static segT
95 fetch_coff_debug_section ()
96 {
97 static segT debug_section;
98 if (!debug_section)
99 {
100 CONST asymbol *s;
101 s = bfd_make_debug_symbol (stdoutput, (char *) 0, 0);
102 assert (s != 0);
103 debug_section = s->section;
104 }
105 return debug_section;
106 }
107
108 void
109 SA_SET_SYM_ENDNDX (sym, val)
110 symbolS *sym;
111 symbolS *val;
112 {
113 combined_entry_type *entry, *p;
114
115 entry = &coffsymbol (sym->bsym)->native[1];
116 p = coffsymbol (val->bsym)->native;
117 entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p;
118 entry->fix_end = 1;
119 }
120
121 static void
122 SA_SET_SYM_TAGNDX (sym, val)
123 symbolS *sym;
124 symbolS *val;
125 {
126 combined_entry_type *entry, *p;
127
128 entry = &coffsymbol (sym->bsym)->native[1];
129 p = coffsymbol (val->bsym)->native;
130 entry->u.auxent.x_sym.x_tagndx.p = p;
131 entry->fix_tag = 1;
132 }
133
134 static int
135 S_GET_DATA_TYPE (sym)
136 symbolS *sym;
137 {
138 return coffsymbol (sym->bsym)->native->u.syment.n_type;
139 }
140
141 int
142 S_SET_DATA_TYPE (sym, val)
143 symbolS *sym;
144 int val;
145 {
146 coffsymbol (sym->bsym)->native->u.syment.n_type = val;
147 return val;
148 }
149
150 int
151 S_GET_STORAGE_CLASS (sym)
152 symbolS *sym;
153 {
154 return coffsymbol (sym->bsym)->native->u.syment.n_sclass;
155 }
156
157 int
158 S_SET_STORAGE_CLASS (sym, val)
159 symbolS *sym;
160 int val;
161 {
162 coffsymbol (sym->bsym)->native->u.syment.n_sclass = val;
163 return val;
164 }
165
166 /* Merge a debug symbol containing debug information into a normal symbol. */
167
168 void
169 c_symbol_merge (debug, normal)
170 symbolS *debug;
171 symbolS *normal;
172 {
173 S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
174 S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
175
176 if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
177 /* take the most we have */
178 S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
179
180 if (S_GET_NUMBER_AUXILIARY (debug) > 0)
181 {
182 /* Move all the auxiliary information. */
183 /* @@ How many fields do we want to preserve? Would it make more
184 sense to pick and choose those we want to copy? Should look
185 into this further.... [raeburn:19920512.2209EST] */
186 alent *linenos;
187 linenos = coffsymbol (normal->bsym)->lineno;
188 memcpy ((char *) &coffsymbol (normal->bsym)->native,
189 (char *) &coffsymbol (debug->bsym)->native,
190 S_GET_NUMBER_AUXILIARY(debug) * AUXESZ);
191 coffsymbol (normal->bsym)->lineno = linenos;
192 }
193
194 /* Move the debug flags. */
195 SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
196 }
197
198 static symbolS *previous_file_symbol;
199 void
200 c_dot_file_symbol (filename)
201 char *filename;
202 {
203 symbolS *symbolP;
204
205 symbolP = symbol_new (filename, &bfd_abs_section, 0,
206 &zero_address_frag);
207
208 S_SET_STORAGE_CLASS (symbolP, C_FILE);
209 S_SET_NUMBER_AUXILIARY (symbolP, 1);
210
211 symbolP->bsym->flags = BSF_DEBUGGING;
212
213 #ifndef NO_LISTING
214 {
215 extern int listing;
216 if (listing)
217 {
218 listing_source_file (filename);
219 }
220 }
221 #endif
222
223 S_SET_VALUE (symbolP, (long) previous_file_symbol);
224
225 previous_file_symbol = symbolP;
226
227 /* Make sure that the symbol is first on the symbol chain */
228 if (symbol_rootP != symbolP)
229 {
230 if (symbolP == symbol_lastP)
231 {
232 symbol_lastP = symbol_lastP->sy_previous;
233 } /* if it was the last thing on the list */
234
235 symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
236 symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
237 symbol_rootP = symbolP;
238 } /* if not first on the list */
239 }
240
241 /*
242 * Build a 'section static' symbol.
243 */
244
245 char *
246 c_section_symbol (name, value, length, nreloc, nlnno)
247 char *name;
248 long value;
249 long length;
250 unsigned short nreloc;
251 unsigned short nlnno;
252 {
253 symbolS *symbolP;
254
255 symbolP = symbol_new (name,
256 (name[1] == 't'
257 ? text_section
258 : name[1] == 'd'
259 ? data_section
260 : bss_section),
261 value,
262 &zero_address_frag);
263
264 S_SET_STORAGE_CLASS (symbolP, C_STAT);
265 S_SET_NUMBER_AUXILIARY (symbolP, 1);
266
267 SA_SET_SCN_SCNLEN (symbolP, length);
268 SA_SET_SCN_NRELOC (symbolP, nreloc);
269 SA_SET_SCN_NLINNO (symbolP, nlnno);
270
271 SF_SET_STATICS (symbolP);
272
273 return (char *) symbolP;
274 }
275
276 /* Line number handling */
277
278 int coff_line_base;
279
280 /* Symbol of last function, which we should hang line#s off of. */
281 static symbolS *line_fsym;
282
283 #define in_function() (line_fsym != 0)
284 #define clear_function() (line_fsym = 0)
285 #define set_function(F) (line_fsym = (F), coff_add_linesym (F))
286
287 \f
288 void
289 obj_symbol_new_hook (symbolP)
290 symbolS *symbolP;
291 {
292 char underscore = 0; /* Symbol has leading _ */
293
294 {
295 long sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
296 char *s = (char *) bfd_alloc_by_size_t (stdoutput, sz);
297 memset (s, 0, sz);
298 coffsymbol (symbolP->bsym)->native = (combined_entry_type *) s;
299 }
300 S_SET_DATA_TYPE (symbolP, T_NULL);
301 S_SET_STORAGE_CLASS (symbolP, 0);
302 S_SET_NUMBER_AUXILIARY (symbolP, 0);
303
304 #ifdef STRIP_UNDERSCORE
305 /* Remove leading underscore at the beginning of the symbol.
306 This is to be compatible with the standard librairies. */
307 if (*S_GET_NAME (symbolP) == '_')
308 {
309 underscore = 1;
310 S_SET_NAME (symbolP, S_GET_NAME (symbolP) + 1);
311 }
312 #endif /* STRIP_UNDERSCORE */
313
314 if (S_IS_STRING (symbolP))
315 SF_SET_STRING (symbolP);
316 if (!underscore && S_IS_LOCAL (symbolP))
317 SF_SET_LOCAL (symbolP);
318 }
319
320 \f
321 /* stack stuff */
322 stack *
323 stack_init (chunk_size, element_size)
324 unsigned long chunk_size;
325 unsigned long element_size;
326 {
327 stack *st;
328
329 st = (stack *) malloc (sizeof (stack));
330 if (!st)
331 return 0;
332 st->data = malloc (chunk_size);
333 if (!st->data)
334 {
335 free (st);
336 return 0;
337 }
338 st->pointer = 0;
339 st->size = chunk_size;
340 st->chunk_size = chunk_size;
341 st->element_size = element_size;
342 return st;
343 }
344
345 void
346 stack_delete (st)
347 stack *st;
348 {
349 free (st->data);
350 free (st);
351 }
352
353 char *
354 stack_push (st, element)
355 stack *st;
356 char *element;
357 {
358 if (st->pointer + st->element_size >= st->size)
359 {
360 st->size += st->chunk_size;
361 if ((st->data = xrealloc (st->data, st->size)) == (char *) 0)
362 return (char *) 0;
363 }
364 memcpy (st->data + st->pointer, element, st->element_size);
365 st->pointer += st->element_size;
366 return st->data + st->pointer;
367 }
368
369 char *
370 stack_pop (st)
371 stack *st;
372 {
373 if (st->pointer < st->element_size)
374 {
375 st->pointer = 0;
376 return (char *) 0;
377 }
378 st->pointer -= st->element_size;
379 return st->data + st->pointer;
380 }
381
382 char *
383 stack_top (st)
384 stack *st;
385 {
386 return st->data + st->pointer - st->element_size;
387 }
388
389
390 /*
391 * Handle .ln directives.
392 */
393
394 static symbolS *current_lineno_sym;
395 static struct line_no *line_nos;
396
397 static void
398 add_lineno (frag, offset, num)
399 fragS *frag;
400 int offset;
401 int num;
402 {
403 struct line_no *new_line = (struct line_no *) bfd_alloc_by_size_t (stdoutput,
404 sizeof (struct line_no));
405 if (!current_lineno_sym)
406 {
407 abort ();
408 }
409 new_line->next = line_nos;
410 new_line->frag = frag;
411 new_line->l.line_number = num;
412 new_line->l.u.offset = offset;
413 line_nos = new_line;
414 }
415
416 void
417 coff_add_linesym (sym)
418 symbolS *sym;
419 {
420 if (line_nos)
421 {
422 add_lineno (0, 0, 0);
423 coffsymbol (current_lineno_sym->bsym)->lineno = (alent *) line_nos;
424 line_nos = 0;
425 }
426 current_lineno_sym = sym;
427 }
428
429 static void
430 obj_coff_ln (appline)
431 int appline;
432 {
433 int l;
434
435 if (! appline && def_symbol_in_progress != NULL)
436 {
437 as_warn (".ln pseudo-op inside .def/.endef: ignored.");
438 demand_empty_rest_of_line ();
439 return;
440 }
441
442 l = get_absolute_expression ();
443 if (!appline)
444 {
445 add_lineno (frag_now, frag_now_fix (), l);
446 }
447
448 #ifndef NO_LISTING
449 {
450 extern int listing;
451
452 if (listing)
453 {
454 if (! appline)
455 l += coff_line_base - 1;
456 listing_source_line (l);
457 }
458 }
459 #endif
460
461 demand_empty_rest_of_line ();
462 }
463
464 /*
465 * def()
466 *
467 * Handle .def directives.
468 *
469 * One might ask : why can't we symbol_new if the symbol does not
470 * already exist and fill it with debug information. Because of
471 * the C_EFCN special symbol. It would clobber the value of the
472 * function symbol before we have a chance to notice that it is
473 * a C_EFCN. And a second reason is that the code is more clear this
474 * way. (at least I think it is :-).
475 *
476 */
477
478 #define SKIP_SEMI_COLON() while (*input_line_pointer++ != ';')
479 #define SKIP_WHITESPACES() while (*input_line_pointer == ' ' || \
480 *input_line_pointer == '\t') \
481 input_line_pointer++;
482
483 static void
484 obj_coff_def (what)
485 int what;
486 {
487 char name_end; /* Char after the end of name */
488 char *symbol_name; /* Name of the debug symbol */
489 char *symbol_name_copy; /* Temporary copy of the name */
490 unsigned int symbol_name_length;
491
492 if (def_symbol_in_progress != NULL)
493 {
494 as_warn (".def pseudo-op used inside of .def/.endef: ignored.");
495 demand_empty_rest_of_line ();
496 return;
497 } /* if not inside .def/.endef */
498
499 SKIP_WHITESPACES ();
500
501 symbol_name = input_line_pointer;
502 #ifdef STRIP_UNDERSCORE
503 if (symbol_name[0] == '_' && symbol_name[1] != 0)
504 symbol_name++;
505 #endif /* STRIP_UNDERSCORE */
506
507 name_end = get_symbol_end ();
508 symbol_name_length = strlen (symbol_name);
509 symbol_name_copy = xmalloc (symbol_name_length + 1);
510 strcpy (symbol_name_copy, symbol_name);
511
512 /* Initialize the new symbol */
513 def_symbol_in_progress = symbol_make (symbol_name_copy);
514 def_symbol_in_progress->sy_frag = &zero_address_frag;
515 S_SET_VALUE (def_symbol_in_progress, 0);
516
517 if (S_IS_STRING (def_symbol_in_progress))
518 SF_SET_STRING (def_symbol_in_progress);
519
520 *input_line_pointer = name_end;
521
522 demand_empty_rest_of_line ();
523 }
524
525 unsigned int dim_index;
526
527 static void
528 obj_coff_endef (ignored)
529 int ignored;
530 {
531 symbolS *symbolP;
532 /* DIM BUG FIX sac@cygnus.com */
533 dim_index = 0;
534 if (def_symbol_in_progress == NULL)
535 {
536 as_warn (".endef pseudo-op used outside of .def/.endef: ignored.");
537 demand_empty_rest_of_line ();
538 return;
539 } /* if not inside .def/.endef */
540
541 /* Set the section number according to storage class. */
542 switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
543 {
544 case C_STRTAG:
545 case C_ENTAG:
546 case C_UNTAG:
547 SF_SET_TAG (def_symbol_in_progress);
548 /* intentional fallthrough */
549 case C_FILE:
550 case C_TPDEF:
551 SF_SET_DEBUG (def_symbol_in_progress);
552 S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
553 break;
554
555 case C_EFCN:
556 SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */
557 /* intentional fallthrough */
558 case C_BLOCK:
559 SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing */
560 /* intentional fallthrough */
561 case C_FCN:
562 {
563 CONST char *name;
564 S_SET_SEGMENT (def_symbol_in_progress, text_section);
565
566 name = bfd_asymbol_name (def_symbol_in_progress->bsym);
567 if (name[1] == 'b' && name[2] == 'f')
568 {
569 if (! in_function ())
570 as_warn ("`%s' symbol without preceding function", name);
571 /* SA_SET_SYM_LNNO (def_symbol_in_progress, 12345);*/
572 /* Will need relocating */
573 SF_SET_PROCESS (def_symbol_in_progress);
574 clear_function ();
575 }
576 }
577 break;
578
579 #ifdef C_AUTOARG
580 case C_AUTOARG:
581 #endif /* C_AUTOARG */
582 case C_AUTO:
583 case C_REG:
584 case C_MOS:
585 case C_MOE:
586 case C_MOU:
587 case C_ARG:
588 case C_REGPARM:
589 case C_FIELD:
590 case C_EOS:
591 SF_SET_DEBUG (def_symbol_in_progress);
592 S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
593 break;
594
595 case C_EXT:
596 case C_STAT:
597 case C_LABEL:
598 /* Valid but set somewhere else (s_comm, s_lcomm, colon) */
599 break;
600
601 case C_USTATIC:
602 case C_EXTDEF:
603 case C_ULABEL:
604 as_warn ("unexpected storage class %d",
605 S_GET_STORAGE_CLASS (def_symbol_in_progress));
606 break;
607 } /* switch on storage class */
608
609 /* Now that we have built a debug symbol, try to find if we should
610 merge with an existing symbol or not. If a symbol is C_EFCN or
611 SEG_ABSOLUTE or untagged SEG_DEBUG it never merges. */
612
613 /* Two cases for functions. Either debug followed by definition or
614 definition followed by debug. For definition first, we will
615 merge the debug symbol into the definition. For debug first, the
616 lineno entry MUST point to the definition function or else it
617 will point off into space when obj_crawl_symbol_chain() merges
618 the debug symbol into the real symbol. Therefor, let's presume
619 the debug symbol is a real function reference. */
620
621 /* FIXME-SOON If for some reason the definition label/symbol is
622 never seen, this will probably leave an undefined symbol at link
623 time. */
624
625 if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
626 || (!strcmp (bfd_get_section_name (stdoutput,
627 S_GET_SEGMENT (def_symbol_in_progress)),
628 "*DEBUG*")
629 && !SF_GET_TAG (def_symbol_in_progress))
630 || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
631 || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL)
632 {
633 if (def_symbol_in_progress != symbol_lastP)
634 symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
635 &symbol_lastP);
636 }
637 else
638 {
639 /* This symbol already exists, merge the newly created symbol
640 into the old one. This is not mandatory. The linker can
641 handle duplicate symbols correctly. But I guess that it save
642 a *lot* of space if the assembly file defines a lot of
643 symbols. [loic] */
644
645 /* The debug entry (def_symbol_in_progress) is merged into the
646 previous definition. */
647
648 c_symbol_merge (def_symbol_in_progress, symbolP);
649 /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
650 def_symbol_in_progress = symbolP;
651
652 if (SF_GET_FUNCTION (def_symbol_in_progress)
653 || SF_GET_TAG (def_symbol_in_progress))
654 {
655 /* For functions, and tags, the symbol *must* be where the
656 debug symbol appears. Move the existing symbol to the
657 current place. */
658 /* If it already is at the end of the symbol list, do nothing */
659 if (def_symbol_in_progress != symbol_lastP)
660 {
661 symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
662 symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
663 }
664 }
665 }
666
667 if (SF_GET_TAG (def_symbol_in_progress)
668 && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL)
669 {
670 tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress);
671 }
672
673 if (SF_GET_FUNCTION (def_symbol_in_progress))
674 {
675 know (sizeof (def_symbol_in_progress) <= sizeof (long));
676 set_function (def_symbol_in_progress);
677 SF_SET_PROCESS (def_symbol_in_progress);
678
679 if (symbolP == NULL)
680 {
681 /* That is, if this is the first time we've seen the
682 function... */
683 symbol_table_insert (def_symbol_in_progress);
684 } /* definition follows debug */
685 } /* Create the line number entry pointing to the function being defined */
686
687 def_symbol_in_progress = NULL;
688 demand_empty_rest_of_line ();
689 }
690
691 static void
692 obj_coff_dim (ignored)
693 int ignored;
694 {
695 int dim_index;
696
697 if (def_symbol_in_progress == NULL)
698 {
699 as_warn (".dim pseudo-op used outside of .def/.endef: ignored.");
700 demand_empty_rest_of_line ();
701 return;
702 } /* if not inside .def/.endef */
703
704 S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
705
706 for (dim_index = 0; dim_index < DIMNUM; dim_index++)
707 {
708 SKIP_WHITESPACES ();
709 SA_SET_SYM_DIMEN (def_symbol_in_progress, dim_index,
710 get_absolute_expression ());
711
712 switch (*input_line_pointer)
713 {
714 case ',':
715 input_line_pointer++;
716 break;
717
718 default:
719 as_warn ("badly formed .dim directive ignored");
720 /* intentional fallthrough */
721 case '\n':
722 case ';':
723 dim_index = DIMNUM;
724 break;
725 }
726 }
727
728 demand_empty_rest_of_line ();
729 }
730
731 static void
732 obj_coff_line (ignored)
733 int ignored;
734 {
735 int this_base;
736
737 if (def_symbol_in_progress == NULL)
738 {
739 /* Probably stabs-style line? */
740 obj_coff_ln (0);
741 return;
742 }
743
744 this_base = get_absolute_expression ();
745 if (this_base > coff_line_base)
746 coff_line_base = this_base;
747
748 S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
749 SA_SET_SYM_LNNO (def_symbol_in_progress, coff_line_base);
750
751 demand_empty_rest_of_line ();
752 }
753
754 static void
755 obj_coff_size (ignored)
756 int ignored;
757 {
758 if (def_symbol_in_progress == NULL)
759 {
760 as_warn (".size pseudo-op used outside of .def/.endef ignored.");
761 demand_empty_rest_of_line ();
762 return;
763 } /* if not inside .def/.endef */
764
765 S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
766 SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
767 demand_empty_rest_of_line ();
768 }
769
770 static void
771 obj_coff_scl (ignored)
772 int ignored;
773 {
774 if (def_symbol_in_progress == NULL)
775 {
776 as_warn (".scl pseudo-op used outside of .def/.endef ignored.");
777 demand_empty_rest_of_line ();
778 return;
779 } /* if not inside .def/.endef */
780
781 S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
782 demand_empty_rest_of_line ();
783 }
784
785 static void
786 obj_coff_tag (ignored)
787 int ignored;
788 {
789 char *symbol_name;
790 char name_end;
791
792 if (def_symbol_in_progress == NULL)
793 {
794 as_warn (".tag pseudo-op used outside of .def/.endef ignored.");
795 demand_empty_rest_of_line ();
796 return;
797 }
798
799 S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
800 symbol_name = input_line_pointer;
801 name_end = get_symbol_end ();
802
803 /* Assume that the symbol referred to by .tag is always defined.
804 This was a bad assumption. I've added find_or_make. xoxorich. */
805 SA_SET_SYM_TAGNDX (def_symbol_in_progress,
806 tag_find_or_make (symbol_name));
807 if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
808 {
809 as_warn ("tag not found for .tag %s", symbol_name);
810 } /* not defined */
811
812 SF_SET_TAGGED (def_symbol_in_progress);
813 *input_line_pointer = name_end;
814
815 demand_empty_rest_of_line ();
816 }
817
818 static void
819 obj_coff_type (ignored)
820 int ignored;
821 {
822 if (def_symbol_in_progress == NULL)
823 {
824 as_warn (".type pseudo-op used outside of .def/.endef ignored.");
825 demand_empty_rest_of_line ();
826 return;
827 } /* if not inside .def/.endef */
828
829 S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
830
831 if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
832 S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
833 {
834 SF_SET_FUNCTION (def_symbol_in_progress);
835 } /* is a function */
836
837 demand_empty_rest_of_line ();
838 }
839
840 static void
841 obj_coff_val (ignored)
842 int ignored;
843 {
844 if (def_symbol_in_progress == NULL)
845 {
846 as_warn (".val pseudo-op used outside of .def/.endef ignored.");
847 demand_empty_rest_of_line ();
848 return;
849 } /* if not inside .def/.endef */
850
851 if (is_name_beginner (*input_line_pointer))
852 {
853 char *symbol_name = input_line_pointer;
854 char name_end = get_symbol_end ();
855
856 if (!strcmp (symbol_name, "."))
857 {
858 def_symbol_in_progress->sy_frag = frag_now;
859 S_SET_VALUE (def_symbol_in_progress, obstack_next_free (&frags) - frag_now->fr_literal);
860 /* If the .val is != from the .def (e.g. statics) */
861 }
862 else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
863 {
864 def_symbol_in_progress->sy_value.X_op = O_symbol;
865 def_symbol_in_progress->sy_value.X_add_symbol =
866 symbol_find_or_make (symbol_name);
867 def_symbol_in_progress->sy_value.X_op_symbol = NULL;
868 def_symbol_in_progress->sy_value.X_add_number = 0;
869
870 /* If the segment is undefined when the forward reference is
871 resolved, then copy the segment id from the forward
872 symbol. */
873 SF_SET_GET_SEGMENT (def_symbol_in_progress);
874 }
875 /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */
876 *input_line_pointer = name_end;
877 }
878 else
879 {
880 S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
881 } /* if symbol based */
882
883 demand_empty_rest_of_line ();
884 }
885
886 /*
887 * Maintain a list of the tagnames of the structres.
888 */
889
890 static void
891 tag_init ()
892 {
893 tag_hash = hash_new ();
894 }
895
896 static void
897 tag_insert (name, symbolP)
898 const char *name;
899 symbolS *symbolP;
900 {
901 const char *error_string;
902
903 if ((error_string = hash_jam (tag_hash, name, (char *) symbolP)))
904 {
905 as_fatal ("Inserting \"%s\" into structure table failed: %s",
906 name, error_string);
907 }
908 }
909
910 static symbolS *
911 tag_find_or_make (name)
912 char *name;
913 {
914 symbolS *symbolP;
915
916 if ((symbolP = tag_find (name)) == NULL)
917 {
918 symbolP = symbol_new (name, undefined_section,
919 0, &zero_address_frag);
920
921 tag_insert (S_GET_NAME (symbolP), symbolP);
922 symbol_table_insert (symbolP);
923 } /* not found */
924
925 return symbolP;
926 }
927
928 static symbolS *
929 tag_find (name)
930 char *name;
931 {
932 #ifdef STRIP_UNDERSCORE
933 if (*name == '_')
934 name++;
935 #endif /* STRIP_UNDERSCORE */
936 return (symbolS *) hash_find (tag_hash, name);
937 }
938
939 void
940 obj_read_begin_hook ()
941 {
942 /* These had better be the same. Usually 18 bytes. */
943 #ifndef BFD_HEADERS
944 know (sizeof (SYMENT) == sizeof (AUXENT));
945 know (SYMESZ == AUXESZ);
946 #endif
947 tag_init ();
948 }
949
950
951 symbolS *coff_last_function;
952
953 void
954 coff_frob_symbol (symp, punt)
955 symbolS *symp;
956 int *punt;
957 {
958 static symbolS *last_tagP;
959 static stack *block_stack;
960 static symbolS *set_end;
961
962 if (symp == &abs_symbol)
963 {
964 *punt = 1;
965 return;
966 }
967
968 if (current_lineno_sym)
969 coff_add_linesym ((symbolS *) 0);
970
971 if (!block_stack)
972 block_stack = stack_init (512, sizeof (symbolS*));
973
974 if (!S_IS_DEFINED (symp) && S_GET_STORAGE_CLASS (symp) != C_STAT)
975 S_SET_STORAGE_CLASS (symp, C_EXT);
976
977 if (!SF_GET_DEBUG (symp))
978 {
979 symbolS *real;
980 if (!SF_GET_LOCAL (symp)
981 && (real = symbol_find_base (S_GET_NAME (symp), DO_NOT_STRIP))
982 && real != symp)
983 {
984 c_symbol_merge (symp, real);
985 *punt = 1;
986 }
987 if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
988 {
989 assert (S_GET_VALUE (symp) == 0);
990 S_SET_EXTERNAL (symp);
991 }
992 else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
993 {
994 if (S_GET_SEGMENT (symp) == text_section)
995 S_SET_STORAGE_CLASS (symp, C_LABEL);
996 else
997 S_SET_STORAGE_CLASS (symp, C_STAT);
998 }
999 if (SF_GET_PROCESS (symp))
1000 {
1001 if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
1002 {
1003 if (!strcmp (S_GET_NAME (symp), ".bb"))
1004 stack_push (block_stack, (char *) &symp);
1005 else
1006 {
1007 symbolS *begin;
1008 begin = *(symbolS **) stack_pop (block_stack);
1009 if (begin == 0)
1010 as_warn ("mismatched .eb");
1011 else
1012 set_end = begin;
1013 }
1014 }
1015 if (coff_last_function == 0 && SF_GET_FUNCTION (symp))
1016 {
1017 union internal_auxent *auxp;
1018 coff_last_function = symp;
1019 if (S_GET_NUMBER_AUXILIARY (symp) < 1)
1020 S_SET_NUMBER_AUXILIARY (symp, 1);
1021 auxp = &coffsymbol (symp->bsym)->native[1].u.auxent;
1022 memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
1023 sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
1024 }
1025 if (S_GET_STORAGE_CLASS (symp) == C_EFCN)
1026 {
1027 if (coff_last_function == 0)
1028 as_fatal ("C_EFCN symbol out of scope");
1029 SA_SET_SYM_FSIZE (coff_last_function,
1030 (long) (S_GET_VALUE (symp)
1031 - S_GET_VALUE (coff_last_function)));
1032 set_end = coff_last_function;
1033 coff_last_function = 0;
1034 }
1035 }
1036 else if (SF_GET_TAG (symp))
1037 last_tagP = symp;
1038 else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
1039 set_end = last_tagP;
1040 else if (S_GET_STORAGE_CLASS (symp) == C_FILE)
1041 {
1042 if (S_GET_VALUE (symp))
1043 {
1044 S_SET_VALUE ((symbolS *) S_GET_VALUE (symp), 0xdeadbeef);
1045 S_SET_VALUE (symp, 0);
1046 }
1047 }
1048 if (S_IS_EXTERNAL (symp))
1049 S_SET_STORAGE_CLASS (symp, C_EXT);
1050 else if (SF_GET_LOCAL (symp))
1051 *punt = 1;
1052 /* more ... */
1053 }
1054
1055 if (set_end != (symbolS *) NULL
1056 && ! *punt)
1057 {
1058 SA_SET_SYM_ENDNDX (set_end, symp);
1059 set_end = NULL;
1060 }
1061
1062 if (coffsymbol (symp->bsym)->lineno)
1063 {
1064 int i, n;
1065 struct line_no *lptr;
1066 alent *l;
1067
1068 lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno;
1069 for (i = 0; lptr; lptr = lptr->next)
1070 i++;
1071 n = i + 1;
1072 lptr = (struct line_no *) coffsymbol (symp->bsym)->lineno;
1073 l = (alent *) bfd_alloc_by_size_t (stdoutput, n * sizeof (alent));
1074 coffsymbol (symp->bsym)->lineno = l;
1075 for (i = n - 1; i > 0; i--)
1076 {
1077 if (lptr->frag)
1078 lptr->l.u.offset += lptr->frag->fr_address;
1079 l[i] = lptr->l;
1080 lptr = lptr->next;
1081 }
1082 }
1083 }
1084
1085 /*
1086 * implement the .section pseudo op:
1087 * .section name {, "flags"}
1088 * ^ ^
1089 * | +--- optional flags: 'b' for bss
1090 * | 'i' for info
1091 * +-- section name 'l' for lib
1092 * 'n' for noload
1093 * 'o' for over
1094 * 'w' for data
1095 * 'd' (apparently m88k for data)
1096 * 'x' for text
1097 * But if the argument is not a quoted string, treat it as a
1098 * subsegment number.
1099 */
1100
1101 void
1102 obj_coff_section (ignore)
1103 int ignore;
1104 {
1105 /* Strip out the section name */
1106 char *section_name;
1107 char c;
1108 char *name;
1109 unsigned int exp;
1110 flagword flags;
1111 asection *sec;
1112
1113 section_name = input_line_pointer;
1114 c = get_symbol_end ();
1115
1116 name = xmalloc (input_line_pointer - section_name + 1);
1117 strcpy (name, section_name);
1118
1119 *input_line_pointer = c;
1120
1121 SKIP_WHITESPACE ();
1122
1123 exp = 0;
1124 flags = SEC_NO_FLAGS;
1125
1126 if (*input_line_pointer == ',')
1127 {
1128 ++input_line_pointer;
1129 SKIP_WHITESPACE ();
1130 if (*input_line_pointer != '"')
1131 exp = get_absolute_expression ();
1132 else
1133 {
1134 ++input_line_pointer;
1135 while (*input_line_pointer != '"'
1136 && ! is_end_of_line[(unsigned char) *input_line_pointer])
1137 {
1138 switch (*input_line_pointer)
1139 {
1140 case 'b': flags |= SEC_ALLOC; flags &=~ SEC_LOAD; break;
1141 case 'n': flags &=~ SEC_LOAD; break;
1142 case 'd':
1143 case 'w': flags &=~ SEC_READONLY; break;
1144 case 'x': flags |= SEC_CODE; break;
1145
1146 case 'i': /* STYP_INFO */
1147 case 'l': /* STYP_LIB */
1148 case 'o': /* STYP_OVER */
1149 as_warn ("unsupported section attribute '%c'",
1150 *input_line_pointer);
1151 break;
1152
1153 default:
1154 as_warn("unknown section attribute '%c'",
1155 *input_line_pointer);
1156 break;
1157 }
1158 ++input_line_pointer;
1159 }
1160 if (*input_line_pointer == '"')
1161 ++input_line_pointer;
1162 }
1163 }
1164
1165 sec = subseg_new (name, (subsegT) exp);
1166
1167 if (flags != SEC_NO_FLAGS)
1168 {
1169 if (! bfd_set_section_flags (stdoutput, sec, flags))
1170 as_warn ("error setting flags for \"%s\": %s",
1171 bfd_section_name (stdoutput, sec),
1172 bfd_errmsg (bfd_get_error ()));
1173 }
1174 }
1175
1176 void
1177 coff_frob_file ()
1178 {
1179 if (symbol_rootP == NULL
1180 || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
1181 {
1182 assert (previous_file_symbol == 0);
1183 c_dot_file_symbol ("fake");
1184 }
1185 }
1186
1187 void
1188 coff_frob_section (strsec)
1189 segT strsec;
1190 {
1191 segT sec;
1192 char *strname, *p;
1193 fragS *fragp;
1194 bfd_vma size, n_entries;
1195
1196 /* @@ these should be in a "stabs.h" file, or maybe as.h */
1197 #ifndef STAB_SECTION_NAME
1198 #define STAB_SECTION_NAME ".stab"
1199 #endif
1200 #ifndef STAB_STRING_SECTION_NAME
1201 #define STAB_STRING_SECTION_NAME ".stabstr"
1202 #endif
1203 if (strcmp (STAB_STRING_SECTION_NAME, strsec->name))
1204 return;
1205
1206 sec = subseg_get (STAB_SECTION_NAME, 0);
1207 /* size is already rounded up, since other section will be listed first */
1208 size = bfd_get_section_size_before_reloc (strsec);
1209
1210 n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1;
1211
1212 /* Find first non-empty frag. It should be large enough. */
1213 fragp = seg_info (sec)->frchainP->frch_root;
1214 while (fragp && fragp->fr_fix == 0)
1215 fragp = fragp->fr_next;
1216 assert (fragp != 0 && fragp->fr_fix >= 12);
1217
1218 /* Store the values. */
1219 p = fragp->fr_literal;
1220 bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
1221 bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
1222 }
1223
1224 void
1225 obj_coff_init_stab_section (seg)
1226 segT seg;
1227 {
1228 char *file;
1229 char *p;
1230 char *stabstr_name;
1231 unsigned int stroff;
1232
1233 /* Make space for this first symbol. */
1234 p = frag_more (12);
1235 /* Zero it out. */
1236 memset (p, 0, 12);
1237 as_where (&file, (unsigned int *) NULL);
1238 stabstr_name = (char *) alloca (strlen (seg->name) + 4);
1239 strcpy (stabstr_name, seg->name);
1240 strcat (stabstr_name, "str");
1241 stroff = get_stab_string_offset (file, stabstr_name);
1242 know (stroff == 1);
1243 md_number_to_chars (p, stroff, 4);
1244 }
1245
1246 #ifdef DEBUG
1247 /* for debugging */
1248 const char *
1249 s_get_name (s)
1250 symbolS *s;
1251 {
1252 return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
1253 }
1254
1255 void
1256 symbol_dump ()
1257 {
1258 symbolS *symbolP;
1259
1260 for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
1261 {
1262 printf("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n",
1263 (unsigned long) symbolP,
1264 S_GET_NAME(symbolP),
1265 (long) S_GET_DATA_TYPE(symbolP),
1266 S_GET_STORAGE_CLASS(symbolP),
1267 (int) S_GET_SEGMENT(symbolP));
1268 }
1269 }
1270
1271 #endif /* DEBUG */
1272
1273 /* end of obj-coff.c */