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