xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/obj-coff.c (revision 2718af68c3efc72c9769069b5c7f9ed36f6b9def)
1 /* coff object file format
2    Copyright (C) 1989-2020 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 3, 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 the Free
18    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19    02110-1301, USA.  */
20 
21 #define OBJ_HEADER "obj-coff.h"
22 
23 #include "as.h"
24 #include "safe-ctype.h"
25 #include "subsegs.h"
26 
27 #ifdef TE_PE
28 #include "coff/pe.h"
29 #endif
30 
31 #ifdef OBJ_XCOFF
32 #include "coff/xcoff.h"
33 #endif
34 
35 #define streq(a,b)     (strcmp ((a), (b)) == 0)
36 #define strneq(a,b,n)  (strncmp ((a), (b), (n)) == 0)
37 
38 /* I think this is probably always correct.  */
39 #ifndef KEEP_RELOC_INFO
40 #define KEEP_RELOC_INFO
41 #endif
42 
43 /* obj_coff_section will use this macro to set a new section's
44    attributes when a directive has no valid flags or the "w" flag is
45    used.  This default should be appropriate for most.  */
46 #ifndef TC_COFF_SECTION_DEFAULT_ATTRIBUTES
47 #define TC_COFF_SECTION_DEFAULT_ATTRIBUTES (SEC_LOAD | SEC_DATA)
48 #endif
49 
50 /* This is used to hold the symbol built by a sequence of pseudo-ops
51    from .def and .endef.  */
52 static symbolS *def_symbol_in_progress;
53 #ifdef TE_PE
54 /* PE weak alternate symbols begin with this string.  */
55 static const char weak_altprefix[] = ".weak.";
56 #endif /* TE_PE */
57 
58 #include "obj-coff-seh.c"
59 
60 typedef struct
61   {
62     unsigned long chunk_size;
63     unsigned long element_size;
64     unsigned long size;
65     char *data;
66     unsigned long pointer;
67   }
68 stack;
69 
70 
71 /* Stack stuff.  */
72 
73 static stack *
74 stack_init (unsigned long chunk_size,
75 	    unsigned long element_size)
76 {
77   stack *st;
78 
79   st = XNEW (stack);
80   st->data = XNEWVEC (char, chunk_size);
81   if (!st->data)
82     {
83       free (st);
84       return NULL;
85     }
86   st->pointer = 0;
87   st->size = chunk_size;
88   st->chunk_size = chunk_size;
89   st->element_size = element_size;
90   return st;
91 }
92 
93 static char *
94 stack_push (stack *st, char *element)
95 {
96   if (st->pointer + st->element_size >= st->size)
97     {
98       st->size += st->chunk_size;
99       st->data = XRESIZEVEC (char, st->data, st->size);
100     }
101   memcpy (st->data + st->pointer, element, st->element_size);
102   st->pointer += st->element_size;
103   return st->data + st->pointer;
104 }
105 
106 static char *
107 stack_pop (stack *st)
108 {
109   if (st->pointer < st->element_size)
110     {
111       st->pointer = 0;
112       return NULL;
113     }
114   st->pointer -= st->element_size;
115   return st->data + st->pointer;
116 }
117 
118 /* Maintain a list of the tagnames of the structures.  */
119 
120 static struct hash_control *tag_hash;
121 
122 static void
123 tag_init (void)
124 {
125   tag_hash = hash_new ();
126 }
127 
128 static void
129 tag_insert (const char *name, symbolS *symbolP)
130 {
131   const char *error_string;
132 
133   if ((error_string = hash_jam (tag_hash, name, (char *) symbolP)))
134     as_fatal (_("Inserting \"%s\" into structure table failed: %s"),
135 	      name, error_string);
136 }
137 
138 static symbolS *
139 tag_find (char *name)
140 {
141   return (symbolS *) hash_find (tag_hash, name);
142 }
143 
144 static symbolS *
145 tag_find_or_make (char *name)
146 {
147   symbolS *symbolP;
148 
149   if ((symbolP = tag_find (name)) == NULL)
150     {
151       symbolP = symbol_new (name, undefined_section,
152 			    0, &zero_address_frag);
153 
154       tag_insert (S_GET_NAME (symbolP), symbolP);
155       symbol_table_insert (symbolP);
156     }
157 
158   return symbolP;
159 }
160 
161 /* We accept the .bss directive to set the section for backward
162    compatibility with earlier versions of gas.  */
163 
164 static void
165 obj_coff_bss (int ignore ATTRIBUTE_UNUSED)
166 {
167   if (*input_line_pointer == '\n')
168     subseg_new (".bss", get_absolute_expression ());
169   else
170     s_lcomm (0);
171 }
172 
173 #ifdef TE_PE
174 /* Called from read.c:s_comm after we've parsed .comm symbol, size.
175    Parse a possible alignment value.  */
176 
177 static symbolS *
178 obj_coff_common_parse (int ignore ATTRIBUTE_UNUSED, symbolS *symbolP, addressT size)
179 {
180   addressT align = 0;
181 
182   if (*input_line_pointer == ',')
183     {
184       align = parse_align (0);
185       if (align == (addressT) -1)
186 	return NULL;
187     }
188 
189   S_SET_VALUE (symbolP, size);
190   S_SET_EXTERNAL (symbolP);
191   S_SET_SEGMENT (symbolP, bfd_com_section_ptr);
192 
193   symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
194 
195   /* There is no S_SET_ALIGN (symbolP, align) in COFF/PE.
196      Instead we must add a note to the .drectve section.  */
197   if (align)
198     {
199       segT current_seg = now_seg;
200       subsegT current_subseg = now_subseg;
201       flagword oldflags;
202       asection *sec;
203       size_t pfxlen, numlen;
204       char *frag;
205       char numbuff[20];
206 
207       sec = subseg_new (".drectve", 0);
208       oldflags = bfd_section_flags (sec);
209       if (oldflags == SEC_NO_FLAGS)
210 	{
211 	  if (!bfd_set_section_flags (sec, TC_COFF_SECTION_DEFAULT_ATTRIBUTES))
212 	    as_warn (_("error setting flags for \"%s\": %s"),
213 		bfd_section_name (sec),
214 		bfd_errmsg (bfd_get_error ()));
215 	}
216 
217       /* Emit a string.  Note no NUL-termination.  */
218       pfxlen = strlen (" -aligncomm:") + 2 + strlen (S_GET_NAME (symbolP)) + 1;
219       numlen = snprintf (numbuff, sizeof (numbuff), "%d", (int) align);
220       frag = frag_more (pfxlen + numlen);
221       (void) sprintf (frag, " -aligncomm:\"%s\",", S_GET_NAME (symbolP));
222       memcpy (frag + pfxlen, numbuff, numlen);
223       /* Restore original subseg. */
224       subseg_set (current_seg, current_subseg);
225     }
226 
227   return symbolP;
228 }
229 
230 static void
231 obj_coff_comm (int ignore ATTRIBUTE_UNUSED)
232 {
233   s_comm_internal (ignore, obj_coff_common_parse);
234 }
235 #endif /* TE_PE */
236 
237 /* @@ Ick.  */
238 static segT
239 fetch_coff_debug_section (void)
240 {
241   static segT debug_section;
242 
243   if (!debug_section)
244     {
245       const asymbol *s;
246 
247       s = bfd_make_debug_symbol (stdoutput, NULL, 0);
248       gas_assert (s != 0);
249       debug_section = s->section;
250     }
251   return debug_section;
252 }
253 
254 void
255 SA_SET_SYM_ENDNDX (symbolS *sym, symbolS *val)
256 {
257   combined_entry_type *entry, *p;
258 
259   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
260   p = coffsymbol (symbol_get_bfdsym (val))->native;
261   entry->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = p;
262   entry->fix_end = 1;
263 }
264 
265 static void
266 SA_SET_SYM_TAGNDX (symbolS *sym, symbolS *val)
267 {
268   combined_entry_type *entry, *p;
269 
270   entry = &coffsymbol (symbol_get_bfdsym (sym))->native[1];
271   p = coffsymbol (symbol_get_bfdsym (val))->native;
272   entry->u.auxent.x_sym.x_tagndx.p = p;
273   entry->fix_tag = 1;
274 }
275 
276 static int
277 S_GET_DATA_TYPE (symbolS *sym)
278 {
279   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type;
280 }
281 
282 int
283 S_SET_DATA_TYPE (symbolS *sym, int val)
284 {
285   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_type = val;
286   return val;
287 }
288 
289 int
290 S_GET_STORAGE_CLASS (symbolS *sym)
291 {
292   return coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass;
293 }
294 
295 int
296 S_SET_STORAGE_CLASS (symbolS *sym, int val)
297 {
298   coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_sclass = val;
299   return val;
300 }
301 
302 /* Merge a debug symbol containing debug information into a normal symbol.  */
303 
304 static void
305 c_symbol_merge (symbolS *debug, symbolS *normal)
306 {
307   S_SET_DATA_TYPE (normal, S_GET_DATA_TYPE (debug));
308   S_SET_STORAGE_CLASS (normal, S_GET_STORAGE_CLASS (debug));
309 
310   if (S_GET_NUMBER_AUXILIARY (debug) > S_GET_NUMBER_AUXILIARY (normal))
311     /* Take the most we have.  */
312     S_SET_NUMBER_AUXILIARY (normal, S_GET_NUMBER_AUXILIARY (debug));
313 
314   if (S_GET_NUMBER_AUXILIARY (debug) > 0)
315     /* Move all the auxiliary information.  */
316     memcpy (SYM_AUXINFO (normal), SYM_AUXINFO (debug),
317 	    (S_GET_NUMBER_AUXILIARY (debug)
318 	     * sizeof (*SYM_AUXINFO (debug))));
319 
320   /* Move the debug flags.  */
321   SF_SET_DEBUG_FIELD (normal, SF_GET_DEBUG_FIELD (debug));
322 }
323 
324 void
325 c_dot_file_symbol (const char *filename, int appfile ATTRIBUTE_UNUSED)
326 {
327   symbolS *symbolP;
328 
329   /* BFD converts filename to a .file symbol with an aux entry.  It
330      also handles chaining.  */
331   symbolP = symbol_new (filename, bfd_abs_section_ptr, 0, &zero_address_frag);
332 
333   S_SET_STORAGE_CLASS (symbolP, C_FILE);
334   S_SET_NUMBER_AUXILIARY (symbolP, 1);
335 
336   symbol_get_bfdsym (symbolP)->flags = BSF_DEBUGGING;
337 
338 #ifndef NO_LISTING
339   {
340     extern int listing;
341 
342     if (listing)
343       listing_source_file (filename);
344   }
345 #endif
346 
347   /* Make sure that the symbol is first on the symbol chain.  */
348   if (symbol_rootP != symbolP)
349     {
350       symbol_remove (symbolP, &symbol_rootP, &symbol_lastP);
351       symbol_insert (symbolP, symbol_rootP, &symbol_rootP, &symbol_lastP);
352     }
353 }
354 
355 /* Line number handling.  */
356 
357 struct line_no
358 {
359   struct line_no *next;
360   fragS *frag;
361   alent l;
362 };
363 
364 int coff_line_base;
365 
366 /* Symbol of last function, which we should hang line#s off of.  */
367 static symbolS *line_fsym;
368 
369 #define in_function()		(line_fsym != 0)
370 #define clear_function()	(line_fsym = 0)
371 #define set_function(F)		(line_fsym = (F), coff_add_linesym (F))
372 
373 
374 void
375 coff_obj_symbol_new_hook (symbolS *symbolP)
376 {
377   long   sz = (OBJ_COFF_MAX_AUXENTRIES + 1) * sizeof (combined_entry_type);
378   char * s  = XNEWVEC (char, sz);
379 
380   memset (s, 0, sz);
381   coffsymbol (symbol_get_bfdsym (symbolP))->native = (combined_entry_type *) s;
382   coffsymbol (symbol_get_bfdsym (symbolP))->native->is_sym = TRUE;
383 
384   S_SET_DATA_TYPE (symbolP, T_NULL);
385   S_SET_STORAGE_CLASS (symbolP, 0);
386   S_SET_NUMBER_AUXILIARY (symbolP, 0);
387 
388   if (S_IS_STRING (symbolP))
389     SF_SET_STRING (symbolP);
390 
391   if (S_IS_LOCAL (symbolP))
392     SF_SET_LOCAL (symbolP);
393 }
394 
395 void
396 coff_obj_symbol_clone_hook (symbolS *newsymP, symbolS *orgsymP)
397 {
398   long elts = OBJ_COFF_MAX_AUXENTRIES + 1;
399   combined_entry_type * s = XNEWVEC (combined_entry_type, elts);
400 
401   memcpy (s, coffsymbol (symbol_get_bfdsym (orgsymP))->native,
402 	  elts * sizeof (combined_entry_type));
403   coffsymbol (symbol_get_bfdsym (newsymP))->native = s;
404 
405   SF_SET (newsymP, SF_GET (orgsymP));
406 }
407 
408 
409 /* Handle .ln directives.  */
410 
411 static symbolS *current_lineno_sym;
412 static struct line_no *line_nos;
413 /* FIXME:  Blindly assume all .ln directives will be in the .text section.  */
414 int coff_n_line_nos;
415 
416 static void
417 add_lineno (fragS * frag, addressT offset, int num)
418 {
419   struct line_no * new_line = XNEW (struct line_no);
420 
421   if (!current_lineno_sym)
422     abort ();
423 
424 #ifndef OBJ_XCOFF
425   /* The native aix assembler accepts negative line number.  */
426 
427   if (num <= 0)
428     {
429       /* Zero is used as an end marker in the file.  */
430       as_warn (_("Line numbers must be positive integers\n"));
431       num = 1;
432     }
433 #endif /* OBJ_XCOFF */
434   new_line->next = line_nos;
435   new_line->frag = frag;
436   new_line->l.line_number = num;
437   new_line->l.u.offset = offset;
438   line_nos = new_line;
439   coff_n_line_nos++;
440 }
441 
442 void
443 coff_add_linesym (symbolS *sym)
444 {
445   if (line_nos)
446     {
447       coffsymbol (symbol_get_bfdsym (current_lineno_sym))->lineno =
448 	(alent *) line_nos;
449       coff_n_line_nos++;
450       line_nos = 0;
451     }
452   current_lineno_sym = sym;
453 }
454 
455 static void
456 obj_coff_ln (int appline)
457 {
458   int l;
459 
460   if (! appline && def_symbol_in_progress != NULL)
461     {
462       as_warn (_(".ln pseudo-op inside .def/.endef: ignored."));
463       demand_empty_rest_of_line ();
464       return;
465     }
466 
467   l = get_absolute_expression ();
468 
469   /* If there is no lineno symbol, treat a .ln
470      directive as if it were a .appline directive.  */
471   if (appline || current_lineno_sym == NULL)
472     new_logical_line ((char *) NULL, l - 1);
473   else
474     add_lineno (frag_now, frag_now_fix (), l);
475 
476 #ifndef NO_LISTING
477   {
478     extern int listing;
479 
480     if (listing)
481       {
482 	if (! appline)
483 	  l += coff_line_base - 1;
484 	listing_source_line (l);
485       }
486   }
487 #endif
488 
489   demand_empty_rest_of_line ();
490 }
491 
492 /* .loc is essentially the same as .ln; parse it for assembler
493    compatibility.  */
494 
495 static void
496 obj_coff_loc (int ignore ATTRIBUTE_UNUSED)
497 {
498   int lineno;
499 
500   /* FIXME: Why do we need this check?  We need it for ECOFF, but why
501      do we need it for COFF?  */
502   if (now_seg != text_section)
503     {
504       as_warn (_(".loc outside of .text"));
505       demand_empty_rest_of_line ();
506       return;
507     }
508 
509   if (def_symbol_in_progress != NULL)
510     {
511       as_warn (_(".loc pseudo-op inside .def/.endef: ignored."));
512       demand_empty_rest_of_line ();
513       return;
514     }
515 
516   /* Skip the file number.  */
517   SKIP_WHITESPACE ();
518   get_absolute_expression ();
519   SKIP_WHITESPACE ();
520 
521   lineno = get_absolute_expression ();
522 
523 #ifndef NO_LISTING
524   {
525     extern int listing;
526 
527     if (listing)
528       {
529 	lineno += coff_line_base - 1;
530 	listing_source_line (lineno);
531       }
532   }
533 #endif
534 
535   demand_empty_rest_of_line ();
536 
537   add_lineno (frag_now, frag_now_fix (), lineno);
538 }
539 
540 /* Handle the .ident pseudo-op.  */
541 
542 static void
543 obj_coff_ident (int ignore ATTRIBUTE_UNUSED)
544 {
545   segT current_seg = now_seg;
546   subsegT current_subseg = now_subseg;
547 
548 #ifdef TE_PE
549   {
550     segT sec;
551 
552     /* We could put it in .comment, but that creates an extra section
553        that shouldn't be loaded into memory, which requires linker
554        changes...  For now, until proven otherwise, use .rdata.  */
555     sec = subseg_new (".rdata$zzz", 0);
556     bfd_set_section_flags (sec,
557 			   ((SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA)
558 			    & bfd_applicable_section_flags (stdoutput)));
559   }
560 #else
561   subseg_new (".comment", 0);
562 #endif
563 
564   stringer (8 + 1);
565   subseg_set (current_seg, current_subseg);
566 }
567 
568 /* Handle .def directives.
569 
570    One might ask : why can't we symbol_new if the symbol does not
571    already exist and fill it with debug information.  Because of
572    the C_EFCN special symbol. It would clobber the value of the
573    function symbol before we have a chance to notice that it is
574    a C_EFCN. And a second reason is that the code is more clear this
575    way. (at least I think it is :-).  */
576 
577 #define SKIP_SEMI_COLON()	while (*input_line_pointer++ != ';')
578 #define SKIP_WHITESPACES()	while (*input_line_pointer == ' ' || \
579 				       *input_line_pointer == '\t')  \
580                                   input_line_pointer++;
581 
582 static void
583 obj_coff_def (int what ATTRIBUTE_UNUSED)
584 {
585   char name_end;		/* Char after the end of name.  */
586   char *symbol_name;		/* Name of the debug symbol.  */
587   char *symbol_name_copy;	/* Temporary copy of the name.  */
588 
589   if (def_symbol_in_progress != NULL)
590     {
591       as_warn (_(".def pseudo-op used inside of .def/.endef: ignored."));
592       demand_empty_rest_of_line ();
593       return;
594     }
595 
596   SKIP_WHITESPACES ();
597 
598   name_end = get_symbol_name (&symbol_name);
599   symbol_name_copy = xstrdup (symbol_name);
600 #ifdef tc_canonicalize_symbol_name
601   symbol_name_copy = tc_canonicalize_symbol_name (symbol_name_copy);
602 #endif
603 
604   /* Initialize the new symbol.  */
605   def_symbol_in_progress = symbol_make (symbol_name_copy);
606   symbol_set_frag (def_symbol_in_progress, &zero_address_frag);
607   S_SET_VALUE (def_symbol_in_progress, 0);
608 
609   if (S_IS_STRING (def_symbol_in_progress))
610     SF_SET_STRING (def_symbol_in_progress);
611 
612   (void) restore_line_pointer (name_end);
613 
614   demand_empty_rest_of_line ();
615 }
616 
617 static void
618 obj_coff_endef (int ignore ATTRIBUTE_UNUSED)
619 {
620   symbolS *symbolP = NULL;
621 
622   if (def_symbol_in_progress == NULL)
623     {
624       as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored."));
625       demand_empty_rest_of_line ();
626       return;
627     }
628 
629   /* Set the section number according to storage class.  */
630   switch (S_GET_STORAGE_CLASS (def_symbol_in_progress))
631     {
632     case C_STRTAG:
633     case C_ENTAG:
634     case C_UNTAG:
635       SF_SET_TAG (def_symbol_in_progress);
636       /* Fall through.  */
637     case C_FILE:
638     case C_TPDEF:
639       SF_SET_DEBUG (def_symbol_in_progress);
640       S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ());
641       break;
642 
643     case C_EFCN:
644       SF_SET_LOCAL (def_symbol_in_progress);	/* Do not emit this symbol.  */
645       /* Fall through.  */
646     case C_BLOCK:
647       SF_SET_PROCESS (def_symbol_in_progress);	/* Will need processing before writing.  */
648       /* Fall through.  */
649     case C_FCN:
650       {
651 	const char *name;
652 
653 	S_SET_SEGMENT (def_symbol_in_progress, text_section);
654 
655 	name = S_GET_NAME (def_symbol_in_progress);
656 	if (name[0] == '.' && name[2] == 'f' && name[3] == '\0')
657 	  {
658 	    switch (name[1])
659 	      {
660 	      case 'b':
661 		/* .bf */
662 		if (! in_function ())
663 		  as_warn (_("`%s' symbol without preceding function"), name);
664 		/* Will need relocating.  */
665 		SF_SET_PROCESS (def_symbol_in_progress);
666 		clear_function ();
667 		break;
668 #ifdef TE_PE
669 	      case 'e':
670 		/* .ef */
671 		/* The MS compilers output the actual endline, not the
672 		   function-relative one... we want to match without
673 		   changing the assembler input.  */
674 		SA_SET_SYM_LNNO (def_symbol_in_progress,
675 				 (SA_GET_SYM_LNNO (def_symbol_in_progress)
676 				  + coff_line_base));
677 		break;
678 #endif
679 	      }
680 	  }
681       }
682       break;
683 
684 #ifdef C_AUTOARG
685     case C_AUTOARG:
686 #endif /* C_AUTOARG */
687     case C_AUTO:
688     case C_REG:
689     case C_ARG:
690     case C_REGPARM:
691     case C_FIELD:
692 
693     /* According to the COFF documentation:
694 
695        http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html
696 
697        A special section number (-2) marks symbolic debugging symbols,
698        including structure/union/enumeration tag names, typedefs, and
699        the name of the file. A section number of -1 indicates that the
700        symbol has a value but is not relocatable. Examples of
701        absolute-valued symbols include automatic and register variables,
702        function arguments, and .eos symbols.
703 
704        But from Ian Lance Taylor:
705 
706        http://sources.redhat.com/ml/binutils/2000-08/msg00202.html
707 
708        the actual tools all marked them as section -1. So the GNU COFF
709        assembler follows historical COFF assemblers.
710 
711        However, it causes problems for djgpp
712 
713        http://sources.redhat.com/ml/binutils/2000-08/msg00210.html
714 
715        By defining STRICTCOFF, a COFF port can make the assembler to
716        follow the documented behavior.  */
717 #ifdef STRICTCOFF
718     case C_MOS:
719     case C_MOE:
720     case C_MOU:
721     case C_EOS:
722 #endif
723       SF_SET_DEBUG (def_symbol_in_progress);
724       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
725       break;
726 
727 #ifndef STRICTCOFF
728     case C_MOS:
729     case C_MOE:
730     case C_MOU:
731     case C_EOS:
732       S_SET_SEGMENT (def_symbol_in_progress, absolute_section);
733       break;
734 #endif
735 
736     case C_EXT:
737     case C_WEAKEXT:
738 #ifdef TE_PE
739     case C_NT_WEAK:
740 #endif
741     case C_STAT:
742     case C_LABEL:
743       /* Valid but set somewhere else (s_comm, s_lcomm, colon).  */
744       break;
745 
746     default:
747     case C_USTATIC:
748     case C_EXTDEF:
749     case C_ULABEL:
750       as_warn (_("unexpected storage class %d"),
751 	       S_GET_STORAGE_CLASS (def_symbol_in_progress));
752       break;
753     }
754 
755   /* Now that we have built a debug symbol, try to find if we should
756      merge with an existing symbol or not.  If a symbol is C_EFCN or
757      absolute_section or untagged SEG_DEBUG it never merges.  We also
758      don't merge labels, which are in a different namespace, nor
759      symbols which have not yet been defined since they are typically
760      unique, nor do we merge tags with non-tags.  */
761 
762   /* Two cases for functions.  Either debug followed by definition or
763      definition followed by debug.  For definition first, we will
764      merge the debug symbol into the definition.  For debug first, the
765      lineno entry MUST point to the definition function or else it
766      will point off into space when obj_crawl_symbol_chain() merges
767      the debug symbol into the real symbol.  Therefor, let's presume
768      the debug symbol is a real function reference.  */
769 
770   /* FIXME-SOON If for some reason the definition label/symbol is
771      never seen, this will probably leave an undefined symbol at link
772      time.  */
773 
774   if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
775       || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
776       || (streq (bfd_section_name (S_GET_SEGMENT (def_symbol_in_progress)),
777 		 "*DEBUG*")
778 	  && !SF_GET_TAG (def_symbol_in_progress))
779       || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section
780       || ! symbol_constant_p (def_symbol_in_progress)
781       || (symbolP = symbol_find (S_GET_NAME (def_symbol_in_progress))) == NULL
782       || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP))
783     {
784       /* If it already is at the end of the symbol list, do nothing */
785       if (def_symbol_in_progress != symbol_lastP)
786 	{
787 	  symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
788 	  symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
789 			 &symbol_lastP);
790 	}
791     }
792   else
793     {
794       /* This symbol already exists, merge the newly created symbol
795 	 into the old one.  This is not mandatory. The linker can
796 	 handle duplicate symbols correctly. But I guess that it save
797 	 a *lot* of space if the assembly file defines a lot of
798 	 symbols. [loic]  */
799 
800       /* The debug entry (def_symbol_in_progress) is merged into the
801 	 previous definition.  */
802 
803       c_symbol_merge (def_symbol_in_progress, symbolP);
804       symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
805 
806       def_symbol_in_progress = symbolP;
807 
808       if (SF_GET_FUNCTION (def_symbol_in_progress)
809 	  || SF_GET_TAG (def_symbol_in_progress)
810 	  || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT)
811 	{
812 	  /* For functions, and tags, and static symbols, the symbol
813 	     *must* be where the debug symbol appears.  Move the
814 	     existing symbol to the current place.  */
815 	  /* If it already is at the end of the symbol list, do nothing.  */
816 	  if (def_symbol_in_progress != symbol_lastP)
817 	    {
818 	      symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
819 	      symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
820 	    }
821 	}
822     }
823 
824   if (SF_GET_TAG (def_symbol_in_progress))
825     {
826       symbolS *oldtag;
827 
828       oldtag = symbol_find (S_GET_NAME (def_symbol_in_progress));
829       if (oldtag == NULL || ! SF_GET_TAG (oldtag))
830 	tag_insert (S_GET_NAME (def_symbol_in_progress),
831 		    def_symbol_in_progress);
832     }
833 
834   if (SF_GET_FUNCTION (def_symbol_in_progress))
835     {
836       set_function (def_symbol_in_progress);
837       SF_SET_PROCESS (def_symbol_in_progress);
838 
839       if (symbolP == NULL)
840 	/* That is, if this is the first time we've seen the
841 	   function.  */
842 	symbol_table_insert (def_symbol_in_progress);
843 
844     }
845 
846   def_symbol_in_progress = NULL;
847   demand_empty_rest_of_line ();
848 }
849 
850 static void
851 obj_coff_dim (int ignore ATTRIBUTE_UNUSED)
852 {
853   int d_index;
854 
855   if (def_symbol_in_progress == NULL)
856     {
857       as_warn (_(".dim pseudo-op used outside of .def/.endef: ignored."));
858       demand_empty_rest_of_line ();
859       return;
860     }
861 
862   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
863 
864   for (d_index = 0; d_index < DIMNUM; d_index++)
865     {
866       SKIP_WHITESPACES ();
867       SA_SET_SYM_DIMEN (def_symbol_in_progress, d_index,
868 			get_absolute_expression ());
869 
870       switch (*input_line_pointer)
871 	{
872 	case ',':
873 	  input_line_pointer++;
874 	  break;
875 
876 	default:
877 	  as_warn (_("badly formed .dim directive ignored"));
878 	  /* Fall through.  */
879 	case '\n':
880 	case ';':
881 	  d_index = DIMNUM;
882 	  break;
883 	}
884     }
885 
886   demand_empty_rest_of_line ();
887 }
888 
889 static void
890 obj_coff_line (int ignore ATTRIBUTE_UNUSED)
891 {
892   int this_base;
893 
894   if (def_symbol_in_progress == NULL)
895     {
896       /* Probably stabs-style line?  */
897       obj_coff_ln (0);
898       return;
899     }
900 
901   this_base = get_absolute_expression ();
902   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
903     coff_line_base = this_base;
904 
905   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
906   SA_SET_SYM_LNNO (def_symbol_in_progress, this_base);
907 
908   demand_empty_rest_of_line ();
909 
910 #ifndef NO_LISTING
911   if (streq (".bf", S_GET_NAME (def_symbol_in_progress)))
912     {
913       extern int listing;
914 
915       if (listing)
916 	listing_source_line ((unsigned int) this_base);
917     }
918 #endif
919 }
920 
921 static void
922 obj_coff_size (int ignore ATTRIBUTE_UNUSED)
923 {
924   if (def_symbol_in_progress == NULL)
925     {
926       as_warn (_(".size pseudo-op used outside of .def/.endef: ignored."));
927       demand_empty_rest_of_line ();
928       return;
929     }
930 
931   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
932   SA_SET_SYM_SIZE (def_symbol_in_progress, get_absolute_expression ());
933   demand_empty_rest_of_line ();
934 }
935 
936 static void
937 obj_coff_scl (int ignore ATTRIBUTE_UNUSED)
938 {
939   if (def_symbol_in_progress == NULL)
940     {
941       as_warn (_(".scl pseudo-op used outside of .def/.endef: ignored."));
942       demand_empty_rest_of_line ();
943       return;
944     }
945 
946   S_SET_STORAGE_CLASS (def_symbol_in_progress, get_absolute_expression ());
947   demand_empty_rest_of_line ();
948 }
949 
950 static void
951 obj_coff_tag (int ignore ATTRIBUTE_UNUSED)
952 {
953   char *symbol_name;
954   char name_end;
955 
956   if (def_symbol_in_progress == NULL)
957     {
958       as_warn (_(".tag pseudo-op used outside of .def/.endef: ignored."));
959       demand_empty_rest_of_line ();
960       return;
961     }
962 
963   S_SET_NUMBER_AUXILIARY (def_symbol_in_progress, 1);
964   name_end = get_symbol_name (&symbol_name);
965 
966 #ifdef tc_canonicalize_symbol_name
967   symbol_name = tc_canonicalize_symbol_name (symbol_name);
968 #endif
969 
970   /* Assume that the symbol referred to by .tag is always defined.
971      This was a bad assumption.  I've added find_or_make. xoxorich.  */
972   SA_SET_SYM_TAGNDX (def_symbol_in_progress,
973 		     tag_find_or_make (symbol_name));
974   if (SA_GET_SYM_TAGNDX (def_symbol_in_progress) == 0L)
975     as_warn (_("tag not found for .tag %s"), symbol_name);
976 
977   SF_SET_TAGGED (def_symbol_in_progress);
978 
979   (void) restore_line_pointer (name_end);
980   demand_empty_rest_of_line ();
981 }
982 
983 static void
984 obj_coff_type (int ignore ATTRIBUTE_UNUSED)
985 {
986   if (def_symbol_in_progress == NULL)
987     {
988       as_warn (_(".type pseudo-op used outside of .def/.endef: ignored."));
989       demand_empty_rest_of_line ();
990       return;
991     }
992 
993   S_SET_DATA_TYPE (def_symbol_in_progress, get_absolute_expression ());
994 
995   if (ISFCN (S_GET_DATA_TYPE (def_symbol_in_progress)) &&
996       S_GET_STORAGE_CLASS (def_symbol_in_progress) != C_TPDEF)
997     SF_SET_FUNCTION (def_symbol_in_progress);
998 
999   demand_empty_rest_of_line ();
1000 }
1001 
1002 static void
1003 obj_coff_val (int ignore ATTRIBUTE_UNUSED)
1004 {
1005   if (def_symbol_in_progress == NULL)
1006     {
1007       as_warn (_(".val pseudo-op used outside of .def/.endef: ignored."));
1008       demand_empty_rest_of_line ();
1009       return;
1010     }
1011 
1012   if (is_name_beginner (*input_line_pointer))
1013     {
1014       char *symbol_name;
1015       char name_end = get_symbol_name (&symbol_name);
1016 
1017 #ifdef tc_canonicalize_symbol_name
1018       symbol_name = tc_canonicalize_symbol_name (symbol_name);
1019 #endif
1020       if (streq (symbol_name, "."))
1021 	{
1022 	  /* If the .val is != from the .def (e.g. statics).  */
1023 	  symbol_set_frag (def_symbol_in_progress, frag_now);
1024 	  S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ());
1025 	}
1026       else if (! streq (S_GET_NAME (def_symbol_in_progress), symbol_name))
1027 	{
1028 	  expressionS exp;
1029 
1030 	  exp.X_op = O_symbol;
1031 	  exp.X_add_symbol = symbol_find_or_make (symbol_name);
1032 	  exp.X_op_symbol = NULL;
1033 	  exp.X_add_number = 0;
1034 	  symbol_set_value_expression (def_symbol_in_progress, &exp);
1035 
1036 	  /* If the segment is undefined when the forward reference is
1037 	     resolved, then copy the segment id from the forward
1038 	     symbol.  */
1039 	  SF_SET_GET_SEGMENT (def_symbol_in_progress);
1040 
1041 	  /* FIXME: gcc can generate address expressions here in
1042 	     unusual cases (search for "obscure" in sdbout.c).  We
1043 	     just ignore the offset here, thus generating incorrect
1044 	     debugging information.  We ignore the rest of the line
1045 	     just below.  */
1046 	}
1047       /* Otherwise, it is the name of a non debug symbol and its value
1048          will be calculated later.  */
1049       (void) restore_line_pointer (name_end);
1050     }
1051   else
1052     {
1053       S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ());
1054     }
1055 
1056   demand_empty_rest_of_line ();
1057 }
1058 
1059 #ifdef TE_PE
1060 
1061 /* Return nonzero if name begins with weak alternate symbol prefix.  */
1062 
1063 static int
1064 weak_is_altname (const char * name)
1065 {
1066   return strneq (name, weak_altprefix, sizeof (weak_altprefix) - 1);
1067 }
1068 
1069 /* Return the name of the alternate symbol
1070    name corresponding to a weak symbol's name.  */
1071 
1072 static const char *
1073 weak_name2altname (const char * name)
1074 {
1075   return concat (weak_altprefix, name, (char *) NULL);
1076 }
1077 
1078 /* Return the name of the weak symbol corresponding to an
1079    alternate symbol.  */
1080 
1081 static const char *
1082 weak_altname2name (const char * name)
1083 {
1084   gas_assert (weak_is_altname (name));
1085   return xstrdup (name + 6);
1086 }
1087 
1088 /* Make a weak symbol name unique by
1089    appending the name of an external symbol.  */
1090 
1091 static const char *
1092 weak_uniquify (const char * name)
1093 {
1094   const char * unique = "";
1095 
1096 #ifdef TE_PE
1097   if (an_external_name != NULL)
1098     unique = an_external_name;
1099 #endif
1100   gas_assert (weak_is_altname (name));
1101 
1102   return concat (name, ".", unique, (char *) NULL);
1103 }
1104 
1105 void
1106 pecoff_obj_set_weak_hook (symbolS *symbolP)
1107 {
1108   symbolS *alternateP;
1109 
1110   /* See _Microsoft Portable Executable and Common Object
1111      File Format Specification_, section 5.5.3.
1112      Create a symbol representing the alternate value.
1113      coff_frob_symbol will set the value of this symbol from
1114      the value of the weak symbol itself.  */
1115   S_SET_STORAGE_CLASS (symbolP, C_NT_WEAK);
1116   S_SET_NUMBER_AUXILIARY (symbolP, 1);
1117   SA_SET_SYM_FSIZE (symbolP, IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY);
1118 
1119   alternateP = symbol_find_or_make (weak_name2altname (S_GET_NAME (symbolP)));
1120   S_SET_EXTERNAL (alternateP);
1121   S_SET_STORAGE_CLASS (alternateP, C_NT_WEAK);
1122 
1123   SA_SET_SYM_TAGNDX (symbolP, alternateP);
1124 }
1125 
1126 void
1127 pecoff_obj_clear_weak_hook (symbolS *symbolP)
1128 {
1129   symbolS *alternateP;
1130 
1131   S_SET_STORAGE_CLASS (symbolP, 0);
1132   SA_SET_SYM_FSIZE (symbolP, 0);
1133 
1134   alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP)));
1135   S_CLEAR_EXTERNAL (alternateP);
1136 }
1137 
1138 #endif  /* TE_PE */
1139 
1140 /* Handle .weak.  This is a GNU extension in formats other than PE. */
1141 
1142 static void
1143 obj_coff_weak (int ignore ATTRIBUTE_UNUSED)
1144 {
1145   char *name;
1146   int c;
1147   symbolS *symbolP;
1148 
1149   do
1150     {
1151       c = get_symbol_name (&name);
1152       if (*name == 0)
1153 	{
1154 	  as_warn (_("badly formed .weak directive ignored"));
1155 	  ignore_rest_of_line ();
1156 	  return;
1157 	}
1158       c = 0;
1159       symbolP = symbol_find_or_make (name);
1160       *input_line_pointer = c;
1161       SKIP_WHITESPACE_AFTER_NAME ();
1162       S_SET_WEAK (symbolP);
1163 
1164       if (c == ',')
1165 	{
1166 	  input_line_pointer++;
1167 	  SKIP_WHITESPACE ();
1168 	  if (*input_line_pointer == '\n')
1169 	    c = '\n';
1170 	}
1171 
1172     }
1173   while (c == ',');
1174 
1175   demand_empty_rest_of_line ();
1176 }
1177 
1178 void
1179 coff_obj_read_begin_hook (void)
1180 {
1181   /* These had better be the same.  Usually 18 bytes.  */
1182   know (sizeof (SYMENT) == sizeof (AUXENT));
1183   know (SYMESZ == AUXESZ);
1184   tag_init ();
1185 }
1186 
1187 symbolS *coff_last_function;
1188 #ifndef OBJ_XCOFF
1189 static symbolS *coff_last_bf;
1190 #endif
1191 
1192 void
1193 coff_frob_symbol (symbolS *symp, int *punt)
1194 {
1195   static symbolS *last_tagP;
1196   static stack *block_stack;
1197   static symbolS *set_end;
1198   symbolS *next_set_end = NULL;
1199 
1200   if (symp == &abs_symbol)
1201     {
1202       *punt = 1;
1203       return;
1204     }
1205 
1206   if (current_lineno_sym)
1207     coff_add_linesym (NULL);
1208 
1209   if (!block_stack)
1210     block_stack = stack_init (512, sizeof (symbolS*));
1211 
1212 #ifdef TE_PE
1213   if (S_GET_STORAGE_CLASS (symp) == C_NT_WEAK
1214       && ! S_IS_WEAK (symp)
1215       && weak_is_altname (S_GET_NAME (symp)))
1216     {
1217       /* This is a weak alternate symbol.  All processing of
1218 	 PECOFFweak symbols is done here, through the alternate.  */
1219       symbolS *weakp = symbol_find_noref (weak_altname2name
1220 					  (S_GET_NAME (symp)), 1);
1221 
1222       gas_assert (weakp);
1223       gas_assert (S_GET_NUMBER_AUXILIARY (weakp) == 1);
1224 
1225       if (! S_IS_WEAK (weakp))
1226 	{
1227 	  /* The symbol was turned from weak to strong.  Discard altname.  */
1228 	  *punt = 1;
1229 	  return;
1230 	}
1231       else if (symbol_equated_p (weakp))
1232 	{
1233 	  /* The weak symbol has an alternate specified; symp is unneeded.  */
1234 	  S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
1235 	  SA_SET_SYM_TAGNDX (weakp,
1236 	    symbol_get_value_expression (weakp)->X_add_symbol);
1237 
1238 	  S_CLEAR_EXTERNAL (symp);
1239 	  *punt = 1;
1240 	  return;
1241 	}
1242       else
1243 	{
1244 	  /* The weak symbol has been assigned an alternate value.
1245              Copy this value to symp, and set symp as weakp's alternate.  */
1246 	  if (S_GET_STORAGE_CLASS (weakp) != C_NT_WEAK)
1247 	    {
1248 	      S_SET_STORAGE_CLASS (symp, S_GET_STORAGE_CLASS (weakp));
1249 	      S_SET_STORAGE_CLASS (weakp, C_NT_WEAK);
1250 	    }
1251 
1252 	  if (S_IS_DEFINED (weakp))
1253 	    {
1254 	      /* This is a defined weak symbol.  Copy value information
1255 	         from the weak symbol itself to the alternate symbol.  */
1256 	      symbol_set_value_expression (symp,
1257 					   symbol_get_value_expression (weakp));
1258 	      symbol_set_frag (symp, symbol_get_frag (weakp));
1259 	      S_SET_SEGMENT (symp, S_GET_SEGMENT (weakp));
1260 	    }
1261 	  else
1262 	    {
1263 	      /* This is an undefined weak symbol.
1264 		 Define the alternate symbol to zero.  */
1265 	      S_SET_VALUE (symp, 0);
1266 	      S_SET_SEGMENT (symp, absolute_section);
1267 	    }
1268 
1269 	  S_SET_NAME (symp, weak_uniquify (S_GET_NAME (symp)));
1270 	  S_SET_STORAGE_CLASS (symp, C_EXT);
1271 
1272 	  S_SET_VALUE (weakp, 0);
1273 	  S_SET_SEGMENT (weakp, undefined_section);
1274 	}
1275     }
1276 #else /* TE_PE */
1277   if (S_IS_WEAK (symp))
1278     S_SET_STORAGE_CLASS (symp, C_WEAKEXT);
1279 #endif /* TE_PE */
1280 
1281   if (!S_IS_DEFINED (symp)
1282       && !S_IS_WEAK (symp)
1283       && S_GET_STORAGE_CLASS (symp) != C_STAT)
1284     S_SET_STORAGE_CLASS (symp, C_EXT);
1285 
1286   if (!SF_GET_DEBUG (symp))
1287     {
1288       symbolS * real;
1289 
1290       if (!SF_GET_LOCAL (symp)
1291 	  && !SF_GET_STATICS (symp)
1292 	  && S_GET_STORAGE_CLASS (symp) != C_LABEL
1293 	  && symbol_constant_p (symp)
1294 	  && (real = symbol_find_noref (S_GET_NAME (symp), 1))
1295 	  && S_GET_STORAGE_CLASS (real) == C_NULL
1296 	  && real != symp)
1297 	{
1298 	  c_symbol_merge (symp, real);
1299 	  *punt = 1;
1300 	  return;
1301 	}
1302 
1303       if (!S_IS_DEFINED (symp) && !SF_GET_LOCAL (symp))
1304 	{
1305 	  gas_assert (S_GET_VALUE (symp) == 0);
1306 	  if (S_IS_WEAKREFD (symp))
1307 	    *punt = 1;
1308 	  else
1309 	    S_SET_EXTERNAL (symp);
1310 	}
1311       else if (S_GET_STORAGE_CLASS (symp) == C_NULL)
1312 	{
1313 	  if (S_GET_SEGMENT (symp) == text_section
1314 	      && symp != seg_info (text_section)->sym)
1315 	    S_SET_STORAGE_CLASS (symp, C_LABEL);
1316 	  else
1317 	    S_SET_STORAGE_CLASS (symp, C_STAT);
1318 	}
1319 
1320       if (SF_GET_PROCESS (symp))
1321 	{
1322 	  if (S_GET_STORAGE_CLASS (symp) == C_BLOCK)
1323 	    {
1324 	      if (streq (S_GET_NAME (symp), ".bb"))
1325 		stack_push (block_stack, (char *) &symp);
1326 	      else
1327 		{
1328 		  symbolS *begin;
1329 
1330 		  begin = *(symbolS **) stack_pop (block_stack);
1331 		  if (begin == 0)
1332 		    as_warn (_("mismatched .eb"));
1333 		  else
1334 		    next_set_end = begin;
1335 		}
1336 	    }
1337 
1338 	  if (coff_last_function == 0 && SF_GET_FUNCTION (symp)
1339 	      && S_IS_DEFINED (symp))
1340 	    {
1341 	      union internal_auxent *auxp;
1342 
1343 	      coff_last_function = symp;
1344 	      if (S_GET_NUMBER_AUXILIARY (symp) < 1)
1345 		S_SET_NUMBER_AUXILIARY (symp, 1);
1346 	      auxp = SYM_AUXENT (symp);
1347 	      memset (auxp->x_sym.x_fcnary.x_ary.x_dimen, 0,
1348 		      sizeof (auxp->x_sym.x_fcnary.x_ary.x_dimen));
1349 	    }
1350 
1351 	  if (S_GET_STORAGE_CLASS (symp) == C_EFCN
1352 	      && S_IS_DEFINED (symp))
1353 	    {
1354 	      if (coff_last_function == 0)
1355 		as_fatal (_("C_EFCN symbol for %s out of scope"),
1356 			  S_GET_NAME (symp));
1357 	      SA_SET_SYM_FSIZE (coff_last_function,
1358 				(long) (S_GET_VALUE (symp)
1359 					- S_GET_VALUE (coff_last_function)));
1360 	      next_set_end = coff_last_function;
1361 	      coff_last_function = 0;
1362 	    }
1363 	}
1364 
1365       if (S_IS_EXTERNAL (symp))
1366 	S_SET_STORAGE_CLASS (symp, C_EXT);
1367       else if (SF_GET_LOCAL (symp))
1368 	*punt = 1;
1369 
1370       if (SF_GET_FUNCTION (symp))
1371 	symbol_get_bfdsym (symp)->flags |= BSF_FUNCTION;
1372     }
1373 
1374   /* Double check weak symbols.  */
1375   if (S_IS_WEAK (symp) && S_IS_COMMON (symp))
1376     as_bad (_("Symbol `%s' can not be both weak and common"),
1377 	    S_GET_NAME (symp));
1378 
1379   if (SF_GET_TAG (symp))
1380     last_tagP = symp;
1381   else if (S_GET_STORAGE_CLASS (symp) == C_EOS)
1382     next_set_end = last_tagP;
1383 
1384 #ifdef OBJ_XCOFF
1385   /* This is pretty horrible, but we have to set *punt correctly in
1386      order to call SA_SET_SYM_ENDNDX correctly.  */
1387   if (! symbol_used_in_reloc_p (symp)
1388       && ((symbol_get_bfdsym (symp)->flags & BSF_SECTION_SYM) != 0
1389 	  || (! (S_IS_EXTERNAL (symp) || S_IS_WEAK (symp))
1390 	      && ! symbol_get_tc (symp)->output
1391 	      && S_GET_STORAGE_CLASS (symp) != C_FILE)))
1392     *punt = 1;
1393 #endif
1394 
1395   if (set_end != (symbolS *) NULL
1396       && ! *punt
1397       && ((symbol_get_bfdsym (symp)->flags & BSF_NOT_AT_END) != 0
1398 	  || (S_IS_DEFINED (symp)
1399 	      && ! S_IS_COMMON (symp)
1400 	      && (! S_IS_EXTERNAL (symp) || SF_GET_FUNCTION (symp)))))
1401     {
1402       SA_SET_SYM_ENDNDX (set_end, symp);
1403       set_end = NULL;
1404     }
1405 
1406   if (next_set_end != NULL)
1407     {
1408       if (set_end != NULL)
1409 	as_warn (_("Warning: internal error: forgetting to set endndx of %s"),
1410 		 S_GET_NAME (set_end));
1411       set_end = next_set_end;
1412     }
1413 
1414 #ifndef OBJ_XCOFF
1415   if (! *punt
1416       && S_GET_STORAGE_CLASS (symp) == C_FCN
1417       && streq (S_GET_NAME (symp), ".bf"))
1418     {
1419       if (coff_last_bf != NULL)
1420 	SA_SET_SYM_ENDNDX (coff_last_bf, symp);
1421       coff_last_bf = symp;
1422     }
1423 #endif
1424   if (coffsymbol (symbol_get_bfdsym (symp))->lineno)
1425     {
1426       int i;
1427       struct line_no *lptr;
1428       alent *l;
1429 
1430       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
1431       for (i = 0; lptr; lptr = lptr->next)
1432 	i++;
1433       lptr = (struct line_no *) coffsymbol (symbol_get_bfdsym (symp))->lineno;
1434 
1435       /* We need i entries for line numbers, plus 1 for the first
1436 	 entry which BFD will override, plus 1 for the last zero
1437 	 entry (a marker for BFD).  */
1438       l = XNEWVEC (alent, (i + 2));
1439       coffsymbol (symbol_get_bfdsym (symp))->lineno = l;
1440       l[i + 1].line_number = 0;
1441       l[i + 1].u.sym = NULL;
1442       for (; i > 0; i--)
1443 	{
1444 	  if (lptr->frag)
1445 	    lptr->l.u.offset += lptr->frag->fr_address / OCTETS_PER_BYTE;
1446 	  l[i] = lptr->l;
1447 	  lptr = lptr->next;
1448 	}
1449     }
1450 }
1451 
1452 void
1453 coff_adjust_section_syms (bfd *abfd ATTRIBUTE_UNUSED,
1454 			  asection *sec,
1455 			  void * x ATTRIBUTE_UNUSED)
1456 {
1457   symbolS *secsym;
1458   segment_info_type *seginfo = seg_info (sec);
1459   int nlnno, nrelocs = 0;
1460 
1461   /* RS/6000 gas creates a .debug section manually in ppc_frob_file in
1462      tc-ppc.c.  Do not get confused by it.  */
1463   if (seginfo == NULL)
1464     return;
1465 
1466   if (streq (sec->name, ".text"))
1467     nlnno = coff_n_line_nos;
1468   else
1469     nlnno = 0;
1470   {
1471     /* @@ Hope that none of the fixups expand to more than one reloc
1472        entry...  */
1473     fixS *fixp = seginfo->fix_root;
1474     while (fixp)
1475       {
1476 	if (! fixp->fx_done)
1477 	  nrelocs++;
1478 	fixp = fixp->fx_next;
1479       }
1480   }
1481   if (bfd_section_size (sec) == 0
1482       && nrelocs == 0
1483       && nlnno == 0
1484       && sec != text_section
1485       && sec != data_section
1486       && sec != bss_section)
1487     return;
1488 
1489   secsym = section_symbol (sec);
1490   /* This is an estimate; we'll plug in the real value using
1491      SET_SECTION_RELOCS later */
1492   SA_SET_SCN_NRELOC (secsym, nrelocs);
1493   SA_SET_SCN_NLINNO (secsym, nlnno);
1494 }
1495 
1496 void
1497 coff_frob_file_after_relocs (void)
1498 {
1499   bfd_map_over_sections (stdoutput, coff_adjust_section_syms, NULL);
1500 }
1501 
1502 /* Implement the .section pseudo op:
1503   	.section name {, "flags"}
1504                   ^         ^
1505                   |         +--- optional flags: 'b' for bss
1506                   |                              'i' for info
1507                   +-- section name               'l' for lib
1508                                                  'n' for noload
1509                                                  'o' for over
1510                                                  'w' for data
1511   						 'd' (apparently m88k for data)
1512 						 'e' for exclude
1513                                                  'x' for text
1514   						 'r' for read-only data
1515   						 's' for shared data (PE)
1516 						 'y' for noread
1517 					   '0' - '9' for power-of-two alignment (GNU extension).
1518    But if the argument is not a quoted string, treat it as a
1519    subsegment number.
1520 
1521    Note the 'a' flag is silently ignored.  This allows the same
1522    .section directive to be parsed in both ELF and COFF formats.  */
1523 
1524 void
1525 obj_coff_section (int ignore ATTRIBUTE_UNUSED)
1526 {
1527   /* Strip out the section name.  */
1528   char *section_name;
1529   char c;
1530   int alignment = -1;
1531   char *name;
1532   unsigned int exp;
1533   flagword flags, oldflags;
1534   asection *sec;
1535 
1536   if (flag_mri)
1537     {
1538       char type;
1539 
1540       s_mri_sect (&type);
1541       return;
1542     }
1543 
1544   c = get_symbol_name (&section_name);
1545   name = xmemdup0 (section_name, input_line_pointer - section_name);
1546   *input_line_pointer = c;
1547   SKIP_WHITESPACE_AFTER_NAME ();
1548 
1549   exp = 0;
1550   flags = SEC_NO_FLAGS;
1551 
1552   if (*input_line_pointer == ',')
1553     {
1554       ++input_line_pointer;
1555       SKIP_WHITESPACE ();
1556       if (*input_line_pointer != '"')
1557 	exp = get_absolute_expression ();
1558       else
1559 	{
1560 	  unsigned char attr;
1561 	  int readonly_removed = 0;
1562 	  int load_removed = 0;
1563 
1564 	  while (attr = *++input_line_pointer,
1565 		 attr != '"'
1566 		 && ! is_end_of_line[attr])
1567 	    {
1568 	      if (ISDIGIT (attr))
1569 		{
1570 		  alignment = attr - '0';
1571 		  continue;
1572 		}
1573 	      switch (attr)
1574 		{
1575 		case 'e':
1576 		  /* Exclude section from linking.  */
1577 		  flags |= SEC_EXCLUDE;
1578 		  break;
1579 
1580 		case 'b':
1581 		  /* Uninitialised data section.  */
1582 		  flags |= SEC_ALLOC;
1583 		  flags &=~ SEC_LOAD;
1584 		  break;
1585 
1586 		case 'n':
1587 		  /* Section not loaded.  */
1588 		  flags &=~ SEC_LOAD;
1589 		  flags |= SEC_NEVER_LOAD;
1590 		  load_removed = 1;
1591 		  break;
1592 
1593 		case 's':
1594 		  /* Shared section.  */
1595 		  flags |= SEC_COFF_SHARED;
1596 		  /* Fall through.  */
1597 		case 'd':
1598 		  /* Data section.  */
1599 		  flags |= SEC_DATA;
1600 		  if (! load_removed)
1601 		    flags |= SEC_LOAD;
1602 		  flags &=~ SEC_READONLY;
1603 		  break;
1604 
1605 		case 'w':
1606 		  /* Writable section.  */
1607 		  flags &=~ SEC_READONLY;
1608 		  readonly_removed = 1;
1609 		  break;
1610 
1611 		case 'a':
1612 		  /* Ignore.  Here for compatibility with ELF.  */
1613 		  break;
1614 
1615 		case 'r': /* Read-only section.  Implies a data section.  */
1616 		  readonly_removed = 0;
1617 		  /* Fall through.  */
1618 		case 'x': /* Executable section.  */
1619 		  /* If we are setting the 'x' attribute or if the 'r'
1620 		     attribute is being used to restore the readonly status
1621 		     of a code section (eg "wxr") then set the SEC_CODE flag,
1622 		     otherwise set the SEC_DATA flag.  */
1623 		  flags |= (attr == 'x' || (flags & SEC_CODE) ? SEC_CODE : SEC_DATA);
1624 		  if (! load_removed)
1625 		    flags |= SEC_LOAD;
1626 		  /* Note - the READONLY flag is set here, even for the 'x'
1627 		     attribute in order to be compatible with the MSVC
1628 		     linker.  */
1629 		  if (! readonly_removed)
1630 		    flags |= SEC_READONLY;
1631 		  break;
1632 
1633 		case 'y':
1634 		  flags |= SEC_COFF_NOREAD | SEC_READONLY;
1635 		  break;
1636 
1637 		case 'i': /* STYP_INFO */
1638 		case 'l': /* STYP_LIB */
1639 		case 'o': /* STYP_OVER */
1640 		  as_warn (_("unsupported section attribute '%c'"), attr);
1641 		  break;
1642 
1643 		default:
1644 		  as_warn (_("unknown section attribute '%c'"), attr);
1645 		  break;
1646 		}
1647 	    }
1648 	  if (attr == '"')
1649 	    ++input_line_pointer;
1650 	}
1651     }
1652 
1653   sec = subseg_new (name, (subsegT) exp);
1654 
1655   if (alignment >= 0)
1656     sec->alignment_power = alignment;
1657 
1658   oldflags = bfd_section_flags (sec);
1659   if (oldflags == SEC_NO_FLAGS)
1660     {
1661       /* Set section flags for a new section just created by subseg_new.
1662          Provide a default if no flags were parsed.  */
1663       if (flags == SEC_NO_FLAGS)
1664 	flags = TC_COFF_SECTION_DEFAULT_ATTRIBUTES;
1665 
1666 #ifdef COFF_LONG_SECTION_NAMES
1667       /* Add SEC_LINK_ONCE and SEC_LINK_DUPLICATES_DISCARD to .gnu.linkonce
1668          sections so adjust_reloc_syms in write.c will correctly handle
1669          relocs which refer to non-local symbols in these sections.  */
1670       if (strneq (name, ".gnu.linkonce", sizeof (".gnu.linkonce") - 1))
1671 	flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
1672 #endif
1673 
1674       if (!bfd_set_section_flags (sec, flags))
1675 	as_warn (_("error setting flags for \"%s\": %s"),
1676 		 bfd_section_name (sec),
1677 		 bfd_errmsg (bfd_get_error ()));
1678     }
1679   else if (flags != SEC_NO_FLAGS)
1680     {
1681       /* This section's attributes have already been set.  Warn if the
1682          attributes don't match.  */
1683       flagword matchflags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
1684 			     | SEC_DATA | SEC_COFF_SHARED | SEC_NEVER_LOAD
1685 			     | SEC_COFF_NOREAD);
1686       if ((flags ^ oldflags) & matchflags)
1687 	as_warn (_("Ignoring changed section attributes for %s"), name);
1688     }
1689 
1690   demand_empty_rest_of_line ();
1691 }
1692 
1693 void
1694 coff_adjust_symtab (void)
1695 {
1696   if (symbol_rootP == NULL
1697       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
1698     c_dot_file_symbol ("fake", 0);
1699 }
1700 
1701 void
1702 coff_frob_section (segT sec)
1703 {
1704   segT strsec;
1705   char *p;
1706   fragS *fragp;
1707   bfd_vma n_entries;
1708 
1709   /* The COFF back end in BFD requires that all section sizes be
1710      rounded up to multiples of the corresponding section alignments,
1711      supposedly because standard COFF has no other way of encoding alignment
1712      for sections.  If your COFF flavor has a different way of encoding
1713      section alignment, then skip this step, as TICOFF does.  */
1714   bfd_vma size = bfd_section_size (sec);
1715 #if !defined(TICOFF)
1716   bfd_vma align_power = (bfd_vma) sec->alignment_power + OCTETS_PER_BYTE_POWER;
1717   bfd_vma mask = ((bfd_vma) 1 << align_power) - 1;
1718 
1719   if (size & mask)
1720     {
1721       bfd_vma new_size;
1722       fragS *last;
1723 
1724       new_size = (size + mask) & ~mask;
1725       bfd_set_section_size (sec, new_size);
1726 
1727       /* If the size had to be rounded up, add some padding in
1728          the last non-empty frag.  */
1729       fragp = seg_info (sec)->frchainP->frch_root;
1730       last = seg_info (sec)->frchainP->frch_last;
1731       while (fragp->fr_next != last)
1732 	fragp = fragp->fr_next;
1733       last->fr_address = size;
1734       fragp->fr_offset += new_size - size;
1735     }
1736 #endif
1737 
1738   /* If the section size is non-zero, the section symbol needs an aux
1739      entry associated with it, indicating the size.  We don't know
1740      all the values yet; coff_frob_symbol will fill them in later.  */
1741 #ifndef TICOFF
1742   if (size != 0
1743       || sec == text_section
1744       || sec == data_section
1745       || sec == bss_section)
1746 #endif
1747     {
1748       symbolS *secsym = section_symbol (sec);
1749       unsigned char sclass = C_STAT;
1750 
1751 #ifdef OBJ_XCOFF
1752       if (bfd_section_flags (sec) & SEC_DEBUGGING)
1753         sclass = C_DWARF;
1754 #endif
1755       S_SET_STORAGE_CLASS (secsym, sclass);
1756       S_SET_NUMBER_AUXILIARY (secsym, 1);
1757       SF_SET_STATICS (secsym);
1758       SA_SET_SCN_SCNLEN (secsym, size);
1759     }
1760   /* FIXME: These should be in a "stabs.h" file, or maybe as.h.  */
1761 #ifndef STAB_SECTION_NAME
1762 #define STAB_SECTION_NAME ".stab"
1763 #endif
1764 #ifndef STAB_STRING_SECTION_NAME
1765 #define STAB_STRING_SECTION_NAME ".stabstr"
1766 #endif
1767   if (! streq (STAB_STRING_SECTION_NAME, sec->name))
1768     return;
1769 
1770   strsec = sec;
1771   sec = subseg_get (STAB_SECTION_NAME, 0);
1772   /* size is already rounded up, since other section will be listed first */
1773   size = bfd_section_size (strsec);
1774 
1775   n_entries = bfd_section_size (sec) / 12 - 1;
1776 
1777   /* Find first non-empty frag.  It should be large enough.  */
1778   fragp = seg_info (sec)->frchainP->frch_root;
1779   while (fragp && fragp->fr_fix == 0)
1780     fragp = fragp->fr_next;
1781   gas_assert (fragp != 0 && fragp->fr_fix >= 12);
1782 
1783   /* Store the values.  */
1784   p = fragp->fr_literal;
1785   bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6);
1786   bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);
1787 }
1788 
1789 void
1790 obj_coff_init_stab_section (segT seg)
1791 {
1792   const char *file;
1793   char *p;
1794   char *stabstr_name;
1795   unsigned int stroff;
1796 
1797   /* Make space for this first symbol.  */
1798   p = frag_more (12);
1799   /* Zero it out.  */
1800   memset (p, 0, 12);
1801   file = as_where ((unsigned int *) NULL);
1802   stabstr_name = concat (seg->name, "str", (char *) NULL);
1803   stroff = get_stab_string_offset (file, stabstr_name, TRUE);
1804   know (stroff == 1);
1805   md_number_to_chars (p, stroff, 4);
1806 }
1807 
1808 #ifdef DEBUG
1809 const char * s_get_name (symbolS *);
1810 
1811 const char *
1812 s_get_name (symbolS *s)
1813 {
1814   return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));
1815 }
1816 
1817 void symbol_dump (void);
1818 
1819 void
1820 symbol_dump (void)
1821 {
1822   symbolS *symbolP;
1823 
1824   for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
1825     printf (_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"),
1826 	    (unsigned long) symbolP,
1827 	    S_GET_NAME (symbolP),
1828 	    (long) S_GET_DATA_TYPE (symbolP),
1829 	    S_GET_STORAGE_CLASS (symbolP),
1830 	    (int) S_GET_SEGMENT (symbolP));
1831 }
1832 
1833 #endif /* DEBUG */
1834 
1835 const pseudo_typeS coff_pseudo_table[] =
1836 {
1837   {"ABORT", s_abort, 0},
1838   {"appline", obj_coff_ln, 1},
1839   /* We accept the .bss directive for backward compatibility with
1840      earlier versions of gas.  */
1841   {"bss", obj_coff_bss, 0},
1842 #ifdef TE_PE
1843   /* PE provides an enhanced version of .comm with alignment.  */
1844   {"comm", obj_coff_comm, 0},
1845 #endif /* TE_PE */
1846   {"def", obj_coff_def, 0},
1847   {"dim", obj_coff_dim, 0},
1848   {"endef", obj_coff_endef, 0},
1849   {"ident", obj_coff_ident, 0},
1850   {"line", obj_coff_line, 0},
1851   {"ln", obj_coff_ln, 0},
1852   {"scl", obj_coff_scl, 0},
1853   {"sect", obj_coff_section, 0},
1854   {"sect.s", obj_coff_section, 0},
1855   {"section", obj_coff_section, 0},
1856   {"section.s", obj_coff_section, 0},
1857   /* FIXME: We ignore the MRI short attribute.  */
1858   {"size", obj_coff_size, 0},
1859   {"tag", obj_coff_tag, 0},
1860   {"type", obj_coff_type, 0},
1861   {"val", obj_coff_val, 0},
1862   {"version", s_ignore, 0},
1863   {"loc", obj_coff_loc, 0},
1864   {"optim", s_ignore, 0},	/* For sun386i cc (?) */
1865   {"weak", obj_coff_weak, 0},
1866 #if defined TC_TIC4X
1867   /* The tic4x uses sdef instead of def.  */
1868   {"sdef", obj_coff_def, 0},
1869 #endif
1870 #if defined(SEH_CMDS)
1871   SEH_CMDS
1872 #endif
1873   {NULL, NULL, 0}
1874 };
1875 
1876 
1877 /* Support for a COFF emulation.  */
1878 
1879 static void
1880 coff_pop_insert (void)
1881 {
1882   pop_insert (coff_pseudo_table);
1883 }
1884 
1885 static int
1886 coff_separate_stab_sections (void)
1887 {
1888   return 1;
1889 }
1890 
1891 const struct format_ops coff_format_ops =
1892 {
1893   bfd_target_coff_flavour,
1894   0,	/* dfl_leading_underscore */
1895   1,	/* emit_section_symbols */
1896   0,    /* begin */
1897   c_dot_file_symbol,
1898   coff_frob_symbol,
1899   0,	/* frob_file */
1900   0,	/* frob_file_before_adjust */
1901   0,	/* frob_file_before_fix */
1902   coff_frob_file_after_relocs,
1903   0,	/* s_get_size */
1904   0,	/* s_set_size */
1905   0,	/* s_get_align */
1906   0,	/* s_set_align */
1907   0,	/* s_get_other */
1908   0,	/* s_set_other */
1909   0,	/* s_get_desc */
1910   0,	/* s_set_desc */
1911   0,	/* s_get_type */
1912   0,	/* s_set_type */
1913   0,	/* copy_symbol_attributes */
1914   0,	/* generate_asm_lineno */
1915   0,	/* process_stab */
1916   coff_separate_stab_sections,
1917   obj_coff_init_stab_section,
1918   0,	/* sec_sym_ok_for_reloc */
1919   coff_pop_insert,
1920   0,	/* ecoff_set_ext */
1921   coff_obj_read_begin_hook,
1922   coff_obj_symbol_new_hook,
1923   coff_obj_symbol_clone_hook,
1924   coff_adjust_symtab
1925 };
1926