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