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