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