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